Docker Terraform Implementation & Quality Standard¶
Purpose & Scope¶
This skill provides the operational standards, security baselines, and validation commands for orchestrating container workloads using the Docker Terraform provider (kreuzwerker/docker) based on machine-readable architecture plans from .terraform-planning-files/.
Core Engineering Principles¶
- Least-Privilege Non-Root Execution: Every container must run as an explicit non-root UID/GID (
user = "10001:10001"). Forbid running as root (UID 0). - Read-Only Root Filesystem: Configure
read_only = trueto neutralize container file system tampering. Provide dedicatedtmpfsmounts for temporary scratch space (tmpfs = { "/tmp" = "rw,noexec,nosuid,size=64m" }). - Linux Capability Dropping: Drop all Linux kernel capabilities (
capabilities { drop = ["ALL"] }). Only re-add specific individual capabilities (e.g.NET_BIND_SERVICE) if strictly necessary and documented. - Hard Resource Bounds (DoS Shield): Always enforce explicit resource bounds:
memory(e.g.,536870912for 512MB),memory_swap, andcpu_shares. Never allow unconstrained container memory consumption. - Custom Network Isolation: Place containers on user-defined bridge networks (
docker_networkwithinternal = truefor backend tiers). Never attach containers to the default bridge network or host network. - Immutable Image Pinning: Always reference container images by immutable cryptographic SHA256 digests (
name = "registry/app:1.0.0@sha256:...") rather than mutable tags (:latest). - Zero Plaintext Secrets: Supply credentials via environment files, external secret mounts, or Docker secrets. Never embed sensitive passwords in plain HCL
envblocks.
Step-by-Step Implementation Workflow¶
Step 1: Read the Plan¶
- Check
.terraform-planning-files/for an existing plan (INFRA.docker.{goal}.mdorINFRA.{goal}.md). - If found, implement exactly what the plan specifies without unauthorized deviation.
- If not found, request that the planning agent produce the plan or confirm minimal scope.
Step 2: Implement Resources¶
- Isolated Custom Bridge Network:
- Hardened Container Configuration:
resource "docker_container" "hardened_service" { name = "${var.project_name}-service" image = docker_image.app.image_id user = "10001:10001" read_only = true tmpfs = { "/tmp" = "rw,noexec,nosuid,size=64m" } capabilities { drop = ["ALL"] } memory = 536870912 # 512 MB cpu_shares = 512 networks_advanced { name = docker_network.app_net.name } restart = "on-failure" } - Digest-Pinned Image:
Step 3: Code Review Checklist¶
Before submitting code for review, verify:
- [ ] Container runs as an explicit non-root user (user = "10001:10001")
- [ ] Read-only root filesystem enforced (read_only = true) with dedicated tmpfs mounts
- [ ] All Linux capabilities dropped (capabilities { drop = ["ALL"] })
- [ ] Memory limit specified (memory) and CPU shares allocated (cpu_shares)
- [ ] Workloads attached to custom user-defined bridge network (no default bridge or host network)
- [ ] Images pinned to immutable SHA256 digests
- [ ] Zero plaintext secrets in env = [...] configuration blocks
- [ ] Outputs cleanly defined and variables have descriptions and validations
Step 4: Validation¶
Execute and fix any findings:
File Structure Standards¶
Standard directory layout for Docker Terraform projects:
infrastructure/docker/
├── main.tf # Container and network definitions
├── variables.tf # Image tags, memory limits, port bindings
├── outputs.tf # Container IDs, network names
├── locals.tf # Common labels and configuration maps
├── versions.tf # kreuzwerker/docker provider requirements
└── modules/
└── <module>/
├── main.tf
├── variables.tf
└── outputs.tf
Standard provider configuration: