I am trying to make sure that my app container does not run migrations / start until the db container is started and READY TO accept connections.
So I decided to use the healthcheck and depends on option in docker compose file v2.
In the app, I have the following
app: ... depends_on: db: condition: service_healthy
The db on the other hand has the following healthcheck
db: ... healthcheck: test: TEST_GOES_HERE timeout: 20s retries: 10
I have tried a couple of approaches like :
- making sure the db DIR is created
test: ["CMD", "test -f var/lib/mysql/db"]
- Getting the mysql version:
test: ["CMD", "echo 'SELECT version();'| mysql"]
- Ping the admin (marks the db container as healthy but does not seem to be a valid test)
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
Does anyone have a solution to this?
4 Answers
Answers 1
version: "2.1" services: api: build: . container_name: api ports: - "8080:8080" depends_on: db: condition: service_healthy db: container_name: db image: mysql ports: - "3306" environment: MYSQL_ALLOW_EMPTY_PASSWORD: "yes" MYSQL_USER: "user" MYSQL_PASSWORD: "password" MYSQL_DATABASE: "database" healthcheck: test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] timeout: 20s retries: 10
The api container will not start until the db container is healthy (basically until mysqladmin is up and accepting connections.)
Answers 2
If you can change the container to wait for mysql to be ready do it.
If you don't have the control of the container that you want to connect the database to, you can try to wait for the specific port.
For that purpose, I'm using a small script to wait for a specific port exposed by another container.
In this example, myserver will wait for port 3306 of mydb container to be reachable.
# Your database mydb: image: mysql ports: - "3306:3306" volumes: - yourDataDir:/var/lib/mysql # Your server myserver: image: myserver ports: - "....:...." entrypoint: ./wait-for-it.sh mydb:3306 -- ./yourEntryPoint.sh
You can find the script wait-for-it documentation here
Answers 3
I modified the docker-compose.yml
as per the following example and it worked.
mysql: image: mysql:5.6 ports: - "3306:3306" volumes: # Preload files for data - ../schemaAndSeedData:/docker-entrypoint-initdb.d environment: MYSQL_ROOT_PASSWORD: rootPass MYSQL_DATABASE: DefaultDB MYSQL_USER: usr MYSQL_PASSWORD: usr healthcheck: test: mysql --user=root --password=rootPass -e 'Design your own check script ' LastSchema
In my case ../schemaAndSeedData
contains multiple schema and data seeding sql files. Design your own check script
can be similar to following select * from LastSchema.LastDBInsert
.
While web dependent container code was
depends_on: mysql: condition: service_healthy
Answers 4
Hi for a simple healthcheck, I used:
/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\"
Basically it runs a simple mysql
command SHOW DATABASES;
using as an example the user root
with the password rootpasswd
in the database.
If the command succeed the db is up and ready so the healthcheck path. You can use interval
so it tests at interval.
Removing the other field for visibility, here is what it would look like in your docker-compose.yaml
.
version: '2.1' services: db: ... healthcheck: test: "/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\"" interval: 2s timeout: 20s retries: 10 app: ... depends_on: db: condition: service_healthy
0 comments:
Post a Comment