PostgreSQL with Docker

From NovaOrdis Knowledge Base
Revision as of 06:37, 19 October 2018 by Ovidiu (talk | contribs)
Jump to navigation Jump to search

Internal

Overview

In its simplest form:

docker run postgres

command starts a transient PostgreSQL container instance that does not expose any port on the local host, it is initialized on the fly to allow access to any user and uses an anonymous local volume. To get a usable Postgres instance we can shut down and restart, and for which we can access the data directory independently, in case it is needed for debugging and troubleshooting, we should use create a dedicated named volume or a bind mount, initialize the database with a username and a password during the first initialization run and map ports to the local host.

Dedicated Storage

We prefer using a bind mount as it gives easy access to the stored state, in case we need to troubleshoot. A named volume can be also used.

docker run ...  --mount type=bind,source=/Users/ovidiu/runtime/docker-volumes/postgres,target=/var/lib/postgresql/data --name postgres ... postgres

Authenticated Access

When the container is run the first time, it goes through an initialization sequence, and if no specific authentication configuration is provided in form of environment variables, it will configure itself to allow unauthenticated access. To prevent that from happening, start the container for the first time as shown:

docker run --mount type=bind,source=/Users/ovidiu/runtime/docker-volumes/postgres,target=/var/lib/postgresql/data -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=<some-password> --name postgres postgres

This will initialized the database to allow access as admin/<some-password>.

Subsequent startups will not require specification of -e POSTGRES_USER and -e POSTGRES_PASSWORD, as long as we use the same local directory Postgres initialized its state on.

Exposing Ports on the Local Host

Postgres binds by default on port 5432 and this is the port published by the following command:

docker run ... -p 5432:5432/tcp  ...

Procedures

Database Initialization

Create a local directory /Users/ovidiu/runtime/docker-volumes/postgres and then execute the initialization run:

docker run --mount type=bind,source=/Users/ovidiu/runtime/docker-volumes/postgres,target=/var/lib/postgresql/data -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=<some-password> --name postgres-init-container postgres

Initialization log:

The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

Success. You can now start the database server using:

    pg_ctl -D /var/lib/postgresql/data -l logfile start


WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
waiting for server to start....2018-10-18 17:51:21.203 UTC [43] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2018-10-18 17:51:21.253 UTC [44] LOG:  database system was shut down at 2018-10-18 17:51:19 UTC
2018-10-18 17:51:21.269 UTC [43] LOG:  database system is ready to accept connections
 done
server started
CREATE DATABASE


/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*

waiting for server to shut down...2018-10-18 17:51:22.349 UTC [43] LOG:  received fast shutdown request
2018-10-18 17:51:22.351 UTC [43] LOG:  aborting any active transactions
.2018-10-18 17:51:22.356 UTC [43] LOG:  worker process: logical replication launcher (PID 50) exited with exit code 1
2018-10-18 17:51:22.356 UTC [45] LOG:  shutting down
2018-10-18 17:51:22.387 UTC [43] LOG:  database system is shut down
 done
server stopped

PostgreSQL init process complete; ready for start up.

2018-10-18 17:51:22.478 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2018-10-18 17:51:22.478 UTC [1] LOG:  listening on IPv6 address "::", port 5432
2018-10-18 17:51:22.482 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2018-10-18 17:51:22.546 UTC [61] LOG:  database system was shut down at 2018-10-18 17:51:22 UTC
2018-10-18 17:51:22.562 UTC [1] LOG:  database system is ready to accept connections

The container can be removed after initialization with:

docker stop postgres-init-container
docker rm postgres-init-container

Production Container Creation

docker run --mount type=bind,source=/Users/ovidiu/runtime/docker-volumes/postgres,target=/var/lib/postgresql/data -p 5432:5432/tcp --name postgres postgres

Note that the container initialized as shown above has only one user "admin", with all possible privileges, so for production you should consider creating regular users with less privileges. See Create User.

Lifecycle

docker stop postgres
docker start [-i] postgres

If actively experimenting or testing with it, it's probably a good idea to start it in interactive mode (-i). If you happen to close the terminal, you can reattach with:

docker attach postgres

Log Into the Container

docker exec -it postgres bash