0

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?

Sander Vanden Hautte
  • 2,138
  • 3
  • 22
  • 36

2 Answers2

4

With a shell script, executable not found means either the script itself does not exist, or the shell launched by the script on the first line does not exist. Things to look for:

  • does /bin/bash exist inside your image? It should since python 3.6 is based on Debian.
  • is the volume mount inside your container overwriting the directory? The .:/code volume mount means everything you do in the image at that location is replaced, but you appear to be running from the same directory.
  • is the script really trying to run /bin/bash or is there a Windows linefeed in the file? Linux doesn't understand the windows linefeeds, so it will look for a /bin/bash^M to execute, which doesn't exist.
BMitch
  • 231,797
  • 42
  • 475
  • 450
  • That's it! Setting the shell script to have line endings only with LF now results in `broker_1 | /code/wait-for-mysql-init.sh: line 14: mysqladmin: command not found`. I have a new issue now apparently, but this is the answer to my question, thanks! Crazy that the problem was such a tiny detail. – Sander Vanden Hautte Jun 08 '18 at 11:09
  • 1
    Documenting the solution to the remaining issue for people that might try the same wait-for-mysql-init.sh approach: use wait-for-it.sh instead, see: https://docs.docker.com/compose/startup-order/. My shell script used the mysqladmin executable and apparently this executable isn't present in the mysql image: https://github.com/docker-library/mysql/issues/410. – Sander Vanden Hautte Jun 08 '18 at 12:15
-1

try COPY instead of ADD

COPY wait-for-mysql-init.sh /code/
pushkin
  • 9,575
  • 15
  • 51
  • 95
Maxim Antonov
  • 295
  • 3
  • 9