Skip to content

Not missing init Containers with Docker Swarm

Kubernetes has the concept of init containers. This does not exist in Docker Swarm, and the depends_on is ignored when deploying to a swarm. There are situation when the init containers are convenient, but in my Docker Swarm usage this doesn’t seem to cause trouble: before I discovered that depends_on is a no-op when deploying to a Swarm, I used it to (I thought) simulate init containers! Let’s see my usage scenario.

When deploying an app on Docker Swarm, I prefer to persist data on the host server’s filesystem rather than in a docker volume, having read that the latter already caused trouble when updating docker itself. As a consequence, I mount the host’s /containers_data/$app_name inside the container at /app_data. However, I don’t want to log in on the server and create the directory manually, I want everything to be present in the compose file I’m deploying to the Docker Swarm.

The solution is easy. For an example, let’s look at an openldap container deployed in a Swarm stack. I need to add the directory /containers_data/openldap and change the owner to 1001.

To this end I add a container (that I name init) in the compose file:

  init:
    command:
      - bash
      - -c
      - mkdir -p /data/openldap ; chown 1001:1001 /data/openldap
    image: ubuntu:latest
    user: root
    volumes:
      - /containers_data:/data

The openldap container mounts the host directory /containers_data/openldap:

  openldap:
    image: bitnami/openldap:2.6.3
    volumes:
      - "/containers_data/openldap:/bitnami/openldap"

I initially put a key depends_on: init thinking it would delay the start of the openldap container. It did nothing actually. If the openldap started before the needed directory was created, it would be restarted until the directory was available. To be sure, let’s check below if that’s really what happens.

I deploy a stack with the init container and a depend_on entry in the openldap container:

version: "3.8"
services:
  init:
    command:
      - bash
      - -c
      - mkdir -p /data/test_container; sleep 10; chown 1001:1001 /data/test_container
    image: ubuntu:latest
    user: root
    volumes:
      - /data:/data
  openldap:
    image: bitnami/openldap:2.6.3
    depends_on: [ init ]
    volumes:
      - "/data/test_container:/bitnami/openldap"

The init container immediately creates the directory mounted by the openldap container (otherwise we would end up with an invalid mount config and the openldap container would not even start) but it waits for 10 seconds before setting the right owner. If depends_on were effective, the openldap container would would not start before the correct owner was set. But this is not the case:

$ docker service logs test_openldap
test_openldap.1.iug8upss0kqc@vmi764857    |  09:46:24.12 INFO  ==> ** Starting LDAP setup **
test_openldap.1.iug8upss0kqc@vmi764857    |  09:46:24.18 INFO  ==> Validating settings in LDAP_* env vars
test_openldap.1.iug8upss0kqc@vmi764857    |  09:46:24.20 INFO  ==> Initializing OpenLDAP...
test_openldap.1.iug8upss0kqc@vmi764857    | mkdir: cannot create directory '/bitnami/openldap/data': Permission denied
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:39.78 INFO  ==> ** Starting LDAP setup **
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:39.82 INFO  ==> Validating settings in LDAP_* env vars
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:39.83 INFO  ==> Initializing OpenLDAP...
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:39.86 INFO  ==> Creating LDAP online configuration
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:39.91 INFO  ==> Starting OpenLDAP server in background
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:40.93 INFO  ==> Configure LDAP credentials for admin user
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:40.96 INFO  ==> Adding LDAP extra schemas
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:41.02 INFO  ==> Creating LDAP default tree
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:42.09 INFO  ==> ** LDAP setup finished! **
test_openldap.1.rzjyshowyzot@vmi764857    |
test_openldap.1.rzjyshowyzot@vmi764857    |  09:46:42.12 INFO  ==> ** Starting slapd **
test_openldap.1.rzjyshowyzot@vmi764857    | 63984a02.07b79532 0x7fc05b931740 @(#) $OpenLDAP: slapd 2.6.3 (Nov 29 2022 11:05:27) $
test_openldap.1.rzjyshowyzot@vmi764857    | 	@4b9918e8888a:/bitnami/blacksmith-sandox/openldap-2.6.3/servers/slapd
test_openldap.1.rzjyshowyzot@vmi764857    | 63984a02.086a9099 0x7fc05b931740 slapd starting

We see in these logs that the openldap container started before the init container ran to completion.

So remember, depends_on is a no-op when deploying to Docker Swarm!