With the following docker-compose.yml
file, I create a stack that contains two services: one is a web application (called broker), the other a MySQL database (called broker_db) that the web application uses.
I found out that I must tell the broker service to wait until MySQL is initialized, and that I could use a shell script that delays the broker from really starting the web application until it can start using the database. However, I get the following error on running docker-compose up
:
broker_1 | standard_init_linux.go:190: exec user process caused "no such file or directory"
My docker-compose.yml
file is:
version: '3'
services:
broker-db:
image: mysql:5.7 # https://store.docker.com/images/mysql
restart: always
environment:
MYSQL_DATABASE: broker # Create a database with name broker during container initialization.
MYSQL_ROOT_PASSWORD: root # Set root/root as user/password credentials in the container.
ports:
- "3302:3306"
volumes:
- ./broker-db-volume:/var/lib/mysql
networks:
- shared-network
broker:
build: .
command: ["/code/wait-for-mysql-init.sh", "broker-db", "python3", "manage.py", "runserver", "0.0.0.0:8080"]
volumes:
- .:/code
ports:
- "8080:8080"
depends_on:
- broker-db
restart: always
networks:
- shared-network
networks:
shared-network:
The broker's Dockerfile adds all code in its root project folder to /code
in the docker container, so I don't understand why docker-compose up
says it can't find wait-for-mysql-init.sh
:
# Based on https://docs.docker.com/compose/django
FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
RUN chmod +x wait-for-mysql-init.sh
The shell script is the following:
#!/bin/bash
# wait-for-mysql-init.sh
# Taken from https://stackoverflow.com/a/29793382/5433896.
# Argument handling based on https://unix.stackexchange.com/questions/31414.
# Delayed command execution based on https://docs.docker.com/compose/startup-order/.
set -e # Exit immediately if a command exits with a non-zero status (https://stackoverflow.com/a/19622569/5433896).
DB_HOST="$1" # First argument passed to the script
shift # Forget the first argument, $2 becomes $1, $3 becomes $2 and so on.
command="$@" # All remaining arguments form the command to execute after MySQL is initialized.
while ! mysqladmin ping -h"$DB_HOST" --silent; do
echo "The initialization of MySQL on $DB_HOST is still ongoing."
sleep 1
done
echo "The initialization of MySQL on $DB_HOST has finished. It is ready to accept incoming queries."
echo "MySQL is up and running. Executing command $command."
exec $command
Also, an abbreviated overview of my broker project content:
C:\*somepath*\broker
├───broker-application-code
├───broker-db-volume
├───broker
├───.dockerignore
├───docker-compose.yml
├───Dockerfile
├───manage.py
├───requirements.txt
└───wait-for-mysql-init.sh
So the shell script is definitely present for adding to the docker image, the ADD instruction is in the Dockerfile, why then is the shell script still not found on starting the broker container?