Learn Labs
Foundations

Docker & Setup

Running PostgreSQL locally

Same as ClickHouse, everything here runs in Docker first. The image/container/volume model is identical across both modules — worth being precise about once.

From image to running server

A Docker image is a read-only template. A container is a running process created from that image, with its own writable layer on top. A volume is storage that lives outside the container's lifecycle, so data survives when the container is removed and recreated.

Docker Hubpostgres:17.6
pulls →
Imageread-only template
↓ runs as
Volumepostgres_data
mounts ←
Containerrunning process

The image is pulled once and cached locally. Every docker compose up after that reuses it — only the container is created and destroyed. docker compose down removes the container but leaves postgres_data untouched; only down -v deletes the volume, and with it, every database in the cluster.

The compose file

This repo's postgres/compose.yaml is intentionally minimal — one service, one port, one named volume:

services:
postgres:
  image: postgres:17.6
  ports:
    - "5432:5432"   # HOST : CONTAINER
  volumes:
    - postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:

Unlike ClickHouse's dual HTTP/native-protocol ports, Postgres exposes a single port: 5432, the Postgres wire protocol. Every client — psql, drivers, connection poolers — speaks it.

Environment & credentials

.env supplies the database name, user, and password Postgres bootstraps on first start — first start only. Changing these after the volume already has data does nothing until you wipe the volume, because the role and database were already created on disk.

POSTGRES_DB=learning
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin123

Everyday commands

# start (detached)
docker compose up -d

# stop the container, keep the volume
docker compose stop

# remove the container, keep the volume
docker compose down

# remove container AND delete all data
docker compose down -v

# open a SQL shell inside the container
docker compose exec postgres psql -U admin -d learning

# tail logs
docker compose logs -f postgres

Verifying it works

Once the container is up, connect and run a few sanity commands. The first two are plain SQL; the last two are psql meta-commands (client-side shortcuts, not SQL — they start with a backslash and aren't sent to the server as queries):

SELECT version();
SELECT now();
\l    -- list databases
\dt   -- list tables in the current schema

With the server running and reachable, the next lesson, Architecture, covers what's actually happening on the other end of that connection.

On this page