noitse
noitse

Reputation: 1045

Docker script not connecting when run first time (sql dump)

I am trying to run mysql through docker and scripts. Everything works fine, it runs it creates users and database. I can connect to it using workbench, but it does not run dump.sql

I get following error

Access denied for user 'userxx'@'localhost' (using password: YES)

But if I run script once again, it will connect and it will run dump.sql

Here is my script:

#!/bin/sh

echo "Starting DB..."
docker run --name test_db -d \
  -e MYSQL_ROOT_PASSWORD=test2018 \
  -e MYSQL_DATABASE=test -e MYSQL_USER=test_user -e MYSQL_PASSWORD=test2018 \
  -p 3306:3306 \
  mysql:latest

# Wait for the database service to start up.
echo "Waiting for DB to start up..."
docker exec test_db mysqladmin --silent --wait=30 -utest_user -ptest2018 ping || exit 1

# Run the setup script.
echo "Setting up initial data..."
docker exec -i test_db mysql -utest_user -ptest2018 test < dump.sql

What am I doing wrong ? Or is there way to run dump through Dockerfile, Since I couldnt manage to do it?

Upvotes: 2

Views: 502

Answers (2)

Shahriar
Shahriar

Reputation: 13804

If you run docker run --help, you will see these flags

  --health-cmd string              Command to run to check health
  --health-interval duration       Time between running the check (ms|s|m|h) (default 0s)
  --health-retries int             Consecutive failures needed to report unhealthy
  --health-start-period duration   Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s)
  --health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)

So, you can use these command to check health with provided command. In your case, that command is

mysqladmin --silent -utest_user -ptest2018 ping

Now run as bellow

docker run --name test_db -d \
  -e MYSQL_ROOT_PASSWORD=test2018 \
  -e MYSQL_DATABASE=test -e MYSQL_USER=test_user -e MYSQL_PASSWORD=test2018 \
  -p 3306:3306 \
  --health-cmd="mysqladmin --silent -utest_user -ptest2018 ping" \
  --health-interval="10s" \
  --health-retries=6 \
  mysql:latest

If you run docker ps, you will see

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                             PORTS                    NAMES
5d1d160ed7de        mysql:latest        "docker-entrypoint.s…"   16 seconds ago      Up 16 seconds (health: starting)   0.0.0.0:3306->3306/tcp   test_db

You will see health: starting in Status.

Finally you can use this to wait. When your mysql is ready, health will be healthy.

So modify your script as below

#!/bin/bash

docker run --name test_db -d \
  -e MYSQL_ROOT_PASSWORD=test2018 \
  -e MYSQL_DATABASE=test -e MYSQL_USER=test_user -e MYSQL_PASSWORD=test2018 \
  -p 3306:3306 \
  --health-cmd="mysqladmin --silent -utest_user -ptest2018 ping" \
  --health-interval="10s" \
  --health-retries=6 \
  mysql:latest

# Wait for the database service to start up.
echo "Waiting for DB to start up..."
until [ $(docker inspect test_db --format '{{.State.Health.Status}}') == "healthy" ]
do
  sleep 10
done

# Run the setup script.
echo "Setting up initial data..."
docker exec -i test_db mysql -utest_user -ptest2018 test < dump.sql

Here, following command returns health status

docker inspect test_db --format '{{.State.Health.Status}}'

Wait until it returns healthy.

Note: I have used #!/bin/bash in script

Upvotes: 1

Mike Doe
Mike Doe

Reputation: 17624

Instead of executing a dump, better mount your sql file to the init directory of MySQL’s image: /docker-entrypoint-initdb.d in the run command.

Simply add the switch:

-v $PWD/dump.sql:/docker-entrypoint-initdb.d/dump.sql

Pro tip :) don’t use latest tag. Always use stable, specific tag like 5, 5.7, 8 etc.

Upvotes: 1

Related Questions