Skip to content

Containerization

Responsibility

Package each of the three binaries into a minimal, secure container image and orchestrate them with Docker Compose on a private network.

Dockerfiles

All three (Dockerfile.backend, Dockerfile.web, Dockerfile.client) use the same multi-stage pattern:

  1. Build stage (golang:1.27.2-alpine): CGO_ENABLED=0 GOOS=linux, go build -ldflags="-s -w" into /app/binary.
  2. Runtime stage (gcr.io/distroless/static-debian12:nonroot): copy the binary, run as non-root UID 65532, ENTRYPOINT ["/binary"]. Backend and web expose 8080; client is outbound only.

Layer caching: go.mod/go.sum are copied and go mod download runs before the source COPY . ..

.dockerignore

Excludes .git, build outputs, secrets (.env, keys), docs, IDE files, and the Dockerfiles themselves, keeping the build context small and protecting layer cache from irrelevant changes.

Docker Compose

compose.yaml defines four services on a shared private network:

  • postgres (postgres:16-alpine) — persistent store.
  • backend — control plane API, STORE=postgres, depends on postgres.
  • frontend — dashboard + gateway, only service with a host-published port (8080), depends on backend.
  • client — data plane example, depends on backend.

Only the frontend maps a port to the host, so all backend traffic stays on the private network.

Build commands

docker build -f Dockerfile.backend -t flaggo-backend:local .
docker compose up -d
  • openwiki/architecture/overview.md
  • openwiki/build/ci-pipeline.md