Docker w module Chat
Szczegółowa dokumentacja wykonania Chat w kontenerach Docker.
Przegląd
Docker executor w module Chat umożliwia:
- ✅ Izolowane środowisko wykonania dla każdej sesji
- ✅ Automatyczne klonowanie repozytoriów Git
- ✅ Instalację Claude CLI w kontenerze
- ✅ Pełny kontekst projektu bez modyfikacji lokalnego środowiska
- ✅ Łatwe zarządzanie zależnościami i wersjami
Architektura
Konfiguracja Docker worker
config.yml
Worker musi mieć docker_compose_path:
workers:
- name: "SemBot Chat"
path: "/Users/user/Projects/sembot-chat"
tags: ["sb"]
docker_compose_path: "/path/to/docker/sembot-chat"
git_repository: "[email protected]:org/sembot-angular.git,[email protected]:org/sembot-laravel.git"
git_branch: "master,master"Struktura katalogu Docker
embedded/resources/docker/sembot-chat/
├── docker-compose.yml
├── start.sh
└── scripts/ (opcjonalne, można współdzielić)docker-compose.yml
Przykład kompletnego pliku
services:
chat-worker:
image: node:18-alpine
container_name: chat-${SESSION_ID}
working_dir: /app
environment:
SESSION_ID: ${SESSION_ID}
WORKER_TAGS: ${WORKER_TAGS}
WORKER_REPOS: ${WORKER_REPOS}
WORKER_BRANCHES: ${WORKER_BRANCHES}
volumes:
# CONFIG - git credentials
- ~/.ssh:/root/.ssh:ro
- ~/.gitconfig:/root/.gitconfig:ro
- ~/.git-credentials:/root/.git-credentials:ro
# CLAUDE - global config from host
- ~/.claude:/root/.claude
- ~/.claude.json:/root/.claude.json
- ~/.claude.json.backup:/root/.claude.json.backup
# GEMINI - global config from host
- ~/.gemini:/root/.gemini
# CODEX
- ~/.codex:/root/.codex
# SCRIPTS
- ./start.sh:/app/start.sh:ro
- ./scripts:/app/scripts:ro
# CHAT SESSION - only chat directory is mounted
- ${CHAT_DIR}/${SESSION_ID}:/app/chat
# CLAUDE CODE RESOURCES - worker-specific configs
- ./resources/.claude:/app/worker/.claude:ro
- ./resources/.gemini:/app/worker/.gemini:ro
command: ["sh", "/app/start.sh"]
restart: unless-stopped
networks:
- chat-network
networks:
chat-network:
driver: bridgeZmienne środowiskowe
| Zmienna | Opis | Przykład |
|---|---|---|
SESSION_ID | UUID sesji chat | abc123-def456-... |
WORKER_TAGS | Tagi workera (rozdzielone przecinkami) | sbf,sb |
WORKER_REPOS | Repozytoria Git (rozdzielone przecinkami) | [email protected]:org/repo1.git,[email protected]:org/repo2.git |
WORKER_BRANCHES | Gałęzie Git (rozdzielone przecinkami) | master |
CHAT_DIR | Katalog .chat | /path/to/.chat |
Volumes
Git credentials (read-only)
- ~/.ssh:/root/.ssh:ro
- ~/.gitconfig:/root/.gitconfig:ro
- ~/.git-credentials:/root/.git-credentials:roMontuje klucze SSH i konfigurację Git z hosta do kontenera (tylko do odczytu).
Claude config (read-write)
- ~/.claude:/root/.claude
- ~/.claude.json:/root/.claude.json
- ~/.claude.json.backup:/root/.claude.json.backupMontuje globalną konfigurację Claude z hosta. Container może modyfikować historię sesji.
Gemini config (read-write)
- ~/.gemini:/root/.geminiMontuje konfigurację Gemini (jeśli używany).
Scripts (read-only)
- ./start.sh:/app/start.sh:ro
- ./scripts:/app/scripts:roMontuje skrypty startowe i wspólne skrypty pomocnicze.
Chat session directory (read-write)
- ${CHAT_DIR}/${SESSION_ID}:/app/chatMontuje katalog sesji chat:
.chat/abc123-def456-.../
├── chat.json
├── container.log
├── messages/
└── llm_outputs/Container zapisuje tutaj:
- Logi kontenera (
container.log) - Q&A pairs (
messages/msg_*.json) - Raw output LLM (
llm_outputs/*.json)
Worker-specific resources (read-only)
- ./resources/.claude:/app/worker/.claude:ro
- ./resources/.gemini:/app/worker/.gemini:roMontuje zasoby Claude Code specyficzne dla workera (np. custom prompts, hooks).
Image
Używamy node:18-alpine jako bazowego image:
- Lekki obraz Alpine Linux
- Node.js 18 (wymagane dla Claude CLI)
- Małe zużycie dysku i pamięci
Możesz użyć innych obrazów:
node:20-alpine- nowsza wersja Nodeubuntu:22.04- pełny Ubuntu (większy)- Custom Dockerfile z dodatkowymi zależnościami
Network
networks:
chat-network:
driver: bridgeKażda sesja ma własną sieć Docker. Izolacja między sesjami.
start.sh
Główny skrypt startowy kontenera.
Przykład
#!/bin/sh
set -e
# Redirect all output to log file in chat directory
LOG_FILE="/app/chat/container.log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "$(date): Container started for session: $SESSION_ID"
SCRIPTS_DIR="/app/scripts"
# 1. Install dependencies
if [ -f "${SCRIPTS_DIR}/init_dependencies.sh" ]; then
echo "$(date): 📦 Installing dependencies..."
sh ${SCRIPTS_DIR}/init_dependencies.sh
else
echo "$(date): ⚠️ init_dependencies.sh not found"
fi
# 2. Install Claude CLI
if [ -f "${SCRIPTS_DIR}/claude_install.sh" ]; then
echo "$(date): ⬇️ Installing Claude CLI..."
sh ${SCRIPTS_DIR}/claude_install.sh
else
echo "$(date): ⚠️ claude_install.sh not found"
fi
# 3. Setup SSH
if [ -f "${SCRIPTS_DIR}/ssh_setup.sh" ]; then
echo "$(date): 🔑 Setting up SSH..."
sh ${SCRIPTS_DIR}/ssh_setup.sh
else
echo "$(date): ⚠️ ssh_setup.sh not found"
fi
# 4. Validate and setup Claude config
if [ -f "/root/.claude.json.backup" ]; then
echo "$(date): 🔧 Setting up Claude config..."
if jq empty /root/.claude.json.backup 2>/dev/null; then
echo "$(date): ✅ Claude config is valid"
# Overwrite without deletion to avoid "Resource busy" error
cat /root/.claude.json.backup > /root/.claude.json
echo "$(date): ✅ Claude config copied"
else
echo "$(date): ❌ Claude config is invalid JSON"
exit 1
fi
else
echo "$(date): ⚠️ No Claude config backup found"
fi
# 5. Clone repositories
if [ -f "${SCRIPTS_DIR}/project_repositories_multi.sh" ]; then
echo "$(date): 📂 Cloning repositories..."
sh ${SCRIPTS_DIR}/project_repositories_multi.sh
else
echo "$(date): ⚠️ project_repositories_multi.sh not found"
fi
# 6. Verify Claude CLI installation
if command -v claude >/dev/null 2>&1; then
CLAUDE_VERSION=$(claude --version 2>&1 || echo "unknown")
echo "$(date): ✅ Claude CLI installed: $CLAUDE_VERSION"
else
echo "$(date): ❌ Claude CLI not found in PATH"
exit 1
fi
echo "$(date): ✅ Container ready for session: $SESSION_ID"
echo "$(date): 📁 Working directory: $(pwd)"
echo "$(date): 📋 Workers: $WORKER_TAGS"
# Keep container running
tail -f /dev/nullLogowanie
Wszystkie operacje są logowane do /app/chat/container.log:
exec > >(tee -a "$LOG_FILE") 2>&1To przekierowuje stdout i stderr do pliku i konsoli jednocześnie.
Kroki inicjalizacji
Install dependencies -
init_dependencies.sh- git, bash, curl, jq, openssh-client
Install Claude CLI -
claude_install.sh- Pobiera i instaluje Claude CLI
- Dodaje do PATH
Setup SSH -
ssh_setup.sh- Uruchamia ssh-agent
- Dodaje klucze SSH
- Testuje połączenie z GitHub
Validate Claude config
- Sprawdza czy
.claude.json.backupjest valid JSON - Kopiuje do
.claude.json(bez usuwania, aby uniknąć "Resource busy")
- Sprawdza czy
Clone repositories -
project_repositories_multi.sh- Parsuje
WORKER_REPOSiWORKER_BRANCHES - Klonuje każde repozytorium do
/app/worker/{repo-name}
- Parsuje
Verify installation
- Sprawdza czy
claudejest dostępny - Pokazuje wersję
- Sprawdza czy
Keep container running
tail -f /dev/null- utrzymuje kontener działającym
Wspólne skrypty
Skrypty w embedded/resources/docker/scripts/ są współdzielone między różnymi workerami.
init_dependencies.sh
#!/bin/sh
# Install basic dependencies needed for chat worker
apk add --no-cache \
git \
bash \
curl \
jq \
openssh-client
echo "✅ Dependencies installed"claude_install.sh
#!/bin/sh
# Install Claude CLI
CLAUDE_VERSION="latest"
INSTALL_DIR="/usr/local/bin"
# Download and install
curl -fsSL https://claude.ai/cli/install.sh | sh -s -- --install-dir "$INSTALL_DIR"
# Verify installation
if command -v claude >/dev/null 2>&1; then
echo "✅ Claude CLI installed: $(claude --version)"
else
echo "❌ Claude CLI installation failed"
exit 1
fissh_setup.sh
#!/bin/sh
# Setup SSH agent and add keys
# Start ssh-agent
eval $(ssh-agent -s)
# Add all SSH keys
for key in /root/.ssh/id_*; do
if [ -f "$key" ] && [ "${key##*.}" != "pub" ]; then
ssh-add "$key" 2>/dev/null || true
fi
done
# Test connection
ssh -T [email protected] 2>&1 | head -n 1
echo "✅ SSH setup complete"project_repositories_multi.sh
#!/bin/sh
# Clone multiple repositories (comma-separated)
if [ -z "$WORKER_REPOS" ]; then
echo "No repositories to clone"
exit 0
fi
# Convert comma-separated strings to arrays
IFS=',' read -ra REPO_ARRAY <<< "$WORKER_REPOS"
IFS=',' read -ra BRANCH_ARRAY <<< "$WORKER_BRANCHES"
INDEX=0
for REPO in "${REPO_ARRAY[@]}"; do
# Get corresponding branch (default: main)
BRANCH="${BRANCH_ARRAY[$INDEX]}"
[ -z "$BRANCH" ] && BRANCH="main"
# Extract repo name
REPO_NAME=$(basename "$REPO" .git)
TARGET_DIR="/app/worker/$REPO_NAME"
echo "Cloning $REPO_NAME (branch: $BRANCH)..."
# Clone repository
git clone --depth 1 --branch "$BRANCH" --single-branch "$REPO" "$TARGET_DIR"
if [ $? -eq 0 ]; then
echo "✅ Cloned: $REPO_NAME"
else
echo "❌ Failed to clone: $REPO_NAME"
fi
INDEX=$((INDEX + 1))
done
echo "✅ All repositories cloned"Workflow wykonania
1. Utworzenie sesji z Docker
2. Wysłanie wiadomości przez Docker
3. Zatrzymanie kontenera
Zarządzanie zasobami
CPU i pamięć
Domyślnie kontenery nie mają limitów. Możesz dodać:
services:
chat-worker:
deploy:
resources:
limits:
cpus: '1.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 1GDysk
Chat nie generuje dużo danych:
- Katalog sesji: ~10-50 MB
- Sklonowane repozytoria: zależnie od projektu (50-500 MB)
- Claude CLI: ~100 MB
Razem: ~200-700 MB na sesję
Czyszczenie
Automatyczne
Kontenery są usuwane po docker-compose down.
Ręczne
# Zatrzymaj wszystkie kontenery chat
docker ps | grep "chat-" | awk '{print $1}' | xargs docker stop
# Usuń wszystkie kontenery chat
docker ps -a | grep "chat-" | awk '{print $1}' | xargs docker rm
# Wyczyść volumes (UWAGA: usuwa dane!)
docker volume prune -fTroubleshooting Docker
Problem: Kontener nie startuje
Debug:
# Sprawdź logi Docker Compose
cd .docker/chat-{uuid}/
docker-compose logs
# Sprawdź logi kontenera
docker logs chat-{uuid}Częste przyczyny:
- Brak
docker_compose_pathw konfiguracji workera - Nieprawidłowe zmienne środowiskowe
- Brak dostępu do SSH keys
- Nieprawidłowy
.claude.json
Problem: Claude CLI nie działa
Debug:
# Wejdź do kontenera
docker exec -it chat-{uuid} sh
# Sprawdź instalację
which claude
claude --version
# Sprawdź PATH
echo $PATH
# Sprawdź config
cat /root/.claude.json | jq .Fix:
# Reinstaluj Claude CLI w kontenerze
docker exec -it chat-{uuid} sh -c "curl -fsSL https://claude.ai/cli/install.sh | sh"Problem: Nie może sklonować repozytorium
Debug:
# Sprawdź SSH w kontenerze
docker exec -it chat-{uuid} ssh -T [email protected]
# Sprawdź klucze SSH
docker exec -it chat-{uuid} ls -la /root/.ssh/
# Sprawdź zmienne środowiskowe
docker exec -it chat-{uuid} env | grep WORKERFix:
- Upewnij się że klucze SSH są zamontowane:
~/.ssh:/root/.ssh:ro - Sprawdź uprawnienia kluczy:
chmod 600 ~/.ssh/id_* - Dodaj klucze do ssh-agent w kontenerze
Problem: "Resource busy" przy kopiowaniu .claude.json
Przyczyna: Plik jest w użyciu przez montowanie volume
Fix: Użyj cat zamiast rm && cp:
cat /root/.claude.json.backup > /root/.claude.jsonProblem: Brak dostępu do plików w /app/chat
Debug:
# Sprawdź volume mounts
docker inspect chat-{uuid} | jq '.[0].Mounts'
# Sprawdź uprawnienia
docker exec -it chat-{uuid} ls -la /app/chat/Fix:
- Sprawdź czy
${CHAT_DIR}jest poprawnie ustawiony - Sprawdź uprawnienia katalogu
.chat/na hoście
Najlepsze praktyki
1. Używaj Alpine images
✅ node:18-alpine (100 MB) ❌ node:18 (900 MB)
2. Montuj tylko potrzebne katalogi
❌ Nie montuj całego home directory ✅ Montuj tylko .ssh, .claude, etc.
3. Używaj read-only volumes gdzie możliwe
- ~/.ssh:/root/.ssh:ro
- ./scripts:/app/scripts:ro4. Loguj wszystko do pliku
exec > >(tee -a "$LOG_FILE") 2>&1Ułatwia debugging przez /docker/logs endpoint.
5. Weryfikuj instalację przed użyciem
if command -v claude >/dev/null 2>&1; then
echo "✅ Claude CLI ready"
else
echo "❌ Claude CLI not found"
exit 1
fi6. Używaj shallow clone dla repozytoriów
git clone --depth 1 --single-branchSzybsze klonowanie, mniej miejsca.
7. Czyszcz stare kontenery regularnie
# Cron job do czyszczenia kontenerów starszych niż 7 dni
docker ps -a --filter "name=chat-" --format "{{.ID}} {{.CreatedAt}}" | \
awk '$2 < "'$(date -d '7 days ago' '+%Y-%m-%d')'" {print $1}' | \
xargs docker rm -fNastępne kroki
- Konfiguracja → - szczegóły konfiguracji workerów
- API Reference → - endpointy Docker management
- Troubleshooting → - więcej problemów i rozwiązań