7

I am overriding the /usr/lib/systemd/system/docker.service start-up script to extend it with an environment file. I have defined my configuration file at /etc/systemd/system/docker.service.d/docker.conf like so:

test -d /etc/systemd/system/docker.service.d || \
    mkdir /etc/systemd/system/docker.service.d

cat > /etc/systemd/system/docker.service.d/docker.conf <<EOF
[Service]
EnvironmentFile=/etc/sysconfig/docker
ExecStartPre=-/usr/local/sbin/generate-docker-config
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --dns=\${LOCAL_IPV4}
EOF

systemctl daemon-reload

I'm running the above script as a Packer build step for an AMI.

When I launch my AMI, I see the following status output about the Docker service from SystemD:

● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─docker.conf
   Active: active (running) since Mon 2016-03-28 21:16:11 UTC; 6min ago
     Docs: https://docs.docker.com
 Main PID: 858 (docker)
   CGroup: /system.slice/docker.service
           ├─ 858 /usr/bin/docker daemon -H fd:// --dns=10.224.4.178 --log-driver=syslog --log-opt tag={{.ImageName}}

It hasn't run my ExecStartPre, as seen in the output. If I do the following, I do see that it has now run the startup script:

# systemctl daemon-reload && systemctl restart docker.service && \
    systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─docker.conf
   Active: active (running) since Mon 2016-03-28 22:05:24 UTC; 24ms ago
     Docs: https://docs.docker.com
  Process: 1873 ExecStartPre=/usr/local/sbin/generate-docker-config (code=exited, status=0/SUCCESS)
 Main PID: 1876 (docker)
   CGroup: /system.slice/docker.service
           └─1876 /usr/bin/docker daemon -H fd:// --dns=10.224.4.178 --log-driver=syslog --log-opt tag={{.ImageName}}

Notice how it now has the ExecStartPre in the status output?

Is there a command I should be running in my Packer build in addition to daemon-reload to cause SystemD to load and run the new service configuration file and ExecStartPre script? Should I just restart the service in the Packer build, or is there a better, more tailored solution to the problem?

NOTE: My ExecStartPre script needs the network available to curl for EC2 instance tags. The Docker service file does specify After=network.target docker.socket so I'm assuming it will run after networking has started.

1

Well, this is the expected behavior. If you intend to restart the docker service just after overriding the docker unit file, you are supposed to invoke systemctl restart docker.service after systemctl daemon-reload in the script. If you also wants to restart docket only if it is already running, invoke systemctl try-restart docker.service instead.

The purpose of systemctl daemon-reload commands is to tell systemd daemon to reload all its configuration, reload units files and regenerate the service dependency tree. However, it doesn't affect any other service in the system, even though unit files are changed on disk.

  • 1
    The unexpected part of the behavior is that when I restart the system, it doesn't load in the ExecStartPre. The Packer EC2 instance is shut down, and then the next time it is launched is as an AMI for a new EC2 instance, and the problem is that during this phase, it doesn't call the script. – Naftuli Kay Mar 28 '16 at 23:59
  • Then, I am afraid I couldn't help you with the issue. I know how to manage services with systemd, but I don't know how to deal with Amazon compute clouds. The only possible cause I figure is that the script doesn't restart docker.service after overriding its unit file and it should do. – Anderson M. Gomes Mar 29 '16 at 0:40
1

Assuming the network is 'online' after network.service isn't 100% reliable. That's why there's a network-online.target.

If you're relying on curl and want to be absolutely sure the network is up before the service starts, DNS works, etc. then adding this to your docker.conf might help ...

[Unit]
After=network-online.target

... and since you're doing all this post boot, for the new ExecStartPre to work, then you should add either systemctl daemon-reload && systemctl restart docker.service or systemctl stop docker.service && systemctl daemon-reload && systemctl start docker.service in your Packer build script. The latter is most reliable.

Stopping a service before it's modified and daemon-reload is done will ensure the entire unit is reloaded as specified. I can see in the third bit of output you've provided that the ExecStart for docker.service does not contain the arguments you've specified in the Packer build script. That's because of the systemctl restart docker.service (versus stop, daemon-reload, & start).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.