Moayyad Faris
AWS and DevOps

Processed locally in your browser — not uploaded

Docker Compose Security Linter

Audit your docker-compose.yml file against CIS Docker Security benchmarks. Calculates a 0–100 Security Rating, flags root user execution, exposed database host ports, hardcoded passwords, missing health checks, and un-capped memory limits. Runs 100% locally in your browser.

Docker Security Rating:5/100 (Grade: F)
Security & Optimization Findings (6)
⚠️ Containers Running as Root User-20 pts

Running containers as root compromises host security if a container breakout vulnerability occurs.

💡 Fix: Specify an unprivileged non-root user (e.g. `user: node` or `user: 1000:1000`).
⚠️ Database Ports Exposed Directly to Host-25 pts

Binding database ports (5432, 3306, 6379) directly to host interfaces (`0.0.0.0`) exposes databases to automated port scanners.

💡 Fix: Remove host port mappings for internal databases. Connect web services using internal Compose networks.
⚠️ Hardcoded Passwords & Environment Secrets-20 pts

Hardcoding plain-text secrets in compose files risks accidental exposure when committed to version control.

💡 Fix: Use external `.env` files or Docker secrets (`env_file: .env`).
⚠️ Missing Container Health Checks-15 pts

Without healthcheck definitions, orchestrators cannot automatically detect or restart unresponsive containers.

💡 Fix: Add `healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/"]`
⚠️ Missing Resource Memory Limits-10 pts

Uncapped containers can exhaust host RAM, triggering out-of-memory (OOM) kernel kills on adjacent processes.

💡 Fix: Set `deploy.resources.limits.memory: 512M` or `mem_limit: 512m`.
⚠️ Deprecated `version:` Tag-5 pts

Modern Docker Compose V2 ignores top-level `version:` declarations.

💡 Fix: Omit the top-level `version:` key in new compose files.
Hardened Docker Compose Template
services:
  app:
    image: node:20-alpine
    user: "1000:1000"
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    env_file:
      - .env
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
      interval: 30s
      timeout: 5s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M

  db:
    image: postgres:16-alpine
    user: "70:70"
    restart: unless-stopped
    env_file:
      - .env
    networks:
      - app-network
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  app-network:
    driver: bridge

volumes:
  db-data:
01

How to use

  1. Paste your docker-compose.yml file contents into the code editor.
  2. Review your calculated Security Health Rating (0–100 score).
  3. Inspect flagged security vulnerabilities (root execution, exposed DB ports, hardcoded passwords, missing health checks).
  4. Copy the auto-generated hardened docker-compose.yml production template.
02

Understanding the output

The linter parses your Docker Compose service definitions and checks against Docker CIS security benchmarks: avoiding root user execution, preventing database host port exposure, enforcing health checks, avoiding hardcoded secrets, and defining memory limits.

03

Common issues & tips

  • Modern Docker Compose V2 ignores top-level `version:` keys. It is recommended to omit `version:` in new compose files.
  • Exposing database ports like `5432:5432` binds the database to all public host interfaces. Use internal Docker networks for app-to-db communication instead.

Frequently asked questions

Is my docker-compose.yml sent to a server?
No. Analysis is performed entirely in your browser.
Why should database ports not be exposed in compose?
Exposing ports like 5432:5432 exposes your database to automated scanners on host networks. App containers should communicate via internal Docker networks instead.

Related tools