If you are developing microservices, docker-compose(compose), can be a very powerful tool. Think of a case with an API service and database. Creating and maintaining a database with the use of the Liquibase.
- start DB
- run the Liquibase to make changes
- start an app
Adding docker-compose as a driver to utilize this process:
This is the simplest step. According to the docs, this would be enough:
service: ... pg: container_name: pg image: postgres:13.1 healthcheck: test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER timeout: 45s interval: 10s retries: 10 restart: always environment: POSTGRES_USER: root POSTGRES_PASSWORD: password POSTGRES_DB: docker volumes: - ./db:/docker-entrypoint-initdb.d/ ports: - 5432:5432 ...
Without going into Postgres setup specifics above configuration can be interpreted as:
- service name is pg
- container name is pg, too
- use image postgres version 13.1
- setup healthcheck
- restart always container is it not running
- set environment variables
- attach volume
- expose container port to the host
This instruction tells Docker how to test container health status. Container starts with starting status. After interval period test is executed. If in timeout period test return 0, then container is healthy. If test returns 1, or there is no response after timeout period test fails. Next test is executed after interval passes. If retries number of time test fails, container is considered unhealthy.
The restart policy defines what to do when the container fails or stops.
This instruction defines environment variables set in the container. The application running in the container will be able to read them.
The volumes mount a local file system within a container file system. In case above directory ./db will be mounted to container as /docker-entrypoint-initdb.d/. If ./db does not exist Docker will make it.
We could start the PG database and then run the Liquibase manually. But why?:
service: ... liquibase_pg: container_name: pg_updater image: liquibase/liquibase:4.7.0 volumes: - ./liquibase:/liquibase/changelog command: liquibase --url="jdbc:postgresql://pg:5432/docker" --changeLogFile=./changelog/changelog.xml --username=root --password=password update depends_on: - pg ...
So, the new service is named liquibase_pg. As well it mounts volume /liquibase/changelog for the local directory ./liquibase. Then it executes command but only when service pg is healthy as it depends on pg service. The command is the Liquibase specific. It defines connection string, credentials, command and utilizes mounted volume.
Mounted volume should contain Liquibase changelog.
This instruction defines a list of services that need to be running and healthy before Docker can start this one.
services: ... app: container_name: echo build: . ports: - 9999:9999 volumes: - ./configs:/app/configs depends_on: - liquibase_pg restart: always ...
This is some application developer is working on. It does not pull any image. Rather if the image does not exist it will be built from Dockerfile located in the path defined with build. And it will start only after Liquibase is started.
Nothing here that we did not already use.
Putting all together
The whole configuration can be found here.
In full setup, the application is run on MariaDB as well.