4.2 KiB
4.2 KiB
Compose & Infrastructure Conventions
This document outlines the standard conventions and best practices for Docker and Podman Compose files, volume layouts, networking, and smart image packaging across our infrastructure.
1. Storage & Host Volume Conventions
- Root Project Directory: All project state lives under
/volume1/docker/<stack-name>/(e.g.,/volume1/docker/auth-yes/,/volume1/docker/spire/). - Standard Folder Naming: Always use
datafor persistent application and database storage (neverdbor fragmented subfolders when a single root directory suffices). - Local Bind Mount Syntax: Always use the standard
driver_optslocal bind definition:volumes: <service>-data: driver: local driver_opts: type: none device: ${<STACK>_DATA_PATH} o: bind - Zero-Trust Inter-Process Sockets:
- Sockets shared across stacks (e.g., the SPIFFE Workload API
agent.sock) MUST use a named volume (spire-socket). - Application containers mount this volume read-only (
:ro), ensuring zero access to sensitive server CA keys, SQLite databases, or internal host state. - Client stacks declare
spire-socketasexternal: true.
- Sockets shared across stacks (e.g., the SPIFFE Workload API
2. Smart Container Images & Scripting Guidelines
- Pragmatic Scripting in Compose:
- Short one-line commands, flags, or glue checks in
command:orentrypoint:are fine. - Complex configuration generation, heredoc templating (
cat << 'EOF'), and heavy lifecycle bootstrapping MUST NOT be embedded in Compose files.
- Short one-line commands, flags, or glue checks in
- Smart Image Packaging & Repository Segregation:
- Self-seeding configuration and container lifecycle scripts belong in the container image.
- All smart image logic, Dockerfiles, entrypoint scripts (
entrypoint.sh), and configuration templates (templates/) must be cleanly segregated in dedicated directories in the codebase (e.g.,spire/).
- Persistence & User Modification:
- Smart image entrypoints must follow the self-seeding pattern: check if the target configuration exists on the host mount.
- If missing on first boot
\rightarrowatomically write the master template with guiding comments. - If already present
\rightarrowleave it untouched, preserving all user modifications across restarts and image updates.
3. Environment Variables & Clean YAML
- No Inline Variable Fallbacks in Compose:
- Always write clean variable references:
${REG},${GHCR_REG},${SYSTEM_DOMAIN},${SPIRE_DATA_PATH}. - Do NOT use inline defaults (e.g.,
${REG:-quay.atyg.org}) inside the Compose file. - All default values belong strictly in
.envor the interactive setup wizard (infra/setup.ts).
- Always write clean variable references:
- Parameterize Registry Endpoints:
- Always prefix images with
${REG}/library/<image>:<tag>or${GHCR_REG}/<org>/<image>:<tag>.
- Always prefix images with
4. Networking & Traefik Routing
- Ingress Network:
- Web-facing containers connect to the pre-existing external network
traefik-net(external: true).
- Web-facing containers connect to the pre-existing external network
- Network Routing Ambiguity Guard:
- Whenever a service connects to more than one network (e.g., internal
bridge +
traefik-net), always specify:labels: - "traefik.docker.network=traefik-net"
- Whenever a service connects to more than one network (e.g., internal
bridge +
- Internal Service Mesh:
- Backends, databases, Valkey, and internal daemons communicate over a project
bridge network (e.g.,
auth-internal-net) without exposing ports directly to the host.
- Backends, databases, Valkey, and internal daemons communicate over a project
bridge network (e.g.,
- Standard Websecure Labels:
labels: - "traefik.enable=true" - "traefik.docker.network=traefik-net" - "traefik.http.routers.<app>.rule=Host(`${SYSTEM_DOMAIN}`)" - "traefik.http.routers.<app>.entrypoints=websecure" - "traefik.http.routers.<app>.tls=true" - "traefik.http.services.<app>.loadbalancer.server.port=<port>"
5. Stack Independence & Decoupling
- Standalone Infrastructure Stacks:
- General-purpose infrastructure components (e.g., SPIRE, Auth-Yes, Registry
Caches) are standalone stacks with their own dedicated project directories
(
/volume1/docker/spire,/volume1/docker/auth-yes). - Never nest one stack's storage or lifecycle under another stack's directory structure.
- General-purpose infrastructure components (e.g., SPIRE, Auth-Yes, Registry
Caches) are standalone stacks with their own dedicated project directories
(