Instruction file imported from oskarc/AssetHub (
.github/instructions/containerization-docker-best-practices.instructions.md). Copyright stays with the author.
Docker Conventions — AssetHub
Reference files
Before editing, read the existing Dockerfiles and compose files:
docker/Dockerfile— API multi-stage build (.NET 10)docker/Dockerfile.Worker— Worker multi-stage builddocker/Dockerfile.ClamAV,docker/Dockerfile.RabbitMQ— patched infra imagesdocker/docker-compose.yml— development stackdocker/docker-compose.prod.yml— production overrides
AssetHub image rules
- Multi-stage builds for all application images (build → runtime).
- Base images:
mcr.microsoft.com/dotnet/aspnet:10.0-alpine(runtime),mcr.microsoft.com/dotnet/sdk:10.0-alpine(build). Pin minor versions — no:latest. - Non-root
USERin all production images. HEALTHCHECKinstruction in every Dockerfile.- No secrets in layers — use runtime secrets (Docker Secrets, env vars with
__→:mapping). - Combine
RUNcommands and clean up temp files in the same layer. .dockerignoreexcludes.git,node_modules, build artifacts, IDE files, test files.
Compose conventions
- Resource limits (
cpu_limits,memory_limits) on every service. - Named volumes for persistent data (Postgres, MinIO, Redis, RabbitMQ).
- Internal networks for backend services; only reverse proxy and API exposed.
- Logs to
STDOUT/STDERR— no file-based logging inside containers.
Security scanning
CI pipeline (.github/workflows/ci.yml) builds and scans images with Trivy on the main branch. Critical vulnerabilities block the build.
Quick checklist
- Multi-stage build separates SDK from runtime?
- Pinned base image version (not
:latest)? - Non-root
USERdefined? -
HEALTHCHECKpresent? - No secrets or credentials in any layer?
-
.dockerignoreup to date? - Resource limits in compose?