instancse / preflight
100% Client-Side · Zero Telemetry

Docker Compose Preflight & Security Audit

Instant client-side configuration diagnostics, security linting, and one-click hardening.

Sample:
compose.yaml 0 services · 0 lines
--
Preflight Score
Ready to analyze
Sanitized & Hardened Configuration
Extracted Secrets & Environment Variables
Modifications Summary - Original + Hardened
Specification & Security Standards

Preflight Rules Reference

Every rule executed by the instancse audit engine is deterministic, rule-based, and aligned with the modern Docker Compose Specification (v2+) and CIS Docker Benchmarks.

critical SEC-001 Security
Docs ↗

Hardcoded Plaintext Secrets in Environment

Direct Recommendation: Hardcoding secrets into compose files leads to immediate credential leakage whenever files are pushed to Git or shared in forums. Always isolate secrets into an untracked .env file and reference them using ${VARIABLE_NAME} interpolation.

Risk Analysis: Environment variables like POSTGRES_PASSWORD, API_SECRET_KEY, and DATABASE_URL are readily exposed in version control logs, CI/CD pipeline outputs, and docker inspect commands.

Recommended Remediation
# ✗ Vulnerable:
environment:
  - POSTGRES_PASSWORD=my_insecure_password

# ✓ Hardened:
environment:
  - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
# Secrets are stored securely in local .env
critical SEC-002 Security
Docs ↗

Dangerous 'privileged: true' Container Mode

Direct Recommendation: 'privileged: true' grants container processes full root access to host devices and kernel capabilities, completely breaking container isolation. An attacker exploiting an app inside a privileged container can trivially take over the host operating system.

Risk Analysis: Privileged containers can mount arbitrary host block devices, modify host kernel sysctls, and read physical memory. It violates the principle of least privilege.

Recommended Remediation
# ✗ Dangerous:
privileged: true

# ✓ Secure:
# Remove 'privileged: true'. Grant granular Linux capabilities if needed:
cap_add:
  - NET_ADMIN
  - SYS_TIME
critical SEC-003 Security
Docs ↗

Host Docker Socket Bind Mount (/var/run/docker.sock)

Direct Recommendation: Mounting /var/run/docker.sock gives the container direct API control over the host Docker daemon. Anyone with execution rights in the container can spin up sibling containers with host filesystem access to gain root shell.

Risk Analysis: Commonly used in dashboard or monitoring containers (Portainer, Traefik, Watchtower). If left writable, container compromise equals host root compromise.

Recommended Remediation
# ✗ Writable Socket:
volumes:
  - /var/run/docker.sock:/var/run/docker.sock

# ✓ Hardened (Read-Only):
volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro
# Or route via an isolated Tecnativa docker-socket-proxy
warning SEC-004 Security
Docs ↗

Sensitive Database or Cache Port Bound to 0.0.0.0

Direct Recommendation: Exposing databases and caches to all network interfaces (0.0.0.0) leaves them vulnerable to automated internet scrapers and brute-force attacks. Bind database ports strictly to 127.0.0.1 or keep them purely on internal Docker bridge networks.

Risk Analysis: Redis and Elasticsearch default instances without passwords are top targets for automated botnets and ransomware crawlers scanning public IPv4 ranges.

Recommended Remediation
# ✗ Exposed to Public Internet:
ports:
  - "6379:6379"

# ✓ Localhost Only:
ports:
  - "127.0.0.1:6379:6379"
# Or omit ports entirely if only sibling containers need access
warning REL-001 Reliability
Docs ↗

Missing Container Restart Policy

Direct Recommendation: Without an explicit restart policy, Docker containers remain offline after unexpected process exits or host system reboots. Production services and homelab media servers should specify 'restart: unless-stopped'.

Risk Analysis: If your VPS or NAS restarts for OS updates, containers without restart policies will not boot back up automatically, leading to silent service outages.

Recommended Remediation
# ✓ High Availability Policy:
restart: unless-stopped
warning REL-002 Reliability
Docs ↗

Unpinned Floating or ':latest' Image Tag

Direct Recommendation: Using the ':latest' tag introduces unpredictable breaking changes whenever upstream maintainers publish new major releases. Pin services to immutable semantic version tags to ensure consistent, stable deployments.

Risk Analysis: A routine docker compose pull command can accidentally pull a major version database upgrade that corrupts existing schema or migrations.

Recommended Remediation
# ✗ Unpredictable:
image: postgres:latest

# ✓ Reproducible & Pinned:
image: postgres:16.2-alpine
warning REL-003 Reliability
Docs ↗

Host Port Collisions Across Compose Services

Direct Recommendation: Docker cannot bind multiple containers to the same host port on the same IP interface. When port collisions occur, the second container will crash during startup with 'bind: address already in use'.

