1
0
mirror of /repos/baseimage-docker.git synced 2025-12-30 08:01:31 +01:00

Allow running scripts during startup.

This commit is contained in:
Hongli Lai (Phusion) 2014-01-31 15:44:50 +01:00
parent 2ac41ee8ab
commit 62859010cb
No known key found for this signature in database
GPG Key ID: 06A131094B6F4332
3 changed files with 76 additions and 4 deletions

View File

@ -1,6 +1,7 @@
## 0.9.3 (release date: pending) ## 0.9.3 (release date: pending)
* It looks like Docker changed their Ubuntu 12.04 base image, thereby breaking our Dockerfile. This has been fixed. * It looks like Docker changed their Ubuntu 12.04 base image, thereby breaking our Dockerfile. This has been fixed.
* The init system (`/sbin/my_init`) now supports running scripts during startup. You can put startup scripts `/etc/my_init.d`. `/etc/rc.local` is also run during startup.
## 0.9.2 (release date: 2013-12-11) ## 0.9.2 (release date: 2013-12-11)

View File

@ -101,6 +101,25 @@ Here's an example showing you how to a memached server runit entry can be made.
Note that the shell script must run the daemon **without letting it daemonize/fork it**. Usually, daemons provide a command line flag or a config file option for that. Note that the shell script must run the daemon **without letting it daemonize/fork it**. Usually, daemons provide a command line flag or a config file option for that.
### Running scripts during container startup
The baseimage-docker init system, `/sbin/my_init`, runs the following scripts during startup, in the following order:
* All executable scripts in `/etc/my_init.d`, if this directory exists. The scripts are run during in lexicographic order.
* The script `/etc/rc.local`, if this file exists.
All scripts must exit correctly, e.g. with exit code 0. If any script exits with a non-zero exit code, the booting will fail.
The following example shows how you can add a startup script. This script simply logs the time of boot to the file /tmp/boottime.txt.
### In logtime.sh (make sure this file is chmod +x):
#!/bin/sh
date > /tmp/boottime.txt
### In Dockerfile:
RUN mkdir -p /etc/my_init.d
ADD logtime.sh /etc/my_init.d/logtime.sh
### Login to the container ### Login to the container
You can use SSH to login to any container that is based on baseimage-docker. You can use SSH to login to any container that is based on baseimage-docker.

View File

@ -1,5 +1,24 @@
#!/usr/bin/python2 #!/usr/bin/python2
import os, sys, signal, errno import os, sys, stat, signal, errno
pid = None
status = None
def listdir(path):
try:
result = os.stat(path)
except OSError:
return []
if stat.S_ISDIR(result.st_mode):
return sorted(os.listdir(path))
else:
return []
def is_exe(path):
try:
return os.path.isfile(path) and os.access(path, os.X_OK)
except OSError:
return False
def reap_child(signum, frame): def reap_child(signum, frame):
global pid, status, waiting_for_runit global pid, status, waiting_for_runit
@ -10,20 +29,52 @@ def reap_child(signum, frame):
except OSError: except OSError:
pass pass
def stop_runit(signum, frame): def stop_child_process(name):
global pid global pid
print("*** Shutting down runit (PID %d)..." % pid) print("*** Shutting down %s (PID %d)..." % (name, pid))
try: try:
os.kill(pid, signal.SIGHUP) os.kill(pid, signal.SIGHUP)
except OSError: except OSError:
pass pass
def run_command_killable(*argv):
global pid
filename = argv[0]
pid = os.spawnvp(os.P_NOWAIT, filename, argv)
signal.signal(signal.SIGINT, lambda signum, frame: stop_child_process(filename))
signal.signal(signal.SIGTERM, lambda signum, frame: stop_child_process(filename))
try:
this_pid, status = os.waitpid(pid, 0)
except OSError as e:
if e.errno == errno.EINTR:
sys.exit(2)
else:
raise
finally:
signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGTERM, signal.SIG_DFL)
if status != 0:
sys.stderr.write("*** %s failed with exit code %d\n" % (filename, status))
sys.exit(1)
# Run /etc/my_init.d/*
for name in listdir("/etc/my_init.d"):
filename = "/etc/my_init.d/" + name
if is_exe(filename):
print("*** Running %s..." % filename)
run_command_killable(filename)
# Run /etc/rc.local.
if is_exe("/etc/rc.local"):
print("*** Running /etc/rc.local...")
run_command_killable("/etc/rc.local")
# Start runit. # Start runit.
signal.signal(signal.SIGCHLD, reap_child) signal.signal(signal.SIGCHLD, reap_child)
print("*** Booting runit...") print("*** Booting runit...")
pid = os.spawnl(os.P_NOWAIT, "/usr/sbin/runsvdir-start", "/usr/sbin/runsvdir-start") pid = os.spawnl(os.P_NOWAIT, "/usr/sbin/runsvdir-start", "/usr/sbin/runsvdir-start")
print("*** Runit started as PID %d" % pid) print("*** Runit started as PID %d" % pid)
signal.signal(signal.SIGTERM, stop_runit) signal.signal(signal.SIGTERM, lambda signum, frame: stop_child_process("runit"))
# Wait for runit, and while waiting, reap any adopted orphans. # Wait for runit, and while waiting, reap any adopted orphans.
done = False done = False
@ -62,3 +113,4 @@ while not done:
if not done: if not done:
time.sleep(0.5) time.sleep(0.5)
shutdown() shutdown()