83

I am trying to create multiple databases when a MySQL container starts up. According to https://github.com/docker-library/mysql/pull/18, I can mount or copy my scripts in the /docker-entrypoint-initdb.d of the image and they will be executed automatically on start up.

However my scripts are not at all executed. Seems like the docker-entrypoint.sh doesn't see files in the /docker-entrypoint-initdb.d directory.

This is my Dockerfile:

FROM mysql
ADD script.sql /docker-entrypoint-initdb.d/script.sql
RUN chmod -R 775 /docker-entrypoint-initdb.d

ENV MYSQL_ROOT_PASSWORD mypass

This is my script.sql:

CREATE DATABASE mydb;
CREATE DATABASE mydb2;

I build and run the container:

$ docker build -t mysql .
$ docker run -v data_volume:/var/lib/mysql --name somedb -d mysql

When I access the container in tty I can see that the script.sql is in the /docker-entrypoint-initdb.d but is not executed.

I have seen the docker logs -f somedb output but there is no error.

I have tried with .sh file, I also have tried with Maria-db, the result is the same.

What could be the problem?

1

8 Answers 8

112

Solution

You should clear data_volume BEFORE running the container and the SQL files will be executed.


This volume data_volume can be removed by using command:

docker volume rm data_volume

The root cause of your problem can be found in docker-entrypoint.sh. When you run a MySQL container, it checks if MySQL directory /var/lib/mysql exist or not. If the directory doesn't exist (running it the first time), it will run your SQL files.

if [ ! -d "$DATADIR/mysql" ]; then
    // Some other logic here

    for f in /docker-entrypoint-initdb.d/*; do
        case "$f" in
            *.sh)     echo "$0: running $f"; . "$f" ;;
            *.sql)    echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
            *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
            *)        echo "$0: ignoring $f" ;;
        esac
        echo
    done 

You can get more details from MySQL docker-entrypoint.sh source file.

Sign up to request clarification or add additional context in comments.

8 Comments

There is a slight language barrier above, so I wanted to add to this solution to clarify it a bit, as it is the correct one: If the mysql data volume exists, it will not be overwritten by the SQLs in the entry db. For me, this meant doing rm /my/data/volume, as it was a disposable one. After that, things ran as they should.
Wow, i spent hours on this one. Thank you for this!
Thank @TarekLoubani for the explanation.I've updated the answer also
THANK YOU! I ran into this as well
My import worked fine until I switched from mysql:5.7 to mysql-server:5.7. It turns out that the entrypoint in the server image does not include the line to process .sql.gz extensions.
|
30

So I had the same issue for hours, and then decided to look into docker-entrypoint.sh. It turns out that the script checks for $DATADIR/mysql, typical /var/lib/mysql and skips the rest of the code if the datadir exists, incl. docker-entrypoint-initdb.d

So what I did was make a simple init.sh file to remove the datadir then start docker.

docker-compose.yml:

volumes:
  - ./docker/mysql/scripts:/docker-entrypoint-initdb.d
  - ./mysql_data:/var/lib/mysql

init.sh:

#!/bin/bash
rm -rf mysql_data
docker-compose up --force-recreate

And of course add -d to docker-compose once I see it works as expected.

3 Comments

where did you add the init.sh file?
@GeorgeGeorgitsis: If the Docker image finds any files with the extensions .sh or .iql inside of the /docker-entrypoint-initdb.d folder, it will execute them. I my case the init.sh it located inside ./docker/mysql/scripts/
My 5 cents: Mind that you should include execution in the permissions for the init.sh file on the host - otherwise you could get an error like: /docker-entrypoint-initdb.d/init.sh: /usr/bin/env: bad interpreter: Permission denied
9

I had the exact same issue with the mariadb image (version: 10.4) and I solved it by making sure my container data volume is empty from any files or directories when I create the container from scratch.

This is my docker compose file:

  mariadb:
    image: mariadb:10.4
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ********
    volumes:
    - ./storage/db:/var/lib/mysql:rw
    - ./app/db/SQL:/docker-entrypoint-initdb.d/:rw
    ports:
    - 3306:3306/tcp

For me I just had to make sure this path: './storage/db' is empty from files. Please notice that the directory has to exists but be empty.

2 Comments

How did you empty ./storage/db?
You can try and use a new docker volume or delete all content of your data mounted directory
3

I had the same problem. I solved it by changing directory owner before starting entrypoint script. Example Dockerfile:

FROM mysql:5.7.17
ADD scripts/init.sql /docker-entrypoint-initdb.d/

RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/

CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]

Comments

3

I had the same issue and like @Ricky suggested above the root cause was the volume being non empty. I ran the command docker volume ls to check if the volume was still present before running my docker-compose up and sure enough the volume was there. I deleted the volume using docker volume rm <volume name> and ran the docker-compose and voila the script I had in the docker-entrypoint-initdb.d had run and I had my data in my database. I would say don't worry about the chmod stuff (as some people have suggested) until you make sure the volume is non-existent before running the docker-compose. In case that doesn't work, you can try playing around with the file permissions.

This is what I have permissions wise in my working container in case anybody is wondering -

Permission on docker-entrypoint-initdb.d

drwxr-xr-x   1 root root 4.0K Nov 16 01:52 docker-entrypoint-initdb.d

and the following on the sql scripts -

root@f0a4da202f39:/opt/app# ls -lh /docker-entrypoint-initdb.d/
total 12K
-rw-r--r-- 1 root root 12K Nov 15 22:14 Henry.sql

Comments

3

As per: https://stackoverflow.com/a/67435932/15926221

If you're using "MYSQL_USER: root" as the env variable in mysql/mariadb, this can be the cause of the problem, because the root user was already pre-created.

1 Comment

That was the problem on my side!! Thanks for the hint.
0

not really an answer to that behavior but i usually do it like this:

RUN mkdir -p /docker-entrypoint-initdb.d && mv myScript.sql /docker-entrypoint-initdb.d/myScript.sql

don't think there's anything wrong with your code but who knows. i suppose you checked 775 is the correct owner? btw im using FROM mysql:5

1 Comment

This configuration didn't solve the problem. I have checked that the file is executable. I guess the problem is in the data_volume. I keep working on it thank you.
0

Have you solved the issue yet?

A simple workaround is to use absolute path when reading files in /docker-entrypoint-initdb.d/

I made my test using the default config of: https://github.com/docker-library/mysql/blob/master/5.7/Dockerfile#L70

The docker-entrypoint.sh is first moved to /usr/local/bin before execution.

Then it comes to reading files in /docker-entrypoint-initdb.d/, but the following:

for f in /docker-entrypoint-initdb.d/*; do

doesn't seem to find anything.

If you replace it with:

for f in /usr/local/bin/docker-entrypoint-initdb.d/*; do

and then make sure the folder is populated by the Dockerfile command:

COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

COPY docker-entrypoint-initdb.d/ /usr/local/bin/docker-entrypoint-initdb.d/
RUN chmod -R +x /usr/local/bin/docker-entrypoint-initdb.d

From there, build a test statement in /docker-entrypoint-initdb.d/test.sql

CREATE DATABASE `test`;

Finally build and run the image and you should see your database created.

1 Comment

You mean editing mysql's Dockerfile? If so, I hope there is a better solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.