I had the same error, but I used MongoDB as a database. The initialization principle is the same, so I will describe my solution.
The solution I found is to create a Dockerfile with a forced copy of the database initialization file directly to the folder used by the database. In this case, I specify the Dockerfile for assembly directly in docker-compose and use the docker compose build command in gitlab-ci.
The project structure is shown below. I have omitted the details and left only the most necessary.
# Project structure
|-pkg/
|-tests/
| |-docker/
| | |-mongo_init_data/
| | | |-test_data.js # script for DB
| | |-compose.yml # docker-compose file docker-compose file that will be launched in pipeline
| | |-Dockerfile.mongo # Dockerfile for creating a DB container
| |-unit_tests/
|-auth_module.py
|-Dockerfile
The Dockerfile contains the base image and file copying. You can specify more settings here, but this was enough for me.
# Dockerfile.mongo
FROM mongo:latest
COPY ./mongo_init_data /docker-entrypoint-initdb.d
The mongo_init_data
folder contains scripts that the database must execute during initialization.
IMPORTANT: the docker-compose
file will run exactly where it is located in the project structure. For this reason, sometimes you have to go up several directories when building a project.
Below you can see that I am assembling a mongo container and a program container from Dockerfiles.
# compose.yml
name: auth_module_test
services:
mongo:
build:
dockerfile: ./Dockerfile.mongo #<-----------------------
container_name: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
command: mongod --port ${MONGO_PORT}
restart: always
ports:
- ${MONGO_PORT}:${MONGO_PORT}
auth_module:
image: auth_module:test
build:
context: ../../. #<-----------------------
container_name: auth_module_test
environment:
MONGO_PASSWORD: ${MONGO_PASSWORD}
MONGO_USERNAME: ${MONGO_USERNAME}
MONGO_PORT: ${MONGO_PORT}
MONGO_HOST: ${MONGO_HOST}
command: >
bash -c "sleep 5 && python3 -m unittest discover ./tests/unit_tests/"
Also omitting the implementation details. This is how running a docker-compose
file looks like. The most important thing here is to destroy the volumes
after executing the pipeline. The -v
flag is used for this. If you do not do this, runners can use old volumes
to start containers. Then the database will be considered initialized and the startup script will not be executed.
--abort-on-container-exit
stops all containers if any container was stopped.
# .gitlab-ci.yml
stages:
- Unittests
unittest:
stage: Unittests
script:
- docker compose -f ./tests/docker/compose.yml down -v
- docker compose -f ./tests/docker/compose.yml build #<-----------------------
- docker compose -f ./tests/docker/compose.yml up --abort-on-container-exit
after_script:
- docker compose -f ./tests/docker/compose.yml down -v
This way I managed to initialize the database with the initial data.
docker exec your_db_container ls -l /docker-entrypoint-initdb.d/
to your CI config, just to make sure that the SQL file is really there? – Stypsisdocker volume ls
? If so, try to delete them (if there is nothing important there, of course – if this is the case, just rename the service in thedocker-compose.yml
). If this helps, try to changedocker-compose down
in your script todocker-compose down -v
. – Stypsis--build
to your command? You didn't specify any build part in yourdocker-compose.yml
, so... – Stypsis--build
parameter was a leftover from breaking this down to a minimal example. But it's not that what went wrong, but something really stupid, see my own answer. – Deen.sql
not anything else such as.ddl
. Check out the link @Stypsis sent to see why. – Magnificatdocker exec your_db_container ls -l /docker-entrypoint-initdb.d/
showed me the dir was empty- I forgot I had moved its location in my repo – Obstinate