How can I get an upstart script to properly manage running a docker image?
Asked Answered
A

5

12

I have a local docker-registry that I'd like to manage with upstart.

I have the following script (in /etc/init/docker-registry.conf):

description "docker registry" 
author "me" 
start on filesystem and started docker 
stop on runlevel [!2345] 
respawn 
script
    /usr/bin/docker.io run -a stdout --rm --name=docker-registry \
    -v /var/local/docker-registry:/var/local/docker-registry \
    -p 5000:5000 mysite:5000/docker-registry
end script

I can start my docker registry fine with:

sudo start docker-registry

Response: docker-registry start/running, process 8620

Check to confirm its running?

sudo status docker-registry

Response: docker-registry start/running, process 8620

Trying to stop it with:

sudo stop docker-registry

Response: docker-registry stop/waiting

However, it doesn't actually stop. The process is still alive, the container is running, and it's still functioning perfectly


It does stop perfectly with:

docker stop docker-registry

I've tried adding this to the upstart script:

post-stop script
    docker stop docker-registry
end script

But it just returns: stop: Job failed while stopping

Angio answered 1/6, 2014 at 17:47 Comment(0)
C
8

This worked for me:

description "container foo"
author "me"
start on filesystem and started docker
stop on runlevel [!2345]
respawn
script
  /usr/bin/docker start -a foo
end script
pre-stop script
  /usr/bin/docker stop foo
end script

I'm assuming the official Docker docs only care about the automatic starting part. The actual PID output by upstart differs from the actual docker process PID, and I suspect this causes some mismatch when stopping:

sudo service foo-docker start
foo-docker start/running, process 30313

What is this process? It looks like it's how Docker launched the container:

ps -p 30386 -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     30386     1  0 14:48 ?        00:00:00 /bin/sh -e -c /usr/bin/docker start -a foo  /bin/sh

The PID of the actual command running inside the container is a different one:

pidof foo
30400

And killing the docker PID, as I guess the service foo-docker stop does, does not kill the container (or the command running within it):

sudo kill 30386 # or sudo service foo-docker stop
#30400 is still running
Concepcionconcept answered 24/11, 2014 at 15:56 Comment(0)
L
3

Try prefixing the docker run line with exec. This will cause the docker container to run within the context of the shell script rather then the shell forking it. As a result, the docker run binary will receive the signals and clean itself up.

For example I have the following:

description "Docker container for OpenVPN server"
start on filesystem and started docker
stop on runlevel [!2345]
respawn
script
  exec docker run --volumes-from ovpn-data --rm -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn
end script

And running start docker-openvpn and stop docker-openvpn works as expected (--rm is honored as well).

Tested on Docker version 1.4.0, build 4595d4f on Ubuntu 14.04.

If it doesn't work, consider updating to use the upstream docker apt repo:

   curl https://get.docker.io/gpg | sudo apt-key add -
   echo deb http://get.docker.io/ubuntu docker main | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update && sudo apt-get install -y lxc-docker
Luane answered 15/12, 2014 at 1:40 Comment(0)
S
0

No need to call docker stop here Upstart's stop command will send the SIGTERM signal to the container which is the same thing.

There may be an issue with getting --rm to work here, though. There is an open issue on Github about it

Ser answered 14/6, 2014 at 4:33 Comment(1)
Apparently, it isn't the same thing. I removed the --rm, and upstart still fails to stop my container. docker stop docker-registry still works though.Angio
P
0

To make your pre-stop script work, just add "rm" to clean up the named container, so:

...
...
pre-stop script
  /usr/bin/docker stop [container name]
  /usr/bin/docker rm   [container name]
end script

You can also avoid having to start (as in "docker start" vs "docker run") a container in this case as well (start only works if you already did a run and stop). So your start script looks like:

...
script
   /usr/bin/docker rm [container name] | true
   /usr/bin/docker run [-v vol:vol] [-p port:port] --name=[container name] [docker tag]
end script

For this to work, you'll need to run with --name, or stop can't find your container. If you really want to start -a, you can run, stop, start in your startup script.

Complete example:

description "storm supervisor docker container"
author "[email protected]"

start on filesystem and started docker
stop on runlevel [!2345]
respawn
script
        /usr/bin/docker rm storm-supervisor | true
        /usr/bin/docker run --name="storm-supervisor" -v /var/log/docker-storm-supervisor:/var/log -p 6700:6700 -p 6701:6701  -p 6702:6702 -p 6703:6703 -p 6704:6704 -p 6705:6705 -p 6706:6706 tycoon/storm-supervisor
end script

pre-stop script
        /usr/bin/docker stop storm-supervisor
        /usr/bin/docker rm storm-supervisor
end script
Pedrick answered 16/4, 2015 at 23:31 Comment(1)
You want to use ||, not |, right? Otherwise you're just piping the output of the Docker command to true, when really you want the OR operator to return success from the Docker command or the true command.Youngman
G
-2

You can use --restart=always when starting docker-registry, i.e.

docker run -d --restart=always docker-registry

This way the image will automatically restart together with a machine restart, just like upstart.

More information on restart policies here

Grainy answered 29/1, 2015 at 10:4 Comment(3)
Output from command: flag provided but not defined: --restart Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]Twowheeler
--restart is part of docker run not startBoothman
Using two process managers such as docker built-in restart flag and upstart is not recommendedBascom

© 2022 - 2024 — McMap. All rights reserved.