Controlling startup order of services -- docker compose parsing error

Hi, I am trying to introduce starting conditions for containers, so that they wait for each other before starting. I am currently doing this with healthchecks.

Here is how my docker-compose.yml looks like:

version: ‘2.1’

init:
build: ./init
healthcheck:
test: ./all_ready.sh
interval: 20s
timeout: 10s
retries: 10

network:
build: ./network
depends_on:
init:
condition: service_healthy

When pushing this to resin remote, I get

[Error] Could not parse compose file
[Error] Service dependencies must be an array
[Error] Not deploying release.

I tried adding “-” in front of the depending service, but this lead to another parsing error.

I tried this docker compose syntax for a docker container outside resin and it worked. Any idea how to fix this in resin?

Hi @ionita ,

This does look like a syntax error, but I cannot tell with much confidence with the existing formatting.

Could you please upload the docker-compose.yml instead? That way the indentation will be kept and it’ll be easier for us to spot any errors there.

Thanks!

Hi @lekkas,

thanks for the reply! Here is the file (renamed from yml to log, as it was otherwise not possible to upload it):

docker-compose.log (387 Bytes)

I think that behaviour is not yet supported by us. Looking at the cocker compose file reference:

depends_on was added in version 2 of docker compose, that we support, and the condition added in 2.1.

As our docs mention, only the version 2’s array format is supported, and that is without the condition, just as

...
  network:
    build: ./network
    depends_on:
      - init
...

We’ll open an internal issue for this. In the meantime, the Docker documentation has some hints how to use a bit of extra tooling to replicate that behaviour, if I read it well.

Let us know if you tried it out, and whether it works…

Hi @imrehg, thanks for you answer! I did indeed used some wrapper scripts to delay the start of containers, after the example of wait-for-*

command: wait-for-container1.sh start-container2

With the healthcheck option I would still have a script executing, maybe it is also a bit more transparent. So looking forward to seeing it supported in the future.

Does the command put in the compose file replace the command in the dockerfile.template?
Or are the separate?

  • "If dockercompose.container1.command then
    • start container1
      • container1.cmd

Also, got this error:

[Error]    Could not parse compose file
[Error]      data/services/camera should NOT have additional properties
[Error]    Not deploying release.

With this compose fragment:

  camera:
    build: ./Camera
    healthcheck:
      test: ["CMD", "curl", "-f", "http://barnserv:80"]
      interval: 30s
      timeout: 10s
      retries: 5

The following docker-compose.yml is accepted fine for me:

version: '2.1'
services:
  camera:
    build: ./Camera
    healthcheck:
      test: ["CMD", "curl", "-f", "http://barnserv:80"]
      interval: 30s
      timeout: 10s
      retries: 5

Are you sure you specify version: '2.1'?

No, I had version 2.
Is there any reason to specify version 2 vs version 2.1 other than the healthcheck field?

Version 2 examples:

Hi,

That’s correct, if you do want the healthchecks you will have to specify 2.1 instead of 2.0.

Best regards, Heds

The healthcheck option is nice but it does not do anything if another service cannot depend on it. I have had the case where a service only exists to expose kernel modules and in this case a simple file written to the filesystem of that service is enough to say “I am done” and therefore having a script running on services that depend on that does not work since they cannot look inside the dependant service filesystem.

I honestly think that we are missing a proper way of a service depending on the healthcheck of another services

Would not what you are suggesting be resolved with named volumes, or I am misunderstanding your comment? E.g.

services:
    one:
        volumes:
            - lock-volume: /some/location/in/container
    two:
        volumes:
            - lock-volume: /some/location/in/container
volumes:
     lock-volume: 

I meant services which are doing something like insmod to make kernel modules available to other services however what you have described is another setup.

In your example service one could be a service which exposes some files required by service two. This means service two depends on service onebeing done.

So in the setup you described service one and two will come up at the same time which might not work. Using depends_on can help however balena only waits for the container to start while service one can take some time to be finished with making those files available.

This is what the condition part of depends_on is solving which we are missing today in Balena

The condition form of depends_on is removed in version 3 of docker-compose. Will an alternative method work for you like the ones explained in https://docs.docker.com/compose/startup-order/?

Yeah I noticed it was removed in version 3 sadly. Has no replacement been specified? I saw just yesterday that docker has recently published official specs for the docker compose so maybe something can be used from there.

An alternative method would of course suit us however the alternative method you linked requires that the container which depends on some service to have a way to ask the dependant service whether it is done doing what needs to be done. In the cases where the dependant service does not expose an external API for that it does not work.

This is why the healthcheck is a good option as it exposes an external API to docker compose that other servicers can query on so the service does not have to do this.

While it would be possible to expose something for other service to query for a dependency, there’s some elegance in providing that on a docker compose level so underlying services don’t have to implement that themselves

Hey there! I totally get your concerns. We’ve talked about leveraging the healthcheck (https://docs.docker.com/compose/compose-file/#healthcheck) options in combination with the depends_on option accomplish this, but its not something that’s in place right now (or will be for sure)

2 Likes