Use Postgres DB with Docker.
In this article i will show you how you can create a Postgres container, create tables if not exist and import data to the tables from csv…
In this article i will show you how you can create a Postgres container, create tables if not exist and import data to the tables from csv files if the tables are empty.
Create the following file as docker-compose.yml
version: "3.8"
services:
db:
container_name: postgres
image: postgres:14.1-alpine
restart: always
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=shops_db
volumes:
- db:/var/lib/postgresql/data
volumes:
db:
driver: localThis docker compose file will create a container that will use the postgres:14.1-alpine image. The database will be named shops_db which the username and password is postgres and will accept connections on port 5432 of the host. The database data will be stored in a Docker volume named db which will be mounted to the /var/lib/postgresql/data directory of the container.
To start the container we enter:
$ docker compose upIf everything goes fine you should see the following message on the console which means that postgres is ready.
database system is ready to accept connectionsCreating Schemas when the container is starting
You can create schemas with the usual way: open a database administrator tool and create your schemas, but there is the docker way as well which is automated.
Create the following file as create_tables.sql
create table if not exists "pets" (
"name" varchar(255) null default null,
"age" integer null default null);Then modify the docker-compose.yml file to match these changes
version: "3.8"
services:
db:
container_name: postgres
image: postgres:14.1-alpine
restart: always
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=shops_db
volumes:
- db:/var/lib/postgresql/data
- ./create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
volumes:
db:
driver: localOn the volumes section of the file we added a map of the sql file we created to the /docker-entrypoint-initdb.d/ directory of the container, any file in this directory will be executed.
Running docker compose up should print in the in console the following message
postgres | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/create_tables.sql
postgres | CREATE TABLEThis indicates that the create table command in the SQL file executed and created the table in our database.
Importing CSV files to the database
Like the previous example there are many ways to import a CSV to a table, but there is the Docker way as well, to do this we need to create a helper container that will be insert the CSV file to the table only when the Database is listening for connections and only if the table has a row count of zero.
Create the following file as pets.csv
name,age
"spike","2"
"rose","3"Now modify docker-compose.yml to match the following
version: "3.8"
services:
db:
container_name: postgres
image: postgres:14.1-alpine
restart: always
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=shops_db
volumes:
- db:/var/lib/postgresql/data
- ./create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
import_csv:
container_name: postgres_helper
image: postgres:14.1-alpine
command:
- sh
- -c
- |
while ! pg_isready -d shops_db -U postgres -h db -p 5432 -q -d shops_db -U postgres -h db -p 5432 -q; do echo 'postgres still not up' ; sleep 10; done
if [ $(psql postgres://postgres:postgres@db:5432/shops_db -tAc "SELECT COUNT(*) FROM pets") -eq 0 ]
then
psql postgres://postgres:postgres@db:5432/shops_db -c "\copy pets FROM '/var/lib/postgresql/csv/pets.csv' DELIMITER ',' CSV HEADER;"
fi
depends_on:
- db
volumes:
- ./pets.csv:/var/lib/postgresql/csv/pets.csv
volumes:
db:
driver: localWe added another container named import_csv this container live only to import the csv files and will exit then. The command section of the file are actually shell commands executed on the import_csv container, the line staring with while uses the pg_isready tool and waits until the main container named db accepts for connections, then the if line queries the database if the pets table has zero rows, if yes then imports the csv file with the copy command. Note that we need also to mount the pets.csv file to the container in order to be accessible.
if we run docker compose up again we should see
postgres | 2023-02-22 19:10:45.660 UTC [1] LOG: database system is ready to accept connections
postgres_helper | COPY 2
postgres_helper exited with code 0The COPY 2 means that two lines imported from the csv
if we stop the container and re-run it will not do any imports or re-create the table because the table exist and have data, but if we stop the container with the -v parameter which deletes any used resources it will re-create them from the start.
Conclusion
In this article we saw how to create a Postgres container, create tables if not exist and import data to the tables from csv files if the tables are empty