I want to unit-test my app which uses a postgres database inside a docker.
EDIT: based on the suggested answer I modified the Dockerfile
:
FROM postgres
USER postgres
RUN sleep 2 # remark 1
RUN initdb # remark 2
RUN sleep 3 # remark 1
RUN psql --host=localhost -l
The remarks are:
- from this reference
Try putting a sleep in there and see if it’s still a problem
- from the docs:
The default postgres user and database are created in the entrypoint with initdb.
Here is the Dockerfile
from the original question:
FROM postgres
COPY input.json .
RUN createdb -h localhost -p 7654 -U moish myLovelyAndTemporaryDb
#
# [ 1 ] run application on input.json
# [ 2 ] check db content after run
#
When I use the above Dockerfile
I seem to be missing something:
(The errors from the edited version are the same)
$ docker build --tag host --file Dockerfile .
[+] Building 0.3s (7/7) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 125B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/postgres:latest 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 40B 0.0s
=> CACHED [1/3] FROM docker.io/library/postgres 0.0s
=> [2/3] COPY input.json . 0.0s
=> ERROR [3/3] RUN createdb -h localhost -p 7654 -U moish myLovelyAndTemporaryDb 0.2s
------
> [3/3] RUN createdb -h localhost -p 7654 -U moish myLovelyAndTemporaryDb:
#7 0.188 createdb: error: connection to server at "localhost" (127.0.0.1), port 7654 failed: Connection refused
#7 0.188 Is the server running on that host and accepting TCP/IP connections?
#7 0.188 connection to server at "localhost" (::1), port 7654 failed: Cannot assign requested address
#7 0.188 Is the server running on that host and accepting TCP/IP connections?
------
3
Answers
Here is a complete answer based on the concepts of slava-kuravsky and mello:
The script can do what I want, currently it only lists the databases:
The Dockerfile does only initialization:
When I perform the three commands above I get what I expect 🙂 :
During the build step of the postgres Docker you cannot run postgres commands. Postgres database will only be available after you run the Docker.
As specified in the postgres Docker documentation you can add customization to your postgres instance through scripts placed in docker-entrypoint-initdb.d directory.
Alternatively you could use a
RUN
directive to start the postgres database and after that run the postgres commands you want (making sure to wait for the DB to accept connections), as mentioned here.Another side note, I personally avoid using real databases for unit testing applications. To me, it’s always better to mock the database for unit tests, in python you can do this with
unittest.mock
.Postgres database starts only after you create a container based on postgres image.
docker build
process doesn’t start entrypoint script. You might need a bash script or CI pipeline where you firstly start postgres container and then use it in your unit testsPostgres container docs
Postgres client authentication
EDIT:
By trying to run initdb, psql etc directly in Dockerfile, you are reinventing the docker-entrypoint.sh