with one click
container-workflow
Guidelines for containerized projects using Docker, Dockerfile, docker-compose, container, and containerization. Covers multi-stage builds, security, signal handling, entrypoint scripts, and deployment workflows.
Menu
Guidelines for containerized projects using Docker, Dockerfile, docker-compose, container, and containerization. Covers multi-stage builds, security, signal handling, entrypoint scripts, and deployment workflows.
Activate when user needs multi-URL scraping, browser automation pipelines, or efficient tool orchestration to reduce API round-trips and context usage.
Language-agnostic API design patterns covering REST and GraphQL, including resource naming, HTTP methods, status codes, versioning, pagination, filtering, authentication, error handling, and schema design. Activate when working with APIs, REST endpoints, GraphQL schemas, API documentation, OpenAPI/Swagger, JWT, OAuth2, endpoint design, API versioning, rate limiting, or GraphQL resolvers.
Git workflow and commit guidelines. Trigger keywords: git, commit, push, .git, version control. MUST be activated before ANY git commit, push, or version control operation. Includes security scanning for secrets (API keys, tokens, .env files), commit message formatting with HEREDOC, logical commit grouping (docs, test, feat, fix, refactor, chore, build, deps), push behavior rules, safety rules for hooks and force pushes, and CRITICAL safeguards for destructive operations (filter-branch, gc --prune, reset --hard). Activate when user requests committing changes, pushing code, creating commits, rewriting history, or performing any git operations including analyzing uncommitted changes.
Testing workflow patterns and quality standards. Activate when working with tests, test files, test directories, code quality tools, coverage reports, or testing tasks. Includes zero-warnings policy, targeted testing during development, mocking patterns, and best practices across languages.
Ansible automation workflow guidelines. Activate when working with Ansible playbooks, ansible-playbook, inventory files (.yml, .ini), or Ansible-specific patterns.
Claude Code AI-assisted development workflow. Activate when discussing Claude Code usage, AI-assisted coding, prompting strategies, or Claude Code-specific patterns.
| name | container-workflow |
| description | Guidelines for containerized projects using Docker, Dockerfile, docker-compose, container, and containerization. Covers multi-stage builds, security, signal handling, entrypoint scripts, and deployment workflows. |
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Auto-activate when: Working with Dockerfile, docker-compose.yml, docker-compose.yaml, .dockerignore, Kubernetes manifests (*.yaml, *.yml in k8s directories), container registries, or when user mentions Docker, containers, orchestration, or deployment workflows.
Guidelines for containerized applications using Docker, Docker Compose, and orchestration tools.
ansible-workflowMUST NOT use version: field (deprecated) or docker-compose with hyphen:
# MUST NOT
version: '3.8'
services:
app:
image: myapp
# MUST
services:
app:
image: myapp
docker compose up # MUST
docker-compose up # MUST NOT
# MUST use .internal for container DNS
services:
app:
environment:
- DNS_DOMAIN=.internal
# MUST NOT use .local (conflicts with mDNS/Bonjour)
python:3.12-alpine, node:20-alpinelatest)# RECOMMENDED: Pin by digest for production
FROM python:3.12-alpine@sha256:abc123...
# Acceptable: Pin by tag for development
FROM python:3.12-alpine
base - Common dependencies and user setupdevelopment - Development tools and dependenciesproduction - Minimal runtime with only production dependencies.dockerignore to exclude sensitive filesno-new-privileges:true security optionservices:
app:
security_opt:
- no-new-privileges:true
Key files: Dockerfile, docker-compose.yml, .dockerignore, .devcontainer/, Makefile, k8s/
Before starting: Check README, Makefile, docker-compose.yml, .env files
Command hierarchy: Makefile - Project scripts - Docker commands
&& to chain related commands# MUST NOT: Multiple layers
RUN apk update
RUN apk add curl
RUN apk add git
RUN rm -rf /var/cache/apk/*
# MUST: Single optimized layer
RUN apk update && \
apk add --no-cache \
curl \
git && \
rm -rf /var/cache/apk/*
apk add --no-cache to avoid caching package index--no-cacheRUN apk add --no-cache \
bash \
curl \
git \
openssh \
vim
# MUST: Dependency layer cached separately
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install --no-cache-dir -r requirements.txt
# Source code changes won't invalidate dependency cache
COPY app/ ./app/
# Copy uv from official image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Install dependencies with cache mount
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system --no-cache -r requirements.txt
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install --no-cache-dir -r requirements.txt
# Create non-root user
ARG PUID=1000
ARG PGID=1000
ARG USER=appuser
RUN addgroup -g ${PGID} ${USER} && \
adduser -D -u ${PUID} -G ${USER} -s /bin/sh ${USER}
# Switch to non-root user before EXPOSE and CMD
USER ${USER}
| Factor | Implementation |
|---|---|
| Configuration | Environment variables only, MUST NOT hardcode |
| Dependencies | Explicit declarations with lockfiles |
| Stateless | No local state, horizontally scalable |
| Port Binding | Self-contained, exports via port binding |
| Disposability | Fast startup/shutdown, graceful termination |
| Dev/Prod Parity | Keep environments similar |
MUST define resource limits for production deployments:
services:
app:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
pids: 100
reservations:
cpus: '0.25'
memory: 128M
MUST configure log rotation to prevent disk exhaustion:
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Base stage with common setup
FROM python:3.12-alpine AS base
# Install uv for fast dependency management
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Build arguments
ARG PUID=1000
ARG PGID=1000
ARG USER=appuser
ARG WORKDIR=/app
# Create non-root user
RUN addgroup -g ${PGID} ${USER} && \
adduser -D -u ${PUID} -G ${USER} -s /bin/sh ${USER}
WORKDIR ${WORKDIR}
# Development stage
FROM base AS development
# Install development tools
RUN apk add --no-cache \
bash \
curl \
git \
vim
# Install development dependencies
COPY requirements.txt requirements-dev.txt ./
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system --no-cache -r requirements-dev.txt
# Copy source code
COPY --chown=${USER}:${USER} . .
USER ${USER}
CMD ["python", "run.py"]
# Production stage
FROM base AS production
# Install runtime system dependencies
RUN apk add --no-cache \
bash \
curl
# Install production dependencies only
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system --no-cache -r requirements.txt
# Copy application code
COPY --chown=${USER}:${USER} app/ ./app/
COPY --chown=${USER}:${USER} run.py .
# Switch to non-root user
USER ${USER}
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Expose port
EXPOSE 8000
# Run application
CMD ["python", "run.py"]
# HTTP service
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Database
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD pg_isready -U postgres || exit 1
services:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
Use include directive for modular Compose files:
project/
├── docker-compose.yml
├── compose/
│ ├── dev.yml
│ ├── service1.yml
│ └── service2.yml
├── .env
├── .env.development
└── .env.production
# docker-compose.yml - Main compose file with includes
include:
- compose/service1.yml
- compose/service2.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
target: production
environment:
- DATABASE_URL=${DATABASE_URL}
- LOG_LEVEL=${LOG_LEVEL:-info}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
depends_on:
db:
condition: service_healthy
networks:
- app_network
security_opt:
- no-new-privileges:true
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
pids: 100
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
db:
image: postgres:15-alpine
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app_network
volumes:
db_data:
networks:
app_network:
driver: bridge
MUST use Docker secrets over environment variables for sensitive data:
services:
app:
secrets:
- db_password
- api_key
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
external: true
# Read secret in application
RUN --mount=type=secret,id=db_password \
cat /run/secrets/db_password > /app/config/db_password
| Aspect | Development | Production |
|---|---|---|
| Base Image | Full OS for debugging | Alpine (minimal) |
| Code Mount | Volume mount for hot reload | Copied into image |
| Dependencies | Include dev tools | Runtime only |
| Ports | Exposed for debugging | Necessary only |
| Restart | no (manual control) | unless-stopped |
| Logging | DEBUG | INFO/WARN |
# compose/dev.yml
services:
app:
build:
target: development
volumes:
- .:/workspace:cached
command: python run.py --reload
environment:
- ENVIRONMENT=development
- LOG_LEVEL=debug
{
"name": "Project Dev Container",
"dockerComposeFile": "../docker-compose.yml",
"service": "dev",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-azuretools.vscode-docker"
]
}
},
"postCreateCommand": "pip install -e .[dev]",
"remoteUser": "appuser"
}
.PHONY: dev build up down logs
dev:
@docker compose -f docker-compose.yml -f compose/dev.yml up
build:
@docker compose build
up:
@docker compose up -d
down:
@docker compose down
logs:
@docker compose logs -f
# Pattern rules
run-%:
@docker compose -f docker-compose.yml -f compose/$*.yml up
stop-%:
@docker compose stop $*
ARG PYTHON_VERSION=3.12
ARG PUID=1000
ARG PGID=1000
ARG USER=appuser
ARG WORKDIR=/app
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
APP_ENV=production
Comprehensive .dockerignore organized by category to exclude unnecessary files from build context:
# Git
.git/
.gitignore
.gitattributes
# Documentation
README.md
docs/
*.md
# CI/CD
.github/
.gitlab-ci.yml
# Development
.vscode/
.idea/
.devcontainer/
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.pytest_cache/
.coverage
htmlcov/
.venv/
venv/
*.egg-info/
# Environment files
.env
.env.*
# Build artifacts
build/
dist/
# Testing
tests/
.spec/
# Logs
*.log
# System
.DS_Store
.windows
Thumbs.db
# Docker files
docker-compose*.yml
Dockerfile*
.dockerignore
# Node (if applicable)
node_modules/
# Misc
*.tmp
.cache/
networks:
app_network:
driver: bridge
db_network:
driver: bridge
internal: true # No external access
FROM python:3.12-alpine AS production
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
ARG USER=appuser
RUN adduser -D -s /bin/sh ${USER}
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system --no-cache -r requirements.txt
COPY --chown=${USER}:${USER} app/ ./app/
COPY --chown=${USER}:${USER} run.py .
USER ${USER}
EXPOSE 5000
HEALTHCHECK CMD curl -f http://localhost:5000/health || exit 1
CMD ["python", "run.py"]
FROM python:3.12-alpine AS production
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
ARG USER=worker
RUN adduser -D -s /bin/sh ${USER}
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system --no-cache -r requirements.txt
COPY --chown=${USER}:${USER} worker/ ./worker/
USER ${USER}
# No EXPOSE needed for background workers
# No HEALTHCHECK - use orchestrator health checks
CMD ["python", "-m", "worker.main"]
# Cache pip packages
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
# Cache npm packages
RUN --mount=type=cache,target=/root/.npm \
npm install
# Support ARM and AMD architectures
FROM --platform=$BUILDPLATFORM python:3.12-alpine
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "Building for $TARGETPLATFORM on $BUILDPLATFORM"
docker buildx for building multiple architectures$BUILDPLATFORM, $TARGETPLATFORM--cache-to=type=registry and --cache-from=type=registrygosu with exec in production entrypoint scripts to drop privileges and forward signalschown ${USER}:${USER} /var/run/docker.sock >/dev/null 2>&1 || true#!/bin/bash
set -o errexit # abort on nonzero exitstatus
set -o nounset # abort on unbound variable
set -o pipefail # do not hide errors within pipes
if [ -v DOCKER_ENTRYPOINT_DEBUG ] && [ "$DOCKER_ENTRYPOINT_DEBUG" == 1 ]; then
set -x
set -o xtrace
fi
# If running as root, adjust the ${USER} user's UID/GID and drop to that user
if [ "$(id -u)" = "0" ]; then
groupmod -o -g ${PGID:-1000} ${USER} 2>&1 >/dev/null|| true
usermod -o -u ${PUID:-1000} ${USER} 2>&1 >/dev/null|| true
# Ensure docker.sock is owned by the target user when running as root
chown ${USER}:${USER} /var/run/docker.sock >/dev/null 2>&1 || true
echo "Running as user ${USER}: $@"
exec gosu ${USER} "$@"
fi
echo "Running: $@"
exec "$@"
services:
app:
depends_on:
db:
condition: service_healthy
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
pids: 100
db:
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db_data:
RUN git clone --recurse-submodules https://github.com/user/repo.git
# Or: RUN git submodule update --init --recursive
# Service management
docker compose up / up -d / down / down -v
docker compose restart app
docker compose build / build --no-cache
# Monitoring
docker compose ps / logs -f / logs -f app
docker stats
# Execute commands
docker compose exec app sh
docker compose run --rm app pytest
# Cleanup
docker image prune -a
docker system prune
Before running containers:
Common mistakes:
version: field or docker-compose with hyphen.local domainNote: Container projects vary in complexity. MUST check project-specific documentation before making changes to Docker configurations.