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 stats to 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 -v

Cập nhật: 2026-05-16