1

I am hoping that someone can help me understand an error that I have encountered while building a multi-container environment using Docker Desktop for Windows using WSL2 (Don't think these details matter, but you never know)

I have a docker-compose.yml script that builds a number of containers that are all linked together. I can get it to work in a very janky way by commenting and uncommenting specific containers, but this seems counter productive to how docker compose is supposed to work from my understanding.

Before anyone comments something about using something like docker-compose-wait or docker-wait the problem with those solutions is that they are run during the build process, the error I am getting is happening before that build process ever gets a chance to process.

This is my docker-compose.yml file:

version: "3.4"

services:
  # Redis Service
  redis:
    build:
      context: .
      dockerfile: docker/redis/Dockerfile
    image: star/redis
    container_name: star_redis
    restart: unless-stopped
    tty: true
    ports:
      - "16379:6379"
    volumes:
      - redis_data:/data

  db:
    build:
      context: .
      dockerfile: docker/mysql/Dockerfile
    image: star/mysql
    container_name: star_db
    restart: unless-stopped
    tty: true
    environment:    
      RUN_INIT_FILES: ${DOCKER_RUN_MYSQL_INIT}
      SERVICE_TAGS: dev
      SERVICE_NAME: MySQL
    ports:
      - "3306:3306"
    volumes:
      - ${WEB_APP_PATH}${WEB_APP_PROJECT_PATH}/docker/mysql/init:/docker-entrypoint- initdb.d
      - star_mysql_db:/var/lib/mysql

  app:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    image: star/php
    container_name: star_app
    restart: unless-stopped
    tty: true
    environment:
      RUNNING_IN_DOCKER: 'true'
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    volumes:
      - star_laravel_data:${WEB_DESTINATION_PATH}
    depends_on:
      - redis
      - db
 
  nginx:
    build:
      context: .
      dockerfile: docker/nginx/Dockerfile
    image: star/nginx
    container_name: star_webserver
    restart: unless-stopped
    tty: true
    environment:
      RUNNING_IN_DOCKER: 'true'
    ports:
      - '80:80'
      - '443:443'
      - '8888:80'
    volumes:
      - star_laravel_data:${WEB_DESTINATION_PATH}
    depends_on:
      - db
      - app


  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: star_phpmyadmin
    environment:
      PMA_PORT: 3306
      PMA_HOST: db
      PMA_USER: ####
      PMA_PASSWORD: ######
    links:
       - db:MySQL
    ports:
       - "8090:80"
    restart: unless-stopped
    depends_on:
      - db
      - app
      - nginx

  package-installer:
    image: star/php:latest
    container_name: star_installer
    restart: on-failure
    depends_on:
      - db
      - app
      - nginx
    volumes:
      - star_laravel_data:${WEB_DESTINATION_PATH}
    environment:
      APP_ENV: local
      CONTAINER_ROLE: installer
      CACHE_DRIVER: redis
      SESSION_DRIVER: redis
      QUEUE_DRIVER: redis
      REDIS_HOST: redis

# Scheduler Service
 scheduler:
   image: star/php:latest
   container_name: star_scheduler
   restart: on-failure
   depends_on:
     - db
     - app
     - nginx
     - package-installer
   volumes:
     - star_laravel_data:${WEB_DESTINATION_PATH}
   environment:
     APP_ENV: local
     CONTAINER_ROLE: scheduler
     CACHE_DRIVER: redis
     SESSION_DRIVER: redis
     QUEUE_DRIVER: redis
     REDIS_HOST: redis

  # Queue Service
  queue:
    image: star/php:latest
    container_name: star_queue
    restart: on-failure
    logging:
      driver: local
    depends_on:
      - db
      - app
      - nginx
      - package-installer
    volumes:
      - star_laravel_data:${WEB_DESTINATION_PATH}
    environment:
      APP_ENV: local
      CONTAINER_ROLE: queue
      CACHE_DRIVER: redis
      SESSION_DRIVER: redis
      QUEUE_DRIVER: redis
      REDIS_HOST: redis

  volumes:
    star_laravel_data:
      driver: local
      driver_opts:
        type: none
        o: bind
        device: ${WEB_APP_PATH}${WEB_APP_PROJECT_PATH}
    star_mysql_db:
    portainer_data:
    redis_data:
      driver: local

So here is the crux of the problem, if I run this, as a fresh install I get this response from docker compose:

[+] Running 0/3                                                                                                                                                         
 - package-installer Error                                                                                                                                              
 - scheduler Error                                                                                                                                                      
 - queue Error                                                                                                                                                          
Error response from daemon: pull access denied for star/php, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

These containers which all have a depends_on field to tell them other containers at least need to be started first are the first ones that docker compose attempts to build. To me that makes no sense. These have a depends_on for a reason, they are using the custom image created by the app container to build their own containers. So why, if they are told they depend on other containers, and they are at the bottom of the script, are they the first ones that docker compose tries to build?

My only working solutions thus far has been:

  1. Comment out the package-installer, scheduler, and queue containers in the docker-compose.yml file
  2. Build the environment
  3. Shut down the environment
  4. Un-comment the package-installer container
  5. Re-build the environment (because now the custom star/php image exists)
  6. Shut down the environment
  7. Un-comment the scheduler and queue containers
  8. Re-build the environment...again (because now the files added by running the package-installer Dockerfile have been added)
  9. Now I can use the environment

If this was just my own environment this wouldn't be an issue, but this docker stack was designed for our development team to be able to use it. With this strategy to get it installed, I would have to explain the process to each person on how to comment and un-comment the various packages to get it to work. That would be a nightmare.

Based on the docker documentation, the depends_on field is supposed to build the containers in order of their dependence, which means the containers should be built in this order:

  1. redis
  2. db
  3. app
  4. nginx
  5. phpmyadmin
  6. package-installer
  7. queue / scheduler

Again, I'm not concerned if the container that it is depending on is running, it simply needs to be built, but it doesn't seem to be doing that, it seems (at least for the three affected containers) to skip right to the running stage, without building the dependencies).

Any useful insight or tips would be welcomed.

Chris
  • 439
  • 7
  • 16
  • 2
    [`depends_on:`](https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on) has no effect on image builds, only on the order the created containers start starting. Separately running `docker-compose build; docker-compose up -d` might help here, or setting all of the containers to have the same `build:` block and removing the `image:`s (most of the builds will come from the Docker layer cache and run extremely quickly). – David Maze Feb 12 '22 at 02:01
  • 1
    Possibly related to your workflow problem: do not write a Compose container that installs packages in a volume then exits. Instead, write this logic into your Dockerfile, and remove the volume declaration hiding the image contents. The libraries will be installed in the image and you will not need as complex a workflow. – David Maze Feb 12 '22 at 02:03
  • @DavidMaze, your comment helped me resolve my problem. Maybe you could turn it into an answer so that I can upvote it. – Lukman Oct 30 '22 at 14:30

1 Answers1

0

depends_on does not wait for other containers to be “ready” before starting only until they have been started. If you need to wait for a service to be ready, see https://docs.docker.com/compose/startup-order/ for solving it.

dataplumber
  • 375
  • 3
  • 16
  • what about [`links`](https://stackoverflow.com/questions/35832095/difference-between-links-and-depends-on-in-docker-compose-yml) parameter instead using [`depends_on`](https://stackoverflow.com/questions/35832095/difference-between-links-and-depends-on-in-docker-compose-yml)? – Affes Salem Feb 11 '22 at 20:56
  • Beyond activating an obsolete Docker networking mode, `links:` is the same as `depends_on:`. I'd remove it from my Compose setup if it was present. – David Maze Feb 12 '22 at 01:59