Marc Le Bihan
Marc Le Bihan

Reputation: 3314

A container is a database server. How to ask it's Dockerfile to complete its construction after that container has started?

I am using a postgis/postgis Docker image to set a database server for my application.

  1. The database server must have a tablespace created, then a database.
  2. Then each time another application will start from another container, it will run a Liquibase script that will update the database schema (create tables, index...) when needed.

On a terminal, to prepare the database container, I'm running these commands :

# Run a naked Postgis container
sudo docker run --name ecoemploi-postgis 
     -e POSTGRES_PASSWORD=postgres 
     -d -v /data/comptes-france:/data/comptes-france postgis/postgis

# Send 'bash level' commands to create the directory for the tablespace
sudo docker exec -it ecoemploi-postgis 
     bin/sh -c 'mkdir /tablespace && chown postgres:postgres /tablespace'

Then to complete my step 1, I have to run SQL statements to create the tablespace in a PostGIS point of view, and create the database by a CREATE DATABASE.

I connect myself, manually, under the psql of my container :

sudo docker exec -it ecoemploi-postgis bin/sh 
     -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" 
     -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

And I run manally these commands :

CREATE TABLESPACE data LOCATION '/tablespace';
CREATE DATABASE comptesfrance TABLESPACE data;
exit

But I would like to have a container created from a single Dockerfile having done all the needed work. The difficulty is that it has to be done in two parts :

  1. One before the container is started. (creating directories, granting them user:group).
  2. One after it is started for the first time : declaring the tablespace and creating the base. If I understand well the base image I took, it should be done after an entrypoint docker-entrypoint.sh has been run ?

What is the good way to write a Dockerfile creating a container having done all these steps ?

Upvotes: 0

Views: 445

Answers (2)

David Maze
David Maze

Reputation: 159722

The PostGIS image "is based on the official postgres image", so it should be able to use the /docker-entrypoint-initdb.d mechanism. Any files you put in that directory will be run the first time the database container is started. The postgis Dockerfile already uses this directory to install the PostGIS extensions into the default database.

That means you can put your build-time setup directly into the Dockerfile, and copy the startup-time script into that directory.

FROM postgis/postgis:12-3.0
RUN mkdir /tablespace && chown postgres:postgres /tablespace
COPY createdb.sql /docker-entrypoint-initdb.d/20-createdb.sql
# Use default ENTRYPOINT/CMD from base image

For the particular setup you describe, this may not be necessary. Each database runs in an isolated filesystem space and starts with an empty data directory, so there's not a specific need to create an alternate data directory; Docker style is to just run multiple databases if you need isolated storage. Similarly, the base postgres image will create a database for you at first start (named by the POSTGRES_DB environment variable).

Upvotes: 1

Efthymios Kasidakis
Efthymios Kasidakis

Reputation: 1

In order to run a container, your Dockerfile must be functional and completed. you must enter the queries in a bash file and in the last line you have to enter an ENTRYPOINT with this bash script

Upvotes: 0

Related Questions