Search code examples
linuxdockerunixservicesystemctl

How can I start docker.service after nslcd.service?


All my unix host use the ldap backend.

docker group is existing on the ldap, this is also why docker.service must start after nslcd.service.

I have tried to edit systemctl startup configuration for docker.service:

$ sudo systemctl edit --full docker.service

And I add nslcd.service to After, Wants, Requires:

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service nslcd.service
Wants=network-online.target nslcd.service
Requires=docker.socket nslcd.service

I still can't get docker to run after that service:

sudo service docker status
● docker.service - Docker Application Container Engine
   Loaded: loaded (/etc/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: https://docs.docker.com

Oct 10 19:35:02 dev-08 systemd[1]: Dependency failed for Docker Application Container Engine.

There is no problem to start container manually after starts, since I login through ldap.


Solution

  • docker group is existing on the ldap, this is also why docker.service must start after nslcd.service.

    It is generally a bad idea to have system services depend on users and groups in a remote directory service (because problems with the directory service can impact service availability on your host).

    And I add nslcd.service to After, Wants, Requires

    Specifying both a Wants= and a Requires= relationship is redundant. The Requires= relationship is simply a stronger version of Wants=: using Requires= means that if you start the docker service, and nslcd is not already running, it will be started as well. Using Wants= in the same situation, docker would start without starting nslcd.

    I still can't get docker to run after that service

    Is is entirely likely that nslcd takes a moment to connect to the directory service. In this case, it's possible that the process has started, which satisfies the After= dependency, so docker starts even though your groups are not yet available.

    There are a few ways of addressing this situation:

    1. In light of my initial comment, just create a local docker group. This is by far the simplest and most robust solution.

    2. Create a new oneshot unit that spins until the docker group exists. Make this unit depend on nslcd, and make docker depend on the new unit.

    3. Possibly replacing nslcd with something that implements local caching (e.g., sssd) would also resolve this problem.

    On a different note, it is a bad idea to directly edit the unit files as you have done in this example, because if you've installed Docker via packaging tools (apt/yum/etc), your modifications will be overwritten next time you upgrade the package. A better solution is to create drop-in files to augment the unit configuration.

    Update

    Option 2 might look like this:

    [Unit]
    Requires=nslcd.service docker.service
    After=nslcd.service
    Before=docker.service
    
    [Service]
    Type=oneshot
    ExecStart=/bin/sh -c "while ! getent group docker; do sleep 1; done"