Everything in this lab runs in Docker first. Before ClickHouse internals mean anything, it helps to be precise about what actually happens between typing docker compose up and having a server listening on your machine.
From image to running server
A Docker image is a read-only template — a frozen filesystem plus metadata about how to run it. 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.
The image is pulled once and cached locally. Every docker compose up after that reuses it — only the container is created and destroyed. The volume is what makes this safe: docker compose down removes the container but leaves clickhouse_data untouched; only down -v deletes the volume, and with it, your data.
The compose file
This repo's clickhouse/compose.yaml is intentionally minimal — one service, two ports, one named volume:
services:
clickhouse:
image: clickhouse/clickhouse-server:25.8.28.1
ports:
- "8123:8123" # HOST : CONTAINER
- "9000:9000"
volumes:
- clickhouse_data:/var/lib/clickhouse
volumes:
clickhouse_data:Port mapping reads as host:container. The container always listens on 8123 and 9000 internally; the left-hand side is just where that gets exposed on your machine. Two protocols, two ports:
8123— HTTP interface. Used by the web UI, most client libraries, and simplecurlqueries.9000— native TCP protocol. Used byclickhouse-clientand drivers that want the faster binary protocol.
Environment & credentials
.env supplies the database name, user, and password ClickHouse bootstraps on first start — first start only. Changing these after the volume already has data does nothing until you wipe the volume, because the users and database were already created on disk.
CLICKHOUSE_DB=learning
CLICKHOUSE_USER=admin
CLICKHOUSE_PASSWORD=admin123Everyday 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 exec -it clickhouse clickhouse-client
# tail logs
docker logs -f clickhousedown -v is the one command here that is not reversible — it deletes the named volume, and every table in it, permanently. If you only want to restart clean without losing data, use down (no -v) or just stop.Verifying it works
Once the container is up, connect from your host on either port and run a few sanity queries:
SELECT version();
SELECT now();
SELECT number FROM numbers(10);numbers(10) is ClickHouse's built-in table function for generating rows on the fly — useful throughout this module for quick experiments without needing real data first.