Files
docker-service-architecture…/SKILL.md
Bill 8f91e71caa refactor: split docker-service-architecture skill into focused files
- Extract testing patterns to testing.md (271 lines)
  - 3-stage testing pipeline
  - Branch and worktree isolation
  - Rich test runner with progress display
  - Makefile integration

- Extract CI/CD pipelines to ci-cd.md (201 lines)
  - GitHub Actions workflow with ghcr.io
  - Gitea Actions workflow with custom registry
  - Platform comparison table
  - Multi-service matrix builds

- Streamline SKILL.md to core content (200 lines)
  - Overview and when to use
  - Directory structure
  - Docker compose patterns (dev/test/prod)
  - Common mistakes and quick reference
  - Cross-reference table to supporting files
2026-01-01 14:34:43 -05:00

6.5 KiB

name, description
name description
docker-service-architecture Use when setting up a new project with multiple services that need Docker containerization, multi-environment deployments (dev/test/prod), CI/CD pipelines, or multi-stage testing (unit/service/integration). Also use when adding testing infrastructure to existing Docker projects.

Docker Service Architecture

Overview

Pattern for organizing multi-service projects with Docker containerization, environment-specific deployments, and a 3-stage testing pipeline. Key principles: service isolation, ephemeral test environments, branch-isolated testing, and context-efficient test output.

When to Use

  • Setting up a new multi-service project
  • Adding Docker containerization to existing services
  • Creating CI/CD pipelines for containerized services
  • Implementing multi-stage testing (unit → service → integration)
  • Need parallel test execution across git branches
Topic File Use When
Testing patterns testing.md Setting up 3-stage testing, branch isolation, test runners
CI/CD pipelines ci-cd.md Configuring GitHub or Gitea automated Docker builds

Single-Service Projects

For projects with only one service, simplify the patterns:

Directory structure - Flatten by removing services/ layer:

project/
├── src/                    # Source code (not services/api/src/)
├── tests/
│   ├── unit/
│   └── integration/
├── deploy/
│   ├── dev/
│   ├── test/
│   └── prod/
├── Dockerfile
└── Makefile

Testing stages - Collapse to 2 stages (skip service tests):

┌─────────────┐     ┌─────────────────┐
│ Unit Tests  │ ──► │Integration Tests│
│ (no Docker) │     │  (with Docker)  │
└─────────────┘     └─────────────────┘

Service tests exist to validate individual services before full-stack integration. With one service, integration tests serve this purpose directly.

CI/CD - Remove matrix strategy (single build target):

build:
  steps:
    - run: docker build -t myapp:$VERSION .

When to use multi-service structure anyway:

  • Service will likely split into multiple services later
  • You want consistency with other multi-service projects
  • The "service" is actually multiple containers (app + worker + scheduler)

Directory Structure

project/
├── services/
│   ├── service-a/
│   │   ├── Dockerfile
│   │   ├── pyproject.toml (or package.json)
│   │   ├── service_a/          # Source code
│   │   ├── tests/
│   │   │   ├── unit/           # No containers needed
│   │   │   └── integration/    # Needs service containers
│   │   └── deploy/
│   │       └── test/
│   │           └── docker-compose.yml  # Service-isolated tests
│   └── service-b/
│       └── ... (same structure)
├── deploy/
│   ├── dev/
│   │   ├── docker-compose.yml
│   │   └── .env.example
│   ├── test/
│   │   └── docker-compose.yml  # Full-stack integration
│   └── prod/
│       ├── docker-compose.yml
│       └── .env.example
├── scripts/
│   ├── test-runner.py          # Rich progress display
│   ├── test-service.sh         # Service-level test runner
│   ├── run-integration-tests.sh
│   └── get-test-instance-id.sh
├── .gitea/workflows/           # Or .github/workflows/
│   └── release.yml
└── Makefile

Docker Compose Patterns

Development Environment

# deploy/dev/docker-compose.yml
services:
  api:
    build:
      context: ../..
      dockerfile: services/api/Dockerfile
    ports:
      - "${API_PORT:-8000}:8000"  # Configurable external port
    volumes:
      # Mount source for hot-reload
      - ../../services/api/src:/app/src:ro
    depends_on:
      database:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

volumes:
  postgres-data:
    name: myproject-dev-postgres  # Named volumes persist

Test Environment

# deploy/test/docker-compose.yml
services:
  database:
    # Ephemeral storage for speed
    tmpfs:
      - /var/lib/postgresql/data
    # PostgreSQL tuning for tests
    command: >
      postgres
      -c synchronous_commit=off
      -c fsync=off
      -c full_page_writes=off
    healthcheck:
      interval: 5s   # Faster checks for tests
      retries: 10
      start_period: 10s

Production Environment

# deploy/prod/docker-compose.yml
services:
  api:
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: "4"
        reservations:
          memory: 1G
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"

Common Mistakes

Mistake Problem Solution
Fixed ports in test compose Parallel runs conflict Use dynamic ports: ports: ["5432"]
Persistent test volumes Slow, stateful tests Use tmpfs for ephemeral storage
No healthchecks Race conditions on startup Add healthcheck + depends_on: condition: service_healthy
Verbose test output Context exhaustion Use rich progress display, details only on failure
Single test stage Slow feedback, hard to debug Separate unit → service → integration
No branch isolation Concurrent branches conflict Use TEST_INSTANCE_ID from git branch
No COMPOSE_PROJECT_NAME Worktrees share images, builds conflict Set COMPOSE_PROJECT_NAME=test-${TEST_INSTANCE_ID}
Global test cleanup Kills tests in other worktrees Scope cleanup to current TEST_INSTANCE_ID
Building all services on every change Slow CI Use matrix strategy, only build changed services

Quick Reference

Component Dev Test Prod
Storage Named volumes tmpfs External mounts
Ports Fixed (configurable) Dynamic Fixed
Healthcheck interval 30s 5s 30s
Restart policy None None unless-stopped
Resource limits None None Set limits
Logging Default Default json-file with rotation