Lab Docker Compose — All-in-one Setup
Single docker-compose.yml để chạy toàn bộ stack lab cho khóa.
Tags: attachment lab docker Liên quan: All Tuần chapters
1. Full Stack (mọi service)
# docker-compose.yml
version: '3.9'
services:
# ========== Postgres ==========
postgres:
image: pgvector/pgvector:pg16
environment:
POSTGRES_PASSWORD: lab
POSTGRES_DB: labdb
ports: ["5432:5432"]
volumes:
- pg_data:/var/lib/postgresql/data
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
command: >
postgres
-c shared_buffers=512MB
-c work_mem=16MB
-c maintenance_work_mem=128MB
-c wal_level=logical
-c max_replication_slots=10
-c max_wal_senders=10
-c max_wal_size=2GB
-c log_min_duration_statement=100
-c log_checkpoints=on
-c log_lock_waits=on
-c track_io_timing=on
-c shared_preload_libraries='pg_stat_statements,auto_explain,pgaudit'
-c pg_stat_statements.track=all
-c auto_explain.log_min_duration=500
-c auto_explain.log_analyze=on
postgres-replica:
image: pgvector/pgvector:pg16
environment:
POSTGRES_PASSWORD: lab
ports: ["5433:5432"]
depends_on: [postgres]
command: >
bash -c "
until pg_basebackup -h postgres -U postgres -D /var/lib/postgresql/data -P -X stream -W; do sleep 5; done;
touch /var/lib/postgresql/data/standby.signal;
echo \"primary_conninfo = 'host=postgres user=postgres password=lab'\" >> /var/lib/postgresql/data/postgresql.auto.conf;
postgres
"
pgbouncer:
image: edoburu/pgbouncer:latest
environment:
DATABASE_URL: "postgres://postgres:lab@postgres:5432/labdb"
POOL_MODE: transaction
MAX_CLIENT_CONN: 1000
DEFAULT_POOL_SIZE: 20
MAX_PREPARED_STATEMENTS: 100
AUTH_TYPE: scram-sha-256
ports: ["6432:6432"]
depends_on: [postgres]
# ========== MySQL (Bonus chapter) ==========
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: lab
MYSQL_DATABASE: labdb
ports: ["3306:3306"]
command: >
mysqld
--default-authentication-plugin=mysql_native_password
--innodb-buffer-pool-size=512M
--innodb-redo-log-capacity=512M
--slow-query-log=ON
--long-query-time=0.1
--log-bin=mysql-bin
--binlog-format=ROW
--gtid-mode=ON
--enforce-gtid-consistency=ON
volumes:
- mysql_data:/var/lib/mysql
# ========== Redis / Valkey ==========
redis:
image: redis:7-alpine
ports: ["6379:6379"]
command: >
redis-server
--maxmemory 1gb
--maxmemory-policy allkeys-lfu
--appendonly yes
--appendfsync everysec
--slowlog-log-slower-than 10000
volumes:
- redis_data:/data
# Optional: replace redis with valkey
# valkey:
# image: valkey/valkey:8
# ports: ["6379:6379"]
# ========== MongoDB ==========
mongo:
image: mongo:7
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: lab
ports: ["27017:27017"]
volumes:
- mongo_data:/data/db
# ========== Elasticsearch / OpenSearch ==========
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms1g -Xmx1g
ports: ["9200:9200", "9300:9300"]
volumes:
- es_data:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:8.13.0
environment:
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
ports: ["5601:5601"]
depends_on: [elasticsearch]
# ========== ClickHouse ==========
clickhouse:
image: clickhouse/clickhouse-server:24.5
ports: ["8123:8123", "9000:9000"]
ulimits:
nofile:
soft: 262144
hard: 262144
volumes:
- ch_data:/var/lib/clickhouse
# ========== Kafka + Schema Registry ==========
zookeeper:
image: confluentinc/cp-zookeeper:7.5.0
environment:
ZOOKEEPER_CLIENT_PORT: 2181
kafka:
image: confluentinc/cp-kafka:7.5.0
depends_on: [zookeeper]
ports: ["9092:9092"]
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
# ========== Debezium (CDC) ==========
debezium:
image: debezium/connect:2.5
depends_on: [kafka]
ports: ["8083:8083"]
environment:
BOOTSTRAP_SERVERS: kafka:29092
GROUP_ID: connect
CONFIG_STORAGE_TOPIC: connect_configs
OFFSET_STORAGE_TOPIC: connect_offsets
STATUS_STORAGE_TOPIC: connect_statuses
# ========== Qdrant (Vector) ==========
qdrant:
image: qdrant/qdrant:latest
ports: ["6333:6333", "6334:6334"]
volumes:
- qdrant_data:/qdrant/storage
# ========== Observability ==========
prometheus:
image: prom/prometheus:latest
ports: ["9090:9090"]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports: ["3000:3000"]
environment:
GF_SECURITY_ADMIN_PASSWORD: lab
postgres_exporter:
image: prometheuscommunity/postgres-exporter:latest
environment:
DATA_SOURCE_NAME: "postgresql://postgres:lab@postgres:5432/labdb?sslmode=disable"
ports: ["9187:9187"]
depends_on: [postgres]
pgbouncer_exporter:
image: prometheuscommunity/pgbouncer-exporter:latest
environment:
PGBOUNCER_EXPORTER_HOST: 0.0.0.0
PGBOUNCER_EXPORTER_PORT: 9127
PGBOUNCER_AUTH_USER: pgbouncer
PGBOUNCER_AUTH_PASS: lab
PGBOUNCER_AUTH_HOST: pgbouncer
ports: ["9127:9127"]
# ========== Admin UIs ==========
pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: lab@local
PGADMIN_DEFAULT_PASSWORD: lab
ports: ["5050:80"]
redisinsight:
image: redislabs/redisinsight:latest
ports: ["5540:5540"]
mongo-express:
image: mongo-express
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: lab
ME_CONFIG_MONGODB_SERVER: mongo
ports: ["8081:8081"]
depends_on: [mongo]
volumes:
pg_data: {}
mysql_data: {}
redis_data: {}
mongo_data: {}
es_data: {}
ch_data: {}
qdrant_data: {}2. Init SQL (postgres)
-- postgres/init.sql
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS pgstattuple;
CREATE EXTENSION IF NOT EXISTS pg_buffercache;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS btree_gin;
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE EXTENSION IF NOT EXISTS hstore;
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS uuid-ossp;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pageinspect;
CREATE EXTENSION IF NOT EXISTS pgaudit;
-- Replication user
CREATE USER replicator WITH REPLICATION LOGIN PASSWORD 'lab';
-- Monitor user
CREATE USER monitor WITH PASSWORD 'lab';
GRANT pg_monitor TO monitor;3. Prometheus Config
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: postgres
static_configs:
- targets: ['postgres_exporter:9187']
- job_name: pgbouncer
static_configs:
- targets: ['pgbouncer_exporter:9127']4. Quick Start
# Spin up
docker compose up -d
# Check
docker compose ps
# Postgres
psql -h localhost -U postgres -d labdb # password: lab
# Through PgBouncer
psql -h localhost -p 6432 -U postgres -d labdb
# Redis
redis-cli -h localhost
# MongoDB
mongosh "mongodb://root:lab@localhost:27017"
# Elasticsearch
curl http://localhost:9200/
# ClickHouse
clickhouse-client -h localhost
# Kafka
docker compose exec kafka kafka-topics --bootstrap-server localhost:9092 --list
# Qdrant
curl http://localhost:6333/
# Grafana → http://localhost:3000 (lab / lab)
# Kibana → http://localhost:5601
# pgAdmin → http://localhost:5050 (lab@local / lab)5. Resource Sizing
This stack ~6GB RAM, 4 CPU. For laptop:
- Comment out services you don’t need per tuần
- Run
docker statsto verify
Per-tuần selection:
- Tuần 01-09: just postgres + pgbouncer + observability
- Tuần 10: + redis
- Tuần 11: + mongo (or skip if focusing DynamoDB local)
- Tuần 12: + mongo
- Tuần 13: + elasticsearch + kibana
- Tuần 14: + clickhouse
- Tuần 15: + qdrant
- Bonus CDC: + kafka + debezium
6. Cleanup
# Stop
docker compose down
# Stop + delete data
docker compose down -vCập nhật: 2026-05-16