简体   繁体   中英

MySQL scripts in docker-entrypoint-initdb are not executed

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?

You should clear data_volume before run 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 mysql directory /var/lib/mysql exist or not. If the directory doesn't exist (run it 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 at Dockerfile source

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.

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.

Short description
I have exactly the same issue , but with a mariadb image (that seems to have exactly the same docker-entrypoint.sh as mysql's one), and I would like to contribute to this thread. Hopefully, if we are many complaining about this issue, we can get it fixed :)

The .sql script contained inside the " docker-entrypoint-initdb.d " folder gets ignored when I run docker-compose.yml on my production environment (Linux) , while exactly the same file works flawlessy on my development environment (Windows 7) .

This doesn't allow me to build the database structure (the .sql file contains all the CREATE TABLE statements...), therefore it's a major showstopper for me .

Detailed description
I tried the following solutions:

  • Changing EOL for the .sql from CRLF to LF;
  • Various chmod settings for " docker-entrypoint-initdb.d " (and contained scripts);
  • Entering the container with "docker exec" (both folder and scripts are accessible from within the container as expected);
  • Adding a *.sh file to " docker-entrypoint-initdb.d " (it gets ignored exactly as the .sql);

No success so far. Checking the logs with:

$ docker logs someappname_db >& logs_db.txt

shows that the following block of code from docker-entrypoint.sh doesn't get called at all on the Linux environment, exactly as @anteverse says:

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

Entering the container with "docker exec", I see the following permissions:

On Linux:

root@deda78e393f9:/# ls -l
total 72
drwxr-xr-x    2 root root 4096 Mar 19 19:53 bin
drwxr-xr-x    2 root root 4096 Nov 19 16:32 boot
drwxr-xr-x    5 root root  340 Apr 29 15:53 dev
**drwxrwxrwx+   2 root root 4096 Apr 29 11:30 docker-entrypoint-initdb.d**
lrwxrwxrwx    1 root root   34 Mar 14 06:26 docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
...

On Windows 7:

root@a3ff19060712:/# ls -l
total 64
drwxr-xr-x   2 root root  4096 Feb 17 09:07 bin
drwxr-xr-x   2 root root  4096 Nov 19 16:32 boot
drwxr-xr-x   5 root root   340 Apr 29 16:04 dev
**drwxrwxrwx   1 1000 staff    0 Apr 28 18:13 docker-entrypoint-initdb.d**
lrwxrwxrwx   1 root root    34 Feb 17 09:08 docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
...

Could it be related to the UID:GID? Should them be 1000:staff as well on Linux?

The user on my Linux host is called 'admin', could be perhaps a mismatch root (on container) : admin (on host) thingy?

Specifications
Development environment: Windows 7, Docker 18.02.0-CE
Production environment: unspecified flavour of Linux (QNAP TS-253A), Docker 17.07.0-CE

[/share/Container/] # uname -or
4.2.8 GNU/Linux

[/share/Container/] # cat /etc/issue
Welcome to TS-253A, QNAP Systems, Inc.

[/share/Container/] # cat /etc/os-release
NAME="QTS"
VERSION="4.3.4 (20180215)"
ID=qts
PRETTY_NAME="QTS 4.3.4 (20180215)"
VERSION_ID="4.3.4"

docker-compose.yml

version: '3'
services:

  db:
    container_name: someappname_db
    image: mariadb:latest
    restart: on-failure:3
    environment: 
      - MYSQL_DATABASE=someappname
      - MYSQL_ROOT_PASSWORD=someappname
      - MYSQL_USER=someappname
      - MYSQL_PASSWORD=someappname
      - MYSQL_ROOT_HOST=%
      - TZ=Europe/Stockholm
    ports:
      - 3306:3306  
    volumes:
      - dbdata:/var/lib/mysql      
      - /share/Container/someappname/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
    networks:
      - net
    command: ["mysqld", "--user=mysql", "--lower_case_table_names=1"]

    # other services

volumes:
  dbdata:

networks:
  net:

Commands:
I always clean-up the volume before re-composing the container:

$ cd /share/Containers/someappname
$ docker stop $(docker ps -a -q --filter="name=someappname") && docker rm $(docker ps -a -q  --filter="name=someappname") && docker volume rm someappname_dbdata
$ docker-compose -f someappnameprod-docker-compose.yml up -d db

Thank you for your kind help!

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"]

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

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM