feat: docker-compose + Dockerfile + .env.example (#24)
* feat(docker): add docker-compose + Dockerfile + .env.example * docs(handoff): add pr-8 handoff + ADR-004 * docs(handoff): fix PR number * docs: update project map + handoff + ADR --------- Co-authored-by: opencode-agent <agent@slaid098.dev>
This commit is contained in:
parent
6005c88203
commit
b9daf31233
6 changed files with 191 additions and 1 deletions
28
.env.example
Normal file
28
.env.example
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# AI Provider
|
||||||
|
AI_PROVIDER_BASE_URL=https://your-ai-provider.example.com/v1/
|
||||||
|
AI_PROVIDER_API_KEY=your-api-key-here
|
||||||
|
|
||||||
|
# OpenCode Server
|
||||||
|
OPENCODE_SERVER_PASSWORD=your-opencode-server-password
|
||||||
|
|
||||||
|
# GitHub
|
||||||
|
GITHUB_TOKEN=your-github-token-here
|
||||||
|
|
||||||
|
# Context7 MCP
|
||||||
|
CONTEX7_API_KEY=your-context7-api-key-here
|
||||||
|
|
||||||
|
# Telegram (optional)
|
||||||
|
TELEGRAM_API_ID=your-telegram-api-id
|
||||||
|
TELEGRAM_API_HASH=your-telegram-api-hash
|
||||||
|
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
||||||
|
|
||||||
|
# Redis (optional)
|
||||||
|
REDIS_PASSWORD=your-redis-password
|
||||||
|
|
||||||
|
# Cloudflare Tunnel (optional — see separate tunnel repo)
|
||||||
|
CLOUDFLARE_TUNNEL_TOKEN=
|
||||||
|
|
||||||
|
# Antidetect Browser MCP
|
||||||
|
# Local: http://localhost:8765/mcp
|
||||||
|
# Remote: http://<your-server-ip>:8765/mcp
|
||||||
|
ANTIDETECT_BROWSER_MCP_URL=http://localhost:8765/mcp
|
||||||
38
Dockerfile
Normal file
38
Dockerfile
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
FROM node:20-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
openssh-client \
|
||||||
|
autossh \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
chromium \
|
||||||
|
gnupg \
|
||||||
|
docker.io \
|
||||||
|
ffmpeg \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh
|
||||||
|
|
||||||
|
RUN mkdir -p -m 0755 /etc/apt/keyrings \
|
||||||
|
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
||||||
|
&& chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
||||||
|
&& mkdir -p /etc/apt/sources.list.d \
|
||||||
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y gh \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
|
||||||
|
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||||
|
|
||||||
|
RUN npm install -g opencode-ai repomix --unsafe-perm
|
||||||
|
|
||||||
|
WORKDIR /root/workspace
|
||||||
|
|
||||||
|
EXPOSE 4096
|
||||||
|
|
||||||
|
ENTRYPOINT ["opencode"]
|
||||||
62
docker-compose.yml
Normal file
62
docker-compose.yml
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
services:
|
||||||
|
dind:
|
||||||
|
image: docker:dind
|
||||||
|
container_name: opencode-docker-dind
|
||||||
|
privileged: true
|
||||||
|
environment:
|
||||||
|
- DOCKER_TLS_CERTDIR=
|
||||||
|
networks:
|
||||||
|
- opencode_network
|
||||||
|
restart: unless-stopped
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '2'
|
||||||
|
memory: 4G
|
||||||
|
pids: 512
|
||||||
|
reservations:
|
||||||
|
memory: 1G
|
||||||
|
|
||||||
|
opencode:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: opencode
|
||||||
|
restart: unless-stopped
|
||||||
|
command: ["serve", "--hostname", "0.0.0.0", "--port", "4096", "--cors", "*"]
|
||||||
|
working_dir: /root/workspace
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- DOCKER_HOST=tcp://docker-dind:2375
|
||||||
|
- OPENCODE_CONFIG_DIR=/root/.config/opencode
|
||||||
|
- OPENCODE_MEMORY_DIR=/root/workspace/app_data/opencode-memory
|
||||||
|
- DOCKER_CONTAINER=true
|
||||||
|
- GIT_AUTHOR_NAME=opencode-agent
|
||||||
|
- GIT_AUTHOR_EMAIL=agent@opencode.local
|
||||||
|
- GIT_COMMITTER_NAME=opencode-agent
|
||||||
|
- GIT_COMMITTER_EMAIL=agent@opencode.local
|
||||||
|
volumes:
|
||||||
|
- ./.opencode:/root/.config/opencode
|
||||||
|
- ./app_data:/root/.local/share/opencode
|
||||||
|
- ./app_data/workspaces:/root/workspace
|
||||||
|
- ./app_data/ssh:/root/.ssh:ro
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:4096:4096"
|
||||||
|
networks:
|
||||||
|
- opencode_network
|
||||||
|
depends_on:
|
||||||
|
dind:
|
||||||
|
condition: service_started
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '3'
|
||||||
|
memory: 6G
|
||||||
|
pids: 1024
|
||||||
|
reservations:
|
||||||
|
memory: 2G
|
||||||
|
|
||||||
|
networks:
|
||||||
|
opencode_network:
|
||||||
|
name: opencode_network
|
||||||
30
docs/decisions/004-pr-24-docker-setup.md
Normal file
30
docs/decisions/004-pr-24-docker-setup.md
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# ADR-004: Docker setup (public, cleaned)
|
||||||
|
|
||||||
|
## Статус
|
||||||
|
Accepted
|
||||||
|
|
||||||
|
## Контекст
|
||||||
|
Docker-based AI coding assistant с persistent memory. Старый репо `/root/workspace/opencode/` содержал `cloudflared` (Cloudflare Tunnel client), external network `digital_factory_app_network` (shared с monorepo digital_factory), приватные IPs (`80.85.139.21`), приватный домен `ai.slaid098.dev` в `AI_PROVIDER_BASE_URL`, tunnel UUID `f97e66a5-...` в комментариях `.env.example`. Публичный релиз `slaid098/opencode-config` требует очистки от приватной инфраструктуры.
|
||||||
|
|
||||||
|
Архитектура нового репо: 4 bind mount'а (`.opencode`/`app_data`/`app_data/workspaces`/`app_data/ssh:ro`) вместо старого `config/`+`sandbox_workspace`.
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
- 2 services в `docker-compose.yml`: `dind` (docker:dind, privileged, 2 CPU / 4G) + `opencode` (build from Dockerfile, 3 CPU / 6G)
|
||||||
|
- Network `opencode_network` (self-contained, НЕ external)
|
||||||
|
- 4 bind mounts: `./.opencode`→`/root/.config/opencode`, `./app_data`→`/root/.local/share/opencode`, `./app_data/workspaces`→`/root/workspace`, `./app_data/ssh`→`/root/.ssh:ro`
|
||||||
|
- `docker-compose.yml`: `env_file: .env` (gitignored, user copies from `.env.example`)
|
||||||
|
- `Dockerfile`: node:20-slim + apt (ca-certificates, curl, git, openssh-client, autossh, python3, make, g++, chromium, gnupg, docker.io, ffmpeg) + uv + gh (via apt keyring) + `npm install -g opencode-ai repomix --unsafe-perm` + Puppeteer ENV (system chromium)
|
||||||
|
- `.env.example`: placeholder only (`your-api-key-here`, `https://your-ai-provider.example.com/v1/`)
|
||||||
|
- Убрано: `cloudflared` install (Dockerfile строки 33-34 оригинала), `digital_factory_app_network` external network, IP `80.85.139.21`, домен `ai.slaid098.dev`, tunnel UUID `f97e66a5-...`
|
||||||
|
- `GIT_AUTHOR/COMMITTER_EMAIL` изменён с `agent@slaid098.dev` на `agent@opencode.local`
|
||||||
|
|
||||||
|
## Альтернативы
|
||||||
|
- **Сохранить cloudflared** — отклонено. Публичный репо, tunnel = приватная инфраструктура (named tunnel `slaid098-dev` привязан к конкретному Cloudflare account). Tunnel вынесен в отдельный приватный репо.
|
||||||
|
- **Docker compose без dind** — отклонено. opencode-ai использует Docker для sandboxed execution (субагенты запускают `docker run`), без dind теряется ключевая возможность.
|
||||||
|
- **Сохранить external network `digital_factory_app_network`** — отклонено. External network shared с monorepo `digital_factory` на конкретной машине, не self-contained. Заменён на локальную `opencode_network`.
|
||||||
|
- **Hardcode приватных IPs/domains в `.env.example`** — отклонено. Публичный репо, секреты в `.env` (gitignored), `.env.example` — документация с placeholder'ами.
|
||||||
|
|
||||||
|
## Последствия
|
||||||
|
- `docker compose config` без `.env` падает с `env file .env not found` — expected, пользователь обязан `cp .env.example .env` перед `docker compose up`.
|
||||||
|
- `OPENCODE_MEMORY_DIR=/root/workspace/app_data/opencode-memory` — путь внутри контейнера маппится через bind mount в `./app_data/workspaces/app_data/opencode-memory` на хосте. Layout может потребовать корректировки после runtime-тестирования.
|
||||||
|
- AGENTS.md bind-mount volume не включён в этот PR — добавляется в #10.
|
||||||
29
docs/handoff/pr-24-docker-setup.md
Normal file
29
docs/handoff/pr-24-docker-setup.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# PR: Docker setup
|
||||||
|
|
||||||
|
## Что сделано
|
||||||
|
- docker-compose.yml: 2 services (dind + opencode), 4 bind mounts, opencode_network
|
||||||
|
- Dockerfile: node:20-slim, uv, gh, chromium, docker.io, opencode-ai, repomix
|
||||||
|
- .env.example: cleaned of private IPs/domains/tunnel UUID, placeholder only
|
||||||
|
- Убрано: cloudflared (tunnel → отдельный репо), digital_factory_app_network (self-contained network)
|
||||||
|
|
||||||
|
## Почему
|
||||||
|
Docker-based AI coding assistant. Публичный релиз — очищено от приватной инфраструктуры.
|
||||||
|
Source: `/root/workspace/opencode/` (ветка fix/pipeline-status/review-next-by-verdict) — docker-compose.yml, Dockerfile, .env.example.
|
||||||
|
|
||||||
|
## Pending
|
||||||
|
- AGENTS.md bind-mount volume — добавляется в #10
|
||||||
|
|
||||||
|
## Watch out
|
||||||
|
- `.env` gitignored — пользователь создаёт из `.env.example` (`cp .env.example .env`). `docker compose config` без `.env` падает с `env file .env not found` — это expected, не баг.
|
||||||
|
- .env.example НЕ содержит реальных ключей — placeholder only.
|
||||||
|
- CLOUDFLARE_TUNNEL_TOKEN= (optional) — оставлен как placeholder, tunnel перенесён в отдельный репо.
|
||||||
|
- ANTIDETECT_BROWSER_MCP_URL=http://localhost:8765/mcp — дефолт local, для remote переопределить в `.env` на `http://<server-ip>:8765/mcp`.
|
||||||
|
- GIT_AUTHOR/COMMITTER_EMAIL изменён с `agent@slaid098.dev` на `agent@opencode.local` — публичный репо без приватного домена.
|
||||||
|
- OPENCODE_MEMORY_DIR=/root/workspace/app_data/opencode-memory — путь внутри контейнера; bind mount `./app_data/workspaces:/root/workspace` маппит host→container, так что memory лежит в `./app_data/workspaces/app_data/opencode-memory` на хосте. Возможен нюанс с layout — проверить в runtime.
|
||||||
|
|
||||||
|
## Файлы
|
||||||
|
- `docker-compose.yml` — 2 services (dind, opencode), network `opencode_network`, 4 bind mounts
|
||||||
|
- `Dockerfile` — node:20-slim + apt (ca-certs, curl, git, ssh, autossh, python3, make, g++, chromium, gnupg, docker.io, ffmpeg) + uv + gh + opencode-ai + repomix
|
||||||
|
- `.env.example` — AI provider, OpenCode server, GitHub, Context7, Telegram, Redis, Cloudflare (optional), Antidetect Browser MCP
|
||||||
|
- `docs/handoff/pr-24-docker-setup.md` — этот файл
|
||||||
|
- `docs/decisions/004-pr-24-docker-setup.md` — ADR-004
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Project Map
|
# Project Map
|
||||||
|
|
||||||
opencode-config — Docker-based AI coding assistant with persistent memory (opencode configuration).
|
opencode-config — Docker-based AI coding assistant with persistent memory (opencode configuration). Runs in Docker via `docker-compose.yml` (dind + opencode services).
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
|
|
@ -81,6 +81,9 @@ opencode-config/
|
||||||
├── pyproject.toml # Python project (uv, ruff, pytest config)
|
├── pyproject.toml # Python project (uv, ruff, pytest config)
|
||||||
├── uv.lock # Locked deps for Python project
|
├── uv.lock # Locked deps for Python project
|
||||||
├── .pre-commit-config.yaml # ruff + UV hooks
|
├── .pre-commit-config.yaml # ruff + UV hooks
|
||||||
|
├── docker-compose.yml # 2 services (dind + opencode), opencode_network, 4 bind mounts — PR#24
|
||||||
|
├── Dockerfile # node:20-slim + uv + gh + chromium + docker.io + opencode-ai + repomix — PR#24
|
||||||
|
├── .env.example # Placeholder-only env template (user copies to .env) — PR#24
|
||||||
├── app_data/
|
├── app_data/
|
||||||
│ ├── workspaces/ # Agent working directory (.gitkeep)
|
│ ├── workspaces/ # Agent working directory (.gitkeep)
|
||||||
│ └── ssh/ # SSH keys, not in git (.gitkeep)
|
│ └── ssh/ # SSH keys, not in git (.gitkeep)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue