docker-compose: Is there any way to prevent `php-fpm` to be started until `db` has end?

I have the following docker-compose.yml file:

version: '2'
services:
    db:
        image: mysql
        environment:
            MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
            MYSQL_DATABASE: ${MYSQL_DATABASE}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
        volumes:
            - sql_data:/var/lib/mysql
    httpd:
        build: docker/httpd
        ports:
            - "80:80"
        volumes_from:
            - php-fpm
    php-fpm:
        build: docker/php-fpm
        depends_on:
            - db
volumes:
    sql_data:
        external: true

The container php-fpm should run some scripts to create the schema and load fake data only if db has been started and DB has been created successfully. Currently docker-compose up -d --build --force-recreate is doing the following:

  • localhost refuses connection with docker
  • Can I run Docker in a Virtual Machine?
  • Docker Clustering multiple proxies fronting multiple tomcats
  • docker registry v2 : get parent image name
  • elastic beanstalk can not find Dockerfile
  • To what extent can a Docker cluster reduce infrastructure costs? [closed]
    • Creating network dockerpyrocms_default with the default driver
    • Building php-fpm
    • Building httpd
    • Creating dockerpyrocms_db_1
    • Creating dockerpyrocms_php-fpm_1
    • Creating dockerpyrocms_httpd_1

    But because the DB hasn’t be created as such point then dockerpyrocms_php-fpm_1 is exiting with code ` and the cause is it can connect to the DB:

    php-fpm_1  |   [Illuminate\Database\QueryException]   
    php-fpm_1  |   SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = pyrocms and table_name = default_migrations)  
    php-fpm_1  |   [Doctrine\DBAL\Driver\PDOException]
    php-fpm_1  |   SQLSTATE[HY000] [2002] Connection refused
    

    Apparently “depends_on” is sort of useless because Docker doesn’t know when the container is “ready”, it only knows when it has been started.

    Can I get some advice on this? Any ideas in how to fix this issue?

    Here is the repo with files and instructions.

    Note: Such problem only happen if MySQL image was already pulled and there wasn’t any changes. If you run this for first time then it’ll works if you run in a second time it will fails.

  • HDFS data node connection error in a docker container
  • Provide only GRANT EXECUTE 'procedure' to a user (No select or insert permissions)
  • What would be a good docker webdev workflow?
  • Docker Cluster loses leader status after reboot
  • Using SUID in Alpine Docker Image
  • Docker remove not working
  • 2 Solutions collect form web for “docker-compose: Is there any way to prevent `php-fpm` to be started until `db` has end?”

    I found it in Docker Compose itself:

    With Compose 1.10, it is now possible to indicate you want a
    dependency to wait for another container to be “healthy” (i.e. its
    healthcheck advertises a successful state) before starting.

    Ex:

    version: '2.1'
    services:
      web:
        build: .
        depends_on:
          db:
            condition: service_healthy
          redis:
            condition: service_started
      redis:
        image: redis
      db:
        image: redis
        healthcheck:
          test: "exit 0"
    

    Now my docker-compose.yml looks like:

    version: '2.1'
    services:
        db:
            image: mysql
            healthcheck:
                test: "exit 0"
            environment:
                MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
                MYSQL_DATABASE: ${MYSQL_DATABASE}
                MYSQL_USER: ${MYSQL_USER}
                MYSQL_PASSWORD: ${MYSQL_PASSWORD}
            volumes:
                - sql_data:/var/lib/mysql
        httpd:
            build: docker/httpd
            ports:
                - "80:80"
            volumes_from:
                - php-fpm
        php-fpm:
            build: docker/php-fpm
            depends_on:
                db:
                    condition: service_healthy
    volumes:
        sql_data:
            external: true
    

    And it works as expected. More info here and here.

    You can use wait for it.

    wait-for-it.sh is a pure bash script that will wait on the availability of a host and TCP port. It is useful for synchronizing the spin-up of interdependent services, such as linked docker containers. Since it is a pure bash script, it does not have any external dependencies.

    How to use?
    add etntrypoint in php-fpm container.
    entrypoint can look like this script:

    wait-for-it.sh db:3306 -t 60
    # some code interacted with database 
    # will executed only when database is started up
    
    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.