Docker
Proxima Console uses Docker images for both local development and production. Locally, Docker
Compose spins up the full infrastructure stack for development. In production, the same
images run as Kubernetes pods in the proxima-production cluster, deployed via ArgoCD
GitOps — see Production (Kubernetes). They are no longer run as
standalone systemd-managed containers.
Local Development
Start all infrastructure services with:
docker compose up -d
This starts the following services:
| Service | Image | Ports | Purpose |
|---|---|---|---|
| PostgreSQL 18 | pgvector/pgvector:pg18 | 5432 | Primary relational database (includes the pgvector extension for AI chat embeddings) |
| NATS 2.10 + JetStream | nats | 4222 (client), 8222 (monitoring) | Message broker for agent communication |
| Tempo | grafana/tempo:2.7.2 | 3200 (HTTP API), 4317 (OTLP) | Distributed tracing backend |
| VictoriaMetrics vmstorage | victoriametrics/vmstorage | 8482 (API) | Time-series storage (120d retention) |
| VictoriaMetrics vminsert | victoriametrics/vminsert | 8480 | Metrics ingestion endpoint |
| VictoriaMetrics vmselect | victoriametrics/vmselect | 8481 | Metrics query endpoint |
| Valkey 8 | valkey/valkey:8-alpine | 6379 | Auth cache (sessions, rate limits, MFA, access resolution) |
| vmagent | victoriametrics/vmagent | 8429 | Scrapes backend /metrics, writes to VictoriaMetrics (account 0) |
| Grafana | grafana/grafana | 3004 | Metrics dashboards (auto-provisioned datasources) |
| VictoriaLogs | victoriametrics/victoria-logs:v1.46.0 | 9428 | Centralized log storage (30d retention) |
| Vector | timberio/vector:0.44.0-debian | — | Ships Docker container logs to VictoriaLogs |
VictoriaLogs and Vector start with the rest of the stack on a plain docker compose up -d —
obs.sh / make obs-* depend on these logs in every environment. Vector configuration is at
infra/vector/vector.yaml. See Observability — Logs for details.
After starting infrastructure, apply database migrations and seed data:
make migrate-up
make seed
Production Images
In production these images do not run as standalone systemd containers. Each is deployed as a
Kubernetes pod in the console-system namespace of the proxima-production cluster, reconciled
by ArgoCD from the argocd-infra repo. The backend additionally uses Argo Rollouts
blue-green. See Production (Kubernetes) for the full runtime model.
CI builds one image per service — backend, frontend, docs, mcp, telegram-bot, telegram-miniapp —
each tagged with the Git SHA (see Image Tagging below). The Dockerfiles for the
three web-facing services are described next; the mcp and Telegram services follow the same
multi-stage pattern.
Backend
Dockerfile: infra/docker/backend/Dockerfile
Multi-stage build:
- Build stage -- Compiles the Go backend binary using the full Go toolchain image.
- Runtime stage -- Copies the statically linked (
CGO_ENABLED=0) binary into a minimalalpine:3.22image, adding onlyca-certificatesandtzdataand running as a non-rootproximauser.
The resulting image is small and has a minimal attack surface.
Frontend
Dockerfile: infra/docker/frontend/Dockerfile
Multi-stage build:
- Build stage -- Installs Node.js dependencies and runs the Vite production build. The API base URL is read from
frontend/.env.productionand baked into the static bundle at build time; the PostHog keys (VITE_POSTHOG_KEY/VITE_POSTHOG_HOST) are passed as Docker build arguments. - Runtime stage -- Copies the built static files into an
nginx:1.28-alpineimage that serves them directly.
Docs
Dockerfile: infra/docker/docs/Dockerfile
Multi-stage build:
- Build stage -- Installs Node.js dependencies and builds the Docusaurus static site.
- Runtime stage -- Copies the built static files into an
nginx:1.28-alpineimage that serves the documentation.
Image Scanning
All production images are scanned with Trivy during CI (using the pre-built ci-docker image). The scan checks for known vulnerabilities in OS packages and application dependencies.
- HIGH and CRITICAL severity vulnerabilities block deployment.
- Scan results are available in the CI job output.
- Trivy vulnerability database is cached across pipeline runs.
Build Performance
Docker builds use BuildKit layer caching to minimize rebuild time:
- Each build pulls the previous
:latestimage as a cache source (--cache-from). BUILDKIT_INLINE_CACHE=1embeds cache metadata in pushed images.- Unchanged layers (base image, dependency install) are reused across builds.
Image Tagging
| Trigger | Tags Applied |
|---|---|
Push to main | :$CI_COMMIT_SHA + :latest |
Stable version tag (e.g., v0.2.0) | :$CI_COMMIT_TAG + :latest |
Pre-release tag (e.g., v0.2.0-beta.1) | :$CI_COMMIT_TAG only (:latest is not updated) |
The immutable :$CI_COMMIT_SHA tag is the one ArgoCD deploys: the deploy:k8s-gitops job writes
that exact SHA into the argocd-infra manifests, so the running pods are always pinned to a specific
commit rather than a moving :latest.
Image Registry
All images are pushed to the self-hosted GitLab container registry, one repository per service:
registry.prxm.uz/proxima/console/backend
registry.prxm.uz/proxima/console/frontend
registry.prxm.uz/proxima/console/docs
registry.prxm.uz/proxima/console/mcp
registry.prxm.uz/proxima/console/telegram-bot
registry.prxm.uz/proxima/console/telegram-miniapp