Zpět na domů

ClickHouse v Dockeru: spuštění analýzy za 2 minuty

Průvodce spuštěním ClickHouse v Dockeru se čtyřmi hotovými scénáři: základní docker run, docker-compose pro vývoj s healthcheck, cluster s ZooKeeper pro replikaci, plná sestava ClickHouse + Kafka + Redis pro gambling analýzu. Vysvětleny proměnné prostředí, montování vlastních konfigurací, typické chyby a jejich řešení.

ClickHouse v Dockeru: 4 hotové scénáře s compose soubory
Advertisement 728x90

ClickHouse v Dockeru: jak jsem přestal mít strach a spustil analytiku za 2 minuty

Proč Docker – a pak teprve všechno ostatní

Pamatuji si, jak jsem poprvé instaloval ClickHouse na produkci. Čtyři hodiny jsem strávil oprávněními, limity, ruční úpravou konfiguráků a restartováním systemd. Za měsíc přišel nový vývojář, snažili jsme se reprodukovat prostředí na jeho počítači – a znovu stejné hrábě.

Docker vyřešil všechno. Teď mám jednu složku s docker-compose.yml, kterou tahám mezi projekty. Analytický cluster zvednu za minutu, a když ho chci smazat – docker-compose down -v a je čisto. Žádný nepořádek v systému.

Níže jsou tři hotové scénáře, které používám v reálných projektech (od startupového pet-projektu až po sázkovou analytiku). Všechny konfiguráky jsou otestované na Docker Engine 24+.

Google AdInline article slot

Scénář 1. Rychlý start: jeden příkaz pro ověření hypotézy

Pro lokální vývoj a rychlé prototypování stačí jeden řádek. Ale ne jen docker run clickhouse/clickhouse-server – přidáme to, bez čeho je ClickHouse k ničemu: trvalé úložiště a přesměrování portů.

docker run -d \
  --name clickhouse-dev \
  --restart unless-stopped \
  -p 8123:8123 \
  -p 9000:9000 \
  -v clickhouse-data:/var/lib/clickhouse \
  -v clickhouse-logs:/var/log/clickhouse-server \
  -e CLICKHOUSE_DB=analytics \
  -e CLICKHOUSE_USER=developer \
  -e CLICKHOUSE_PASSWORD=devpass123 \
  -e CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1 \
  clickhouse/clickhouse-server:latest

Co je zde důležité:

  • -v clickhouse-data – pojmenovaný svazek, ne bind mount. Rozdíl: svazek spravuje Docker, neztrácí se při restartu, je rychlejší na macOS (důležité, pokud máte MacBook – bind mounty zpomalují kvůli synchronizaci).
  • CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1 – zapíná správu přístupu. Bez této proměnné se uživatel developer vytvoří, ale nemůže vytvářet nové účty. Popálili jsme se na tom: v produkci jsme museli lézt do kontejneru a opravovat users.xml.
  • Porty 9000 (nativní protokol) a 8123 (HTTP) – vždy otevírám oba, protože polovina klientů (DBeaver, TablePlus) pracuje přes HTTP a aplikace přes nativní ovladač.

Ověříme, že to funguje:

Google AdInline article slot
# HTTP rozhraní – nejjednodušší test
curl "http://localhost:8123/?query=SELECT+version()"
# Výstup: 24.8.2.3

Scénář 2. Docker Compose pro vývoj (jeden uzel, healthcheck)

Když je projekt trochu složitější, hned přecházím na docker-compose.yml. Tento soubor používám na svých noteboocích a dev serverech:

version: '3.8'

services:
  clickhouse:
    image: clickhouse/clickhouse-server:latest
    container_name: clickhouse-dev
    hostname: clickhouse
    ports:
      - "8123:8123"
      - "9000:9000"
      - "9009:9009"
    volumes:
      - clickhouse-data:/var/lib/clickhouse
      - clickhouse-logs:/var/log/clickhouse-server
      - ./config/config.d:/etc/clickhouse-server/config.d
      - ./config/users.d:/etc/clickhouse-server/users.d
    environment:
      CLICKHOUSE_DB: betting_analytics
      CLICKHOUSE_USER: analyst
      CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-analyst123}
      CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
      nproc:
        soft: 32768
        hard: 32768
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost:8123/ping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    restart: unless-stopped
    networks:
      - analytics-net

networks:
  analytics-net:
    driver: bridge

volumes:
  clickhouse-data:
  clickhouse-logs:

Proč jsem přidal ulimits: na produkci ClickHouse spotřebovává až 262144 otevřených souborových deskriptorů. Bez toho při velké zátěži spadne s chybou Too many open files. Tyto hrábě mě jednou stály tři hodiny, když server začal padat po 2 milionech řádků.

Healthcheck přes /ping: ClickHouse má vestavěný endpoint /ping (vrací "Ok.", pokud je živý). To je lepší než kontrola přes SELECT 1, protože nevyžaduje autentizaci a nezapisuje do logů.

Google AdInline article slot

Proměnná s výchozí hodnotou: ${CLICKHOUSE_PASSWORD:-analyst123} – pokud není nastavena v .env, heslo bude analyst123. Nezapomeňte na soubor .env pro skutečná tajemství.

Scénář 3. Produkční prostředí: ClickHouse + Zookeeper pro replikaci

Replikace tabulek ClickHouse vyžaduje ZooKeeper (nebo ClickHouse Keeper, ale pro začátek dávám klasiku). Tento compose používám pro testování odolnosti proti výpadkům:

version: '3.8'

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"
    volumes:
      - zookeeper-data:/var/lib/zookeeper
    networks:
      - ch-cluster

  clickhouse-1:
    image: clickhouse/clickhouse-server:latest
    container_name: clickhouse-1
    hostname: clickhouse-1
    ports:
      - "8123:8123"
      - "9000:9000"
    volumes:
      - ch1-data:/var/lib/clickhouse
      - ./config/replicated.xml:/etc/clickhouse-server/config.d/replicated.xml
    environment:
      CLICKHOUSE_DB: bets
      CLICKHOUSE_USER: replicator
      CLICKHOUSE_PASSWORD: rep_pass
      CLICKHOUSE_SHARD: 1
      CLICKHOUSE_REPLICA: 1
    depends_on:
      - zookeeper
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    networks:
      - ch-cluster

  clickhouse-2:
    image: clickhouse/clickhouse-server:latest
    container_name: clickhouse-2
    hostname: clickhouse-2
    ports:
      - "8124:8123"  # druhá instance na jiném portu
      - "9001:9000"
    volumes:
      - ch2-data:/var/lib/clickhouse
      - ./config/replicated.xml:/etc/clickhouse-server/config.d/replicated.xml
    environment:
      CLICKHOUSE_DB: bets
      CLICKHOUSE_USER: replicator
      CLICKHOUSE_PASSWORD: rep_pass
      CLICKHOUSE_SHARD: 1
      CLICKHOUSE_REPLICA: 2
    depends_on:
      - zookeeper
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    networks:
      - ch-cluster

networks:
  ch-cluster:
    driver: bridge

volumes:
  zookeeper-data:
  ch1-data:
  ch2-data:

A tady je obsah config/replicated.xml (montujeme do obou kontejnerů):

<clickhouse>
    <zookeeper>
        <node>
            <host>zookeeper</host>
            <port>2181</port>
        </node>
    </zookeeper>
    <remote_servers>
        <replicated_cluster>
            <shard>
                <replica>
                    <host>clickhouse-1</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-2</host>
                    <port>9000</port>
                </replica>
            </shard>
        </replicated_cluster>
    </remote_servers>
    <macros>
        <shard>1</shard>
        <replica>${CLICKHOUSE_REPLICA}</replica>
    </macros>
</clickhouse>

Kdy je to opravdu potřeba: Na produkčním projektu s kasinem jsme ztratili data, protože jsme vše drželi na jednom uzlu. Od té doby vždy zvedám alespoň dva replikované kontejnery pro testy. Rozdíl v ceně – dva kontejnery místo jednoho, ale klidný spánek je dražší.

Scénář 4. Kompletní gambling prostředí: ClickHouse + Kafka + Redis

Pro analytiku sázek v reálném čase potřebuji streamování (Kafka) a cache (Redis). Tento compose používám pro lokální ladění pipeline:

version: '3.8'

services:
  zookeeper-kafka:
    image: confluentinc/cp-zookeeper:latest
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"

  kafka:
    image: confluentinc/cp-kafka:latest
    depends_on:
      - zookeeper-kafka
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper-kafka:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    ports:
      - "9092:9092"

  redis:
    image: redis:7-alpine
    container_name: redis-cache
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-cachepass}
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s

  clickhouse:
    image: clickhouse/clickhouse-server:latest
    container_name: clickhouse-betting
    ports:
      - "8123:8123"
      - "9000:9000"
    volumes:
      - clickhouse-betting-data:/var/lib/clickhouse
      - ./clickhouse-kafka.xml:/etc/clickhouse-server/config.d/kafka.xml
    environment:
      CLICKHOUSE_DB: betting
      CLICKHOUSE_USER: streamer
      CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PW:-stream123}
      CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    depends_on:
      - kafka
      - redis

  kafka-connector:
    image: clickhouse/clickhouse-kafka-connect:latest
    container_name: kafka-connector
    depends_on:
      - kafka
      - clickhouse
    environment:
      CONNECT_BOOTSTRAP_SERVERS: kafka:9092
      CONNECT_GROUP_ID: clickhouse-group
      CONNECT_CONFIG_STORAGE_TOPIC: connect-configs
      CONNECT_OFFSET_STORAGE_TOPIC: connect-offsets
      CONNECT_STATUS_STORAGE_TOPIC: connect-status
      CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter
      CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
    ports:
      - "8083:8083"

volumes:
  redis-data:
  clickhouse-betting-data:

Jak to použít v kódu aplikace:

# Příklad v Pythonu: čteme sázku z Redis (cache), zapisujeme do ClickHouse
import redis
from kafka import KafkaProducer
import json

r = redis.Redis(host='localhost', port=6379, password='cachepass', decode_responses=True)
producer = KafkaProducer(bootstrap_servers='localhost:9092', value_serializer=lambda v: json.dumps(v).encode())

# Kontrola duplicity (detekce podvodů)
bet_id = "bet_12345"
if r.setnx(bet_id, "processed"):
    bet_event = {"user_id": 101, "amount": 500, "odds": 2.1}
    producer.send('bets-stream', bet_event)
else:
    print(f"Duplicitní sázka {bet_id} zablokována")

Jak připojit vlastní config.xml a nerozbít vše

Chyba, kterou jsem udělal pětkrát: připojil jsem celý config.xml, ale v nové verzi ClickHouse přidali povinné sekce. Kontejner spadl s Config has no <logger>.

Správný přístup: dávat pouze override do config.d/. Tady je struktura, která funguje:

docker-clickhouse/
├── docker-compose.yml
├── .env
├── config/
│   ├── config.d/
│   │   ├── memory.xml
│   │   ├── networks.xml
│   │   └── query-log.xml
│   └── users.d/
│       └── profiles.xml

Příklad config/config.d/memory.xml:

<clickhouse>
    <max_server_memory_usage>0.75</max_server_memory_usage>
    <max_memory_usage_for_all_queries>0</max_memory_usage_for_all_queries>
    <background_pool_size>16</background_pool_size>
</clickhouse>

Příklad config/users.d/profiles.xml:

<clickhouse>
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>
            <timeout_before_checking_execution_speed>0</timeout_before_checking_execution_speed>
        </default>
        <analyst>
            <readonly>1</readonly>
            <max_execution_time>300</max_execution_time>
        </analyst>
    </profiles>
</clickhouse>

Práce s clickhouse-client uvnitř kontejneru

Lézt do kontejneru pro rychlé dotazy je normální. Ale ne přes docker exec -it bash, ale přímo:

# Spustit dotaz
docker exec -it clickhouse-dev clickhouse-client --query "SELECT count() FROM system.tables"

# Interaktivní režim
docker exec -it clickhouse-dev clickhouse-client

# S heslem
docker exec -it clickhouse-dev clickhouse-client --password devpass123

Můj lifehack: Přidám alias do ~/.bashrc:

alias ch-cli='docker exec -it clickhouse-dev clickhouse-client'

Poté stačí napsat ch-cli a pracuji jako s lokální databází.

Proměnné prostředí: co opravdu funguje

Oficiální obraz nepodporuje všechny proměnné, které slibují fóra. Zde jsou ověřené:

Proměnná Účel Příklad
CLICKHOUSE_DB Výchozí název DB analytics
CLICKHOUSE_USER Administrátorský uživatel prod_user
CLICKHOUSE_PASSWORD Heslo strongpass
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT Zapnout RBAC (1/0) 1

Co NEFUNGUJE: CLICKHOUSE_HTTP_PORT, CLICKHOUSE_TCP_PORT – entrypoint je ignoruje. Měňte porty přes ports: v compose nebo přes připojení konfiguráku.

Kontrola funkčnosti: můj kompletní checklist

Po spuštění libovolného compose projdu:

# 1. HTTP ping (měl by vrátit "Ok.")
curl http://localhost:8123/ping

# 2. Verze přes HTTP
curl "http://localhost:8123/?query=SELECT+version()"

# 3. Vytvoření testovací tabulky
docker exec -it clickhouse-dev clickhouse-client --query "CREATE TABLE test.t (id UInt64) ENGINE = MergeTree ORDER BY id"

# 4. Vložení a výběr
docker exec -it clickhouse-dev clickhouse-client --query "INSERT INTO test.t SELECT number FROM numbers(1000)"
docker exec -it clickhouse-dev clickhouse-client --query "SELECT count() FROM test.t"

# 5. HTTP s autentizací (pokud jste zadali heslo)
curl -u developer:devpass123 "http://localhost:8123/?query=SELECT+user()"

Co dělat, když to nefunguje – typické chyby v Dockeru

Chyba: Code: 210. DB::NetException: Connection refused Řešení: kontejner se nestihl spustit. Přidejte depends_on a healthcheck, nebo ve skriptech udělejte sleep 5.

Chyba: Cannot create directory /var/lib/clickhouse: Permission denied Řešení: na hostiteli se SELinuxem přidejte :Z do svazku: -v ./data:/var/lib/clickhouse:Z. Nebo použijte pojmenované svazky.

Chyba: Max connections limit reached Řešení: zvyšte v konfiguráku: <max_connections>4096</max_connections> a restartujte.

Paměť kontejneru požírá hostitele Řešení: omezte přes Docker:

docker update --memory=4g --memory-swap=4g clickhouse-dev

Nebo v compose:

deploy:
  resources:
    limits:
      memory: 4G

Závěr: kdy Docker – a kdy ne

Docker je pro ClickHouse ideální v dev, stagingu a malých produkčních nasazeních. Ale pokud máte cluster s 10+ uzly a 100 TB dat – raději nativní balíčky bez zbytečných vrstev.

A zatím – vezměte můj compose pro gambling prostředí, změňte hesla a začněte počítat sázky v reálném čase.

Všechny konfiguráky jsou převzaty z reálných projektů. Jména změněna, hrábě zůstaly.


Předchozí:
Další: ClickHouse client: jak jsem se skamarádil s konzolí a HTTP API v gaming projektu

— Editorial Team

Advertisement 728x90

Číst dál