How to install and deploy PostgreSQL as a Docker container
PostgreSQL , also known as Postgres, is a leading object-relational database system. It is popular because it is highly compliant with the SQL standard and includes additional features that simplify processing complex data sets at scale.
PostgreSQL uses a traditional client-server architecture, so you need to run it independently from your application code. In this post, we will deploy a PostgreSQL server instance as a Docker container. This avoids adding packages to your host and helps isolate the database from the rest of your stack. Before continuing, make sure you have Docker installed.
PostgreSQL has an official image on Docker Hub, which comes in several different variants. Tags allow us to choose between major PostgreSQL versions from v9 to v14, and choose the operating system to use as the base image. Alpine , Debian Stretch , and Debian Bullseye are provided .
For the purpose of this tutorial, we will use postgres:14
the PostgreSQL 14 tag, which is available on Bullseye. We are also free to choose a different version to suit our requirements.
docker run
Start the PostgreSQL container
using the command:
$ docker run -d \
--name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD=<password> \
-v postgres:/var/lib/postgresql/data \
postgres:14
We must provide a value for the POSTGRES_PASSWORD environment variable. This defines the password that will be assigned to the default superuser account of Postgres. The username defaults to postgres but can be changed by setting the POSTGRES_USER environment variable.
-v
The option is used to mount a Docker volume to the PostgreSQL container's data directory. This references a named volume called postgres; Docker will create it or reattach the volume if it already exists. We should use volumes to store our database outside of the container. If not, our data will be used when the container is stopped.
By default, PostgreSQL listens on port 5432. The container port is bound to port 5432 on the Docker host using the -p option. The -d flag is used to start the container in detached mode, effectively making it a background service that runs until stopped by docker stop.
Provide password as a file
If you are uncomfortable with providing the superuser password as a plain text CLI flag, we can inject it as a file via a volume. The POSTGRES_PASSWORD_FILE environment variable should then be set to indicate the path to that file to Postgres:
$ docker run -d \
--name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD_FILE=/run/secrets/postgres-password \
-v ./postgres-password.txt:/run/secrets/postgres-password
-v postgres:/var/lib/postgresql/data \
postgres:14
This also works for POSTGRES_USER and other supported environment variables.
Connect to your database
Since PostgreSQL is bound to port 5432 above, we can connect to the database at localhost:5432 from any compatible client using the credentials assigned when launching the container as environment variables.
The Docker image also includes the psql binary that we can call using docker exec. This allows us to quickly interact with our database from a PostgreSQL shell inside the container.
$ docker exec -it postgres psql -U postgres
Connecting from other Docker containers
Creating a Docker network is the preferred way to access PostgreSQL from other containers on the same host. This avoids binding the Postgres server's ports and potentially exposing the service to the host's wider network.
Create a Docker network:
$ docker network create my-app
Use docker run with the --network option to start the Postgres container and connect to the network:
$ docker run -d \
--name postgres \
--network my-app \
-e POSTGRES_PASSWORD=<password> \
-v postgres:/var/lib/postgresql/data \
postgres:14
Now join your application container to the same network:
$ docker run -d
--name api
--network my-app
my-api:latest
Containers in the network can access Postgres using the postgres hostname, because this is the name assigned to the Postgres container. The connection is made using port 5432.
Configure PostgreSQL
We can pass PostgreSQL server options using the -c option after the image name in the docker run command:
$ docker run -d \
--name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD=<password> \
-v postgres:/var/lib/postgresql/data \
postgres:14 -c max_connections=100
Everything after the image name is passed to the command started in the container. For the Postgres image, this command will be the PostgreSQL server binary.
When you set values for multiple options, you can use a custom configuration file. You need to mount the file into the container using another Docker volume, and then provide a -c option to instruct Postgres where to look:
$ docker run -d \
--name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD=<password> \
-v ./postgres.conf:/etc/postgresql/postgresql.conf \
-v postgres:/var/lib/postgresql/data \
postgres:14 -c config_file=/etc/postgresql/postgresql.conf
This example uses a Docker bind mount to mount the postgres.conf file in the working directory into the container's /etc/postgresql directory.
Initialize the database
The Docker image supports seed files placed in the /docker-entrypoint-initdb.d directory. Any of the /etc/initdb.d or /etc/initdb.d files will be executed .sql
to .sql.gz
initialize the database. This happens after the default user account and postgres database are created. You can also add /etc/initdb.d .sh
files to run arbitrary shell scripts. All scripts are executed in alphabetical order.
This mechanism means that you only need a set of SQL or shell scripts named in the correct order to initialize the database. Install them into a new container using the docker run command with the -v option:
$ docker run -d \
--name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD=<password> \
-v ./db-seed-files/:/etc/docker-entrypoint-initdb.d \
-v postgres:/var/lib/postgresql/data \
postgres:14
The init scripts will only be used if the Postgres data directory is empty. For practical purposes, this means that they will be run the first time the container starts, and a new, empty volume will be attached.
Creating a custom database mirror
You can choose to package the configuration files and initialization scripts in your own Docker image. This will let anyone with access to the image start a new PostgreSQL instance pre-configured for your application. Here is a simple Dockerfile that can be used:
Dockerfile
FROM postgres:14 COPY postgres.conf /etc/postgresql/postgresql.conf COPY db-seed-files/ /etc/docker-entrypoint-initdb.d/ CMD ["-c", "config_file=/etc/postgresql/postgresql.conf"]
Build a custom image:
$ docker build -t custom-postgres:latest .
The build instructions in the Dockerfile will copy the PostgreSQL configuration files and initialization scripts from your working directory and embed them into the container image. Now you can start the database container without manually providing the resources:
$ docker run -d \
--name custom-postgres \
-p 5432:5432
-e POSTGRES_PASSWORD=<password> \
-v postgres:/var/lib/postgresql/data \
custom-postgres:latest
Should You Containerize Your Production Database?
Deciding whether to run your database in Docker can be difficult. Containerizing PostgreSQL makes the setup experience easier, but sometimes more challenging to maintain. Care needs to be taken when managing containers to avoid losing data in the future. Docker also adds a modest performance overhead, which is worth considering when the database is expected to handle very large data volumes.
The benefits of Docker are increased portability, ease of scalability, and developer efficiency. Containerizing your database allows anyone to launch a new instance using Docker without having to manually install and configure PostgreSQL first. Therefore, writing a Dockerfile for your PostgreSQL database to add your configuration files and SQL seed scripts is a great way to help developers quickly launch new environments.
Summarize
PostgreSQL is an advanced SQL-based database engine that adds object-relational capabilities. While you can choose to run a traditional deployment in production, using a containerized instance simplifies setup and helps developers quickly spin up their own infrastructure.
The most critical aspect of a Dockerized deployment is to ensure that you use volumes to store your data. This will allow you to stop, replace, and update your containers to higher versions of the image without losing your database. In addition to storage, you should also evaluate how you will connect to Postgres and avoid binding ports to your host unless necessary. When connecting from another container, it is best to use a shared Docker network for easy access.
For reprinting, please send an email to 1244347461@qq.com for approval. After obtaining the author's consent, kindly include the source as a link.
Related Articles
Killing a process ID in PostgreSQL
Publish Date:2025/04/27 Views:191 Category:PostgreSQL
-
Today, we will learn how to kill or stop a running query in the background when working with PostgreSQL database. This may happen if the frontend stops working but a background process is still running. In this case, you may want to kill th
Difference between timestamps with and without time zone in PostgreSQL
Publish Date:2025/04/27 Views:83 Category:PostgreSQL
-
This article will discuss the timestamp types in PostgreSQL and show how they differ. Timestamps in PostgreSQL In PostgreSQL, there are two types of timestamps. Timestamp without time zone Timestamp with time zone The first stores the local
Terminate the PostgreSQL connection
Publish Date:2025/04/11 Views:200 Category:PostgreSQL
-
In this article, we will learn how to terminate a PostgreSQL session. Any open connections are run by background processes or tasks, PSQL which may no longer exist despite exiting the user interface or command line tool. Use ps -ef or grep
Single query to rename and change column type in PostgreSQL
Publish Date:2025/04/11 Views:166 Category:PostgreSQL
-
This article describes how to rename a column and change its type in PostgreSQL using only a single query. Renaming and changing column types in MySQL In MySQL , if you want to change the column type and rename it, you can use a simple stat
Joining columns using Select in PostgreSQL
Publish Date:2025/04/11 Views:177 Category:PostgreSQL
-
MySQL PostgreSQL is an object-relational database system, which means it can support more complex data types than its competitors . Today we will learn how to use SELECT the operator to join the columns of a table. Using operators to || joi
Using CASE in PostgreSQL
Publish Date:2025/04/11 Views:124 Category:PostgreSQL
-
This article shows how to use the statement in PostgreSQL CASE . CASE How to use the statement in PostgreSQL case Statements are similar to those in general-purpose programming languages if-else . But in SQL, if you want to write IF-ELSE ,
Using NOT IN with subqueries in PostgreSQL
Publish Date:2025/04/11 Views:93 Category:PostgreSQL
-
NOT IN The inverts the result of NOT simply using IN the operator. NOT IN The right side of the operator must have a subquery in which multiple columns are returned to check whether the expression matches the data. NOT IN Tends to return tr
Using variables in PostgreSQL
Publish Date:2025/04/11 Views:171 Category:PostgreSQL
-
This article will demonstrate how we can declare and assign values to variables in PostgreSQL. In PostgreSQL, DECLARE variables are declared using Often you will need variables in your PL/SQL scripts. In DECLARE the section called , y
Connect to PostgreSQL using a password
Publish Date:2025/04/11 Views:171 Category:PostgreSQL
-
This article shows various ways to connect to PostgreSQL using a password. It can be through the command line, pgpass a file, PGPASSWORD an environment variable or a connection string. Connecting to PostgreSQL with a password using the comm