Skip to main content

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:

ServiceImagePortsPurpose
PostgreSQL 18pgvector/pgvector:pg185432Primary relational database (includes the pgvector extension for AI chat embeddings)
NATS 2.10 + JetStreamnats4222 (client), 8222 (monitoring)Message broker for agent communication
Tempografana/tempo:2.7.23200 (HTTP API), 4317 (OTLP)Distributed tracing backend
VictoriaMetrics vmstoragevictoriametrics/vmstorage8482 (API)Time-series storage (120d retention)
VictoriaMetrics vminsertvictoriametrics/vminsert8480Metrics ingestion endpoint
VictoriaMetrics vmselectvictoriametrics/vmselect8481Metrics query endpoint
Valkey 8valkey/valkey:8-alpine6379Auth cache (sessions, rate limits, MFA, access resolution)
vmagentvictoriametrics/vmagent8429Scrapes backend /metrics, writes to VictoriaMetrics (account 0)
Grafanagrafana/grafana3004Metrics dashboards (auto-provisioned datasources)
VictoriaLogsvictoriametrics/victoria-logs:v1.46.09428Centralized log storage (30d retention)
Vectortimberio/vector:0.44.0-debianShips Docker container logs to VictoriaLogs

VictoriaLogs and Vector start with the rest of the stack on a plain docker compose up -dobs.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:

  1. Build stage -- Compiles the Go backend binary using the full Go toolchain image.
  2. Runtime stage -- Copies the statically linked (CGO_ENABLED=0) binary into a minimal alpine:3.22 image, adding only ca-certificates and tzdata and running as a non-root proxima user.

The resulting image is small and has a minimal attack surface.

Frontend

Dockerfile: infra/docker/frontend/Dockerfile

Multi-stage build:

  1. Build stage -- Installs Node.js dependencies and runs the Vite production build. The API base URL is read from frontend/.env.production and baked into the static bundle at build time; the PostHog keys (VITE_POSTHOG_KEY / VITE_POSTHOG_HOST) are passed as Docker build arguments.
  2. Runtime stage -- Copies the built static files into an nginx:1.28-alpine image that serves them directly.

Docs

Dockerfile: infra/docker/docs/Dockerfile

Multi-stage build:

  1. Build stage -- Installs Node.js dependencies and builds the Docusaurus static site.
  2. Runtime stage -- Copies the built static files into an nginx:1.28-alpine image 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 :latest image as a cache source (--cache-from).
  • BUILDKIT_INLINE_CACHE=1 embeds cache metadata in pushed images.
  • Unchanged layers (base image, dependency install) are reused across builds.

Image Tagging

TriggerTags 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