Docker compose:
version: "3"
services:
db:
container_name: db
image: mysql
ports:
- "3306:3306"
volumes:
- initdb:/docker-entrypoint-initdb.d/:ro
web:
container_name: web
image: my_web
volumes:
- initdb:/initdb/:ro
depends_on:
- db
volumes:
initdb:
my_web image contains /initdb/create_schema.sql.
web depends on db. So the service db will start before web.
Will the create_schema.sql from web be available for the db to consume?
From testing, it is available. Is this guaranteed or by random?
The create_schema.sql is generated when building my_web image. It is not on host disk.
Trying to understand when volumes are created and mapped to containers. If they are created and mapped before starting all containers, then the shared data via volumes will be guaranteed to be available.
2
Answers
if you want
than you need to create third container (it can be generated with similar Dockerfile to file for
web
but with different entrypoint) lets name itinit-db-script
, start it before db container, generatecreate_schema.sql
in itthen add it in depends for db
Or you can try to create data in volume by
docker run
for ‘script container’ that will stops afer scripts compleat, but data in volume will be created.But I suggest to generate
create_schema.sql
before build script, add it to your repository and add copy of it to Docker image of db in its DockerfileThe approach as you’ve described it will not work reliably. Most application frameworks include some sort of database migration system, and a more robust approach will be to have your application run migrations on startup than to try to use a named volume like this.
Docker named volumes have a subtly tricky sequence for copying content into a volume. When a container is created that mounts the volume, if and only if the volume is totally empty, then content is copied from the mount point into the image. This only happens if the volume is empty (so it will never see changes to the image content), and it only happens for Docker named volumes and not other kinds of mounts (Docker bind mounts, Kubernetes PersistentVolumeClaims, …).
What this sequence means is that Compose will
db
container, mounting the empty volumeweb
container, at which point Docker will copy the script into the volumeThis leads to a race condition where it’s not certain whether the
web
container startup will copy the file first, or thedb
container starts looking through that directory for initialization scripts.If you extend this setup to use a health check to wait until the database is running, then this won’t work at all. The
web
container won’t be created until thedb
container has finished its initialization, which means you have a guarantee that the volume will be empty when the/docker-entrypoint-initdb.d
directory is scanned.Again, remember that Docker won’t ever update the contents of the volume, so if you change the initialization script, the volume will still have the old one. The standard database images also only run
/docker-entrypoint-initdb.d
if their data directory is uninitialized. Running a migration system avoids both of these problems.