Reputation: 1783
I have a dockerized app that uses mysql, express & react.
I need to first initialize mysql with a docker-entrypoint-initdb.d
before starting the express app. However, when mysql server starts it doesn't execute the starting .sql script right away and my_database_name
starts initially empty.
In that timegap, my express app starts and tries to query en empty database. Later the initialization script works as intended and fills my_database_name
which is already too late by then since my express app has already started.
I've tried depends_on/condition
as shown below but Version 3 no longer supports the condition form of depends_on
as stated in the docs.
version: '3.8'
services:
api-server:
build:
context: ./server
dockerfile: ./Dockerfile
image: myapp_server
env_file: ./server/.env
stdin_open: true
tty: true
depends_on:
mysqldb:
condition: service_healthy
ports:
- 9000:9000
networks:
- mysern-app
container_name: my_express_app
mysqldb:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: my_database_name
volumes:
- mysql-data:/data/db
- ./db/backup/:/mysql/backup
- ./db/init:/docker-entrypoint-initdb.d
healthcheck:
test: 'not sure what to write in here as well'
interval: 1s
retries: 120
networks:
- mysern-app
ports:
- 3306:3306
container_name: my_mysql_app
networks:
mysern-app:
driver: bridge
volumes:
mysql-data:
driver: local
I ultimately want to do this sequence:
Start mysqldb > fill the table from the script > start the express app
Upvotes: 4
Views: 3765
Reputation: 11337
There are several things you can do:
restart: always
to your api-server
. If it crashes because MySQL is not yet available - it will restart until MySQL will be available. I'm assuming that your api-server
will crash if MySQL is not available.docker-compose is your orchestrator and it can help you and take care of failures. In real-world, your MySQL might be not available for a second too, and you must know how to handle that.
Upvotes: 2
Reputation: 301
mysql:
build: ...
...
healthcheck:
test: mysql ${DB_NAME} --user=${DB_USER} --password='${DB_PWD}' --silent --execute "SELECT 1;"
interval: 30s
timeout: 10s
retries: 5
Sample .env file
DB_HOST=...
DB_NAME=...
DB_USER=...
DB_PWD=...
Upvotes: 0
Reputation: 16505
This worked for me:
version: "3.7"
services:
acme-db:
image: mysql:5.7
command: mysqld --sql_mode="" --max_connections=1100 --general-log=1 --general-log-file=/tmp/mysql-general-log.log
container_name: eventhos-db
ports:
- "3306:3306"
volumes:
- ./database:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: changeme
MYSQL_PASSWORD: changeme
MYSQL_USER: "usr_acme"
MYSQL_DATABASE: "acme"
TZ: America/Lima
deploy:
resources:
limits:
memory: 512M
healthcheck:
test: 'cat /tmp/mysql-general-log.log | grep "root@localhost on using Socket"'
interval: 10s
retries: 120
There is not a native way to ask the mysql if dump has been fully imported.
Researching I found an internal mysql log file called mysql general_log and reviewing its content in dockerized mysql I detected a pattern:
If everything is ok, at the end this line appear: "root@localhost on using Socket" just once
So if we enabled this log using command: in docker-compose:
command: mysqld --sql_mode="" --max_connections=1100 --general-log=1 --general-log-file=/tmp/mysql-general-log.log
The health check is just a search of these line
cat /tmp/mysql-general-log.log | grep "root@localhost on using Socket"
Note: Health check interval less than 10 seconds, don't work!
Upvotes: 2