Introduction to Running PostgreSQL in a Docker Container using Docker Compose
In this blog post, we will explore how to run PostgreSQL in a Docker container using Docker Compose. We will also break down and explain the init-user-db.sh script that is executed at startup to initialize the PostgreSQL tables. Running PostgreSQL in a Docker container provides several benefits, including ease of deployment, portability, and isolation. So let’s dive in and understand the process!

This post uses Docker Compose V2, if you are still using V1, consider upgrading otherwise use
docker-composeinstead ofdocker compose.
Why Run PostgreSQL in a Docker Container?
Running PostgreSQL in a Docker container offers numerous advantages. Here are a few key benefits:
Easy Deployment: Docker simplifies the deployment process by encapsulating PostgreSQL and its dependencies into a container, making it easy to set up and manage.
Portability: Docker containers are self-contained and can be run on any system that supports Docker, ensuring consistent behavior across different environments.
Isolation: Running PostgreSQL in a container provides isolation from the host system, preventing potential conflicts with existing installations or dependencies.
Setting Up PostgreSQL in a Docker Container with Docker Compose
Before we start, ensure that you have Docker and Docker Compose installed on your system. Once both are set up, you can proceed with the following steps:
- Create a Docker Compose file: Open a text editor and create a file called
docker-compose.yml. Copy and paste the following contents into the file:
version: '3.3'
services:
postgres:
container_name: my-postgres
image: postgres:latest
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- "5432:5432"
volumes:
- ./data:/var/lib/postgresql/data/pgdata
- ./init-user-db.sh:/docker-entrypoint-initdb.d/init-user-db.sh
In this Docker Compose configuration:
The
postgresservice is defined with the specified container name (my-postgres), the latest PostgreSQL image (postgres:latest), and therestartpolicy set toalwaysto ensure that the container restarts automatically if it stops.The
environmentsection sets the PostgreSQL environment variables (POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DB) using the provided values from the environment. In this example I have a.envfile in the same directory as thedocker-compose.ymlfile, which means that there is no need for sensitive data such as passwords to be stored in our infrastructure code. This.envfile could be replaced by git secrets in part of a pipeline deployment.The
portssection maps the host machine’s port5432to the container’s port5432, allowing you to access the PostgreSQL database from your host machine.The
volumessection mounts two directories:./data:/var/lib/postgresql/data/pgdata: This maps the./datadirectory on your host machine to the/var/lib/postgresql/data/pgdatadirectory inside the container. It allows you to persist the PostgreSQL data files across container restarts../init-user-db.sh:/docker-entrypoint-initdb.d/init-user-db.sh: This mounts theinit-user-db.shscript from your host machine to the/docker-entrypoint-initdb.d/init-user-db.shpath inside the container. This script will be executed during container startup to initialize the PostgreSQL tables.
- Start the PostgreSQL container: Open your terminal or command prompt, navigate to the directory containing the
docker-compose.ymlfile, and run the following command:
docker compose up -d
The -d flag runs the containers in detached mode, allowing
them to run in the background.
Breaking Down the init-user-db.sh Script
The init-user-db.sh script is executed at startup to initialize the PostgreSQL tables. Let’s examine the script and understand its purpose:
#!/bin/bash
set -e
set -u
export PGDATABASE=${POSTGRES_DB}
export PGUSER=${POSTGRES_USER}
export PGPASSWORD=${POSTGRES_PASSWORD}
RUN_PSQL="psql -X --set AUTOCOMMIT=on --set ON_ERROR_STOP=on "
${RUN_PSQL} <<SQL
CREATE TABLE public.mytable
(
id uuid NOT NULL,
sensor_name text NOT NULL,
battery double precision,
humidity double precision,
link_quality double precision,
temperature double precision,
voltage integer,
"time" timestamp with time zone NOT NULL
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.mytable
OWNER to dbadm;
SQL
Here’s a breakdown of the script:
The
set -eandset -ucommands ensure that the script exits immediately if any command fails or encounters an unset variable.The
exportstatements set environment variables to configure the PostgreSQL connection. The variablesPGDATABASE,PGUSER, andPGPASSWORDare assigned values based on the corresponding Docker environment variables (derived from the.envfile).The
RUN_PSQLvariable defines thepsqlcommand with specific options.-Xdisables transaction management,--set AUTOCOMMIT=onensures that each command is executed in its own transaction, and--set ON_ERROR_STOP=onstops the script execution if any error occurs.The
${RUN_PSQL} <<SQLsyntax starts a here-document that allows us to provide SQL commands inline.The SQL commands enclosed within the
SQLdelimiter create a table namedmytablein thepublicschema with the specified columns and data types. TheALTER TABLEstatement sets the owner of the table todbadmif the table already exists.
With this updated Docker Compose configuration, you can easily manage and deploy your PostgreSQL container along with the initialization script. Running docker compose up -d will start the containers and execute the init-user-db.sh script to initialize the PostgreSQL tables.
Conclusion
In this blog post, we have learned how to run PostgreSQL in a Docker container using Docker Compose. We have seen the advantages of running PostgreSQL in a container and how to set it up with the docker-compose.yml file. Additionally, we have explored the init-user-db.sh script and its role in initializing the PostgreSQL tables.
By leveraging Docker and Docker Compose, you can easily deploy and manage PostgreSQL in a portable and isolated environment. This approach brings flexibility and scalability to your PostgreSQL deployments, making it an ideal choice for various applications.
Hopefully this blog post has been helpful in understanding the process of running PostgreSQL in a Docker container using Docker Compose. Stay tuned for more exciting tutorials and guides. Consider buying me a coffee to feed the addiction and help me solve more automation headaches!