Docker Deployment

DocPlatform ships as a multi-architecture Docker image (amd64/arm64) built on Alpine Linux.

Quick start

docker run -d \
  --name docplatform \
  -p 3000:3000 \
  -v docplatform-data:/data \
  ghcr.io/valoryx-org/docplatform:latest

Open http://localhost:3000 and register your admin account.

Docker Compose

For easier management, use Docker Compose:

# docker-compose.yml
services:
  docplatform:
    image: ghcr.io/valoryx-org/docplatform:latest
    container_name: docplatform
    ports:
      - "3000:3000"
    volumes:
      - docplatform-data:/data
      - ./deploy_key:/etc/docplatform/deploy_key:ro
    environment:
      - DATA_DIR=/data
      - PORT=3000
      - GIT_SSH_KEY_PATH=/etc/docplatform/deploy_key
      - BACKUP_RETENTION_DAYS=30  # default is 7
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "docplatform", "doctor"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

volumes:
  docplatform-data:
docker compose up -d

Image details

Property Value
Registry ghcr.io/valoryx-org/docplatform
Base image Alpine Linux 3.20
Architectures linux/amd64, linux/arm64
Size ~120 MB compressed
User Non-root (docplatform, UID 1000)
Exposed port 3000
Data directory /data

Tags

Tag Description
latest Most recent stable release
v0.5.2 Specific version
v0.5 Latest patch for v0.5.x

Volumes

Mount a persistent volume at /data to preserve data across container restarts:

-v docplatform-data:/data

The /data directory contains:

/data/
├── data.db              # SQLite database
├── jwt-private.pem          # Auto-generated RS256 signing key
├── backups/             # Daily backup files
└── workspaces/
    └── {workspace-id}/
        ├── docs/        # Markdown files
        ├── .git/        # Git repository (if connected)
        └── .docplatform/
            └── config.yaml

Do not skip the volume mount. Without it, all data is lost when the container is removed.

Environment variables

Pass configuration via -e flags, --env-file, or Docker Compose environment:

docker run -d \
  --name docplatform \
  -p 3000:3000 \
  -v docplatform-data:/data \
  -e DATA_DIR=/data \
  -e SMTP_HOST=smtp.example.com \
  -e SMTP_PORT=587 \
  -e SMTP_FROM=docs@example.com \
  -e SMTP_USERNAME=docs@example.com \
  -e SMTP_PASSWORD=app-password \
  -e OIDC_GOOGLE_CLIENT_ID=your-client-id \
  -e OIDC_GOOGLE_CLIENT_SECRET=your-client-secret \
  ghcr.io/valoryx-org/docplatform:latest

Or use an env file:

docker run -d \
  --name docplatform \
  -p 3000:3000 \
  -v docplatform-data:/data \
  --env-file .env.production \
  ghcr.io/valoryx-org/docplatform:latest

See Environment Variables for the complete reference.

SSH key for git sync

Mount your deploy key as a read-only volume:

-v /path/to/deploy_key:/etc/docplatform/deploy_key:ro
-e GIT_SSH_KEY_PATH=/etc/docplatform/deploy_key

Ensure the key file has correct permissions on the host:

chmod 600 /path/to/deploy_key

Health checks

DocPlatform exposes health endpoints:

Endpoint Purpose
GET /api/health Basic liveness check (server is running)
GET /api/ready Readiness check (database and search are initialized, reconciliation complete)

Use these for load balancer probes or orchestrator liveness/readiness probes. Note that the Dockerfile’s built-in healthcheck uses docplatform doctor rather than wget.

With a reverse proxy

Caddy + Docker Compose

services:
  docplatform:
    image: ghcr.io/valoryx-org/docplatform:latest
    volumes:
      - docplatform-data:/data
    environment:
      - DATA_DIR=/data
      - HOST=0.0.0.0
    restart: unless-stopped

  caddy:
    image: caddy:2-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    restart: unless-stopped

volumes:
  docplatform-data:
  caddy-data:
  caddy-config:
# Caddyfile
docs.yourcompany.com {
    reverse_proxy docplatform:3000
}

Caddy handles TLS automatically via Let’s Encrypt.

Upgrades

# Pull the latest image
docker pull ghcr.io/valoryx-org/docplatform:latest

# Recreate the container
docker compose up -d

Or with plain Docker:

docker pull ghcr.io/valoryx-org/docplatform:latest
docker stop docplatform
docker rm docplatform
docker run -d \
  --name docplatform \
  -p 3000:3000 \
  -v docplatform-data:/data \
  ghcr.io/valoryx-org/docplatform:latest

Data in the volume persists across container recreations.

Build from source

Build your own image from the Dockerfile:

cd docplatform
docker build -t docplatform:custom .

The Dockerfile uses a 2-stage build:

  1. Build stage — Go compilation with CGO disabled (static frontend assets are embedded at compile time)
  2. Runtime stage — Alpine Linux with the compiled binary

Logs

# Follow container logs
docker logs -f docplatform

# Last 100 lines
docker logs --tail 100 docplatform

Logs are JSON-structured with request IDs for observability.

Backup and restore

Manual backup

# Copy the database from the container
docker cp docplatform:/data/data.db ./backup-$(date +%Y%m%d).db

Automated backups

Daily backups run automatically inside the container (enabled by default). They’re stored in /data/backups/ and included in the volume.

Restore

docker stop docplatform
docker cp ./backup-20250115.db docplatform:/data/data.db
docker start docplatform