gentoo-syslog/Dockerfile.template: Add tail-syslog (and other tweaks)
authorW. Trevor King <wking@tremily.us>
Wed, 12 Mar 2014 18:46:03 +0000 (11:46 -0700)
committerW. Trevor King <wking@tremily.us>
Wed, 12 Mar 2014 19:05:27 +0000 (12:05 -0700)
The main change here is a new tail-syslog script that traps SIGTERM
and shuts down running OpenRC processes (using 'rc shutdown').  This
gives us clean shutdowns for 'docker stop' and friends, which makes
'docker restart' and host reboots more reliable.

The tail-syslog script is not the most elegant solution.  In fact,
rc(8) suggests:

  There are some special runlevels that you should be aware of:
  ...
  shutdown  Changes to the shutdown runlevel and then halts the host.

  You should not call any of these runlevels yourself.  Instead you
  should use init(8) and shutdown(8) and let them call these special
  runlevels.

Indead, using 'CMD /sbin/init' seems to work fine, but I can't figure
out how to get the logs out via 'docker logs'.  I tried a number of
things, including

  RUN sed -i 's|^\([^#].*/sbin/agetty.*\)|#\1|' /etc/inittab
  RUN echo 'log1:12345:respawn:/usr/bin/tail -F /var/log/messages >/dev/console' >> /etc/inittab

but none of my attempts along those lines worked.

You could work around this by volume-mounting a host directory to the
container's /var/log, or by configuring syslog-ng to forward logs to a
remote destination with something like:

  RUN sed -i 's/^\(destination messages\).*;$/\1 { tcp("logs.example.net" port(514) };/' /etc/syslog-ng/syslog-ng.conf

But we don't have a central syslog instance to forward to, and I like
'docker logs' ;).

So that nixed the /sbin/init approach, and I started looking at signal
trapping in a shell script [1].  When I tried to use 'shutdown -h now'
in place of 'rc shutdown', I got log messages like:

  Mar 12 18:29:14 f50a7b4bd8c9 logger: trapped SIGTERM, shutting down
  Mar 12 18:29:14 f50a7b4bd8c9 shutdown[272]: shutting down for system halt
  shutdown: /dev/initctl: No such file or directory
  init: /dev/initctl: No such file or directory

because /sbin/init (which creates /dev/initctl) was not running).
Using 'rc shutdown' directly avoids that problem.

Also in this commit:
* Add an initial ^ to the console_all sed line, which just makes
  explicit the fact that I'm matching from the beginning of the line.
* Enable boot logging to /var/log/rc.log, in case someone actually
  does run /sbin/init.

[1]: 'trap' is in POSIX.1-2008 (IEEE Std 1003.1, 2013 Edition)
     http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_28

gentoo-syslog/Dockerfile.template
gentoo-syslog/tail-syslog.sh [new file with mode: 0755]

index 7f5ee2545514cbaf2c07e97f8d135de71ff91e44..193ea93ae02623feb382d127cfc817e0d2443a2d 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 W. Trevor King <wking@tremily.us>
+# Copyright (C) 2013-2014 W. Trevor King <wking@tremily.us>
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,12 @@ MAINTAINER ${MAINTAINER}
 RUN emerge -v sys-process/vixie-cron app-admin/syslog-ng app-admin/logrotate
 RUN rc-update add syslog-ng default
 RUN rc-update add vixie-cron default
+ADD tail-syslog.sh /usr/bin/tail-syslog
 
 # Disable logging to tty12
-RUN sed -i 's/\([^#].*console_all.*\)/#\1/' /etc/syslog-ng/syslog-ng.conf
+RUN sed -i 's/^\([^#].*console_all.*\)/#\1/' /etc/syslog-ng/syslog-ng.conf
+
+# Log boot process to /var/log/rc.log
+RUN sed -i 's/^#\(rc_logger="YES"\)$/\1/' /etc/rc.conf
+
+CMD rc default && exec tail-syslog
diff --git a/gentoo-syslog/tail-syslog.sh b/gentoo-syslog/tail-syslog.sh
new file mode 100755 (executable)
index 0000000..0729a04
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Copyright (C) 2014 W. Trevor King <wking@tremily.us>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Tail syslog, trapping SIGTERM to trigger a clean container shutdown
+
+tail -F /var/log/messages &
+pid="$!"
+
+trap "
+       trap '' TERM;
+       logger 'trapped SIGTERM, shutting down';
+       rc shutdown;
+       kill '${pid}';
+       wait '${pid}';
+       exit
+       " TERM
+
+wait "${pid}"