Risk Analysis: Causes deployment failure on docker compose up and disrupts active services running on the shared port.

Recommended Remediation
# Service 1:
ports:
  - "8080:80"
# Service 2 (Remapped):
ports:
  - "8081:80"
info OPS-001 Operations
Docs ↗

Database Missing Healthcheck Definition

Direct Recommendation: Just because a database container is 'running' does not mean it is ready to accept TCP socket connections. Defining a healthcheck allows backend web services to use 'depends_on: { condition: service_healthy }' to prevent boot race conditions.

Risk Analysis: Web applications that start before the database engine completes initial recovery will throw 500 errors and crash-loop during initial stack launch.

Recommended Remediation
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
  interval: 10s
  timeout: 5s
  retries: 5
info OPS-002 Operations
Docs ↗

Missing Timezone (TZ) Variable

Direct Recommendation: Containers default to UTC unless an explicit TZ environment variable is declared. Setting TZ prevents timestamp discrepancies in application logs, database records, and automated scheduled jobs.

Risk Analysis: Log aggregation and incident investigations become error-prone when host system time and container time differ by several hours.

Recommended Remediation
environment:
  - TZ=${TZ:-Etc/UTC}
info OPS-003 Spec
Docs ↗

Deprecated Top-Level 'version' Attribute

Direct Recommendation: The top-level 'version: "3.8"' key is obsolete under the modern Compose Specification (Docker Compose v2+). Modern Docker CLI reads compose.yaml natively and ignores the version attribute.

Risk Analysis: Retaining obsolete version strings produces harmless but annoying warnings during docker compose up execution.

Recommended Remediation
# Simply delete 'version: "3.8"' from the root of your compose.yaml file.
warning OPS-004 Storage
Docs ↗

Stateful Database Running Without Persistent Volumes

Direct Recommendation: Containers are ephemeral by design. Running databases without named volumes or host bind mounts means all records, schemas, and uploaded files are irreversibly deleted whenever the container is recreated or upgraded.

Risk Analysis: A single docker compose down followed by up completely wipes the database.

Recommended Remediation
services:
  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:
Architecture & Migration

docker run vs. Docker Compose

Understanding when to migrate imperative CLI commands into declarative, version-controlled Compose stacks.

Evaluation Dimension Imperative docker run Declarative Docker Compose Hardening Recommendation
Configuration Format Ephemeral terminal flags in shell history Declarative, reproducible compose.yaml Store in Git with version history
Multi-Container Interconnect Manual network creation and linking Automatic internal bridge network & DNS Rely on internal service names for routing
Secret Management Exposed in process list (ps aux) & shell history Decoupled via standard untracked .env file Always extract secrets using ${VAR}
Port Exposure Defaults to 0.0.0.0:port unless specified Explicit interface binding (e.g. 127.0.0.1:port) Restrict databases to localhost or internal network
Failure Recovery Manual intervention unless --restart passed Declarative restart: unless-stopped Set restart policies on all stateful services
Startup Ordering Manual sequential execution in bash script Native depends_on with service_healthy Define healthchecks for stateful databases
Knowledge Base

Frequently Asked Questions

Common questions about Docker Compose configuration standards, security vulnerabilities, and preflight automation.

How do I securely pass passwords into Docker Compose without hardcoding them?

Create a separate '.env' file in the same directory as your compose.yaml file and add key-value pairs (e.g. POSTGRES_PASSWORD=my_secure_secret). In your compose.yaml, reference them as '${POSTGRES_PASSWORD}'. Ensure you add '.env' to your '.gitignore' file so secrets are never pushed to public repositories.

Why does modern Docker Compose recommend removing the top-level 'version' field?

Under the modern unified Docker Compose Specification (Compose v2+), the format is backward-compatible and continuously updated. Specifying legacy version strings like 'version: "3.8"' is officially obsolete and produces CLI deprecation notices.

What is the difference between 'docker run' and 'docker compose'?

'docker run' is an imperative CLI command suited for quick, one-off container tests. 'docker compose' is a declarative YAML specification that enables version-controlled, multi-container orchestration with automatic networking, volume persistence, and reproducible environment declarations.

Why is mounting /var/run/docker.sock considered a critical security vulnerability?

Mounting the Docker Unix socket into a container gives processes inside that container direct access to the Docker daemon API. A compromised container can execute arbitrary API commands to create new privileged containers with full host filesystem mounts, resulting in immediate host takeover.

Does instancse preflight upload my Docker Compose configuration to a server?

No. instancse executes 100% client-side in your web browser using an offline AST YAML parser. Zero configuration data, credentials, or telemetry ever leave your machine.