Docker and Kubernetes Security Checklist!!

Securing containerized environments is no longer optional — it’s essential. Whether you’re managing Docker, Kubernetes, or bare-metal servers, security misconfigurations can lead to major vulnerabilities.
This guide provides a complete, production-grade security checklist covering Docker Compose, Dockerfiles, Kubernetes Pods, and Linux servers — following industry best practices and CIS Benchmarks.

🔴 Malware Injection Scenarios Through Docker

One common attack scenario occurs when containers are left exposed to the internet without proper protections. For example, an exposed PostgreSQL container with weak or default credentials can be discovered by attackers using automated scanning tools like Masscan or Shodan. Once found, attackers can gain access using default passwords, SQL injection, or known CVEs, then execute commands to download and run malware such as cryptominers (kdevtmpfsi) or other malicious scripts inside the container. This malware can consume excessive CPU resources, attempt persistence via cron jobs, disable security tools, and even scan for other vulnerable systems. Similar risks exist for other services: exposed Redis containers can allow attackers to write malicious cron jobs or SSH keys; mounting the Docker socket or host filesystem gives attackers root access to the host; and using untrusted images can lead to supply chain attacks. The key takeaway is that any service exposed to 0.0.0.0 without proper authentication or restrictions is likely to be found and exploited within hours or days. Always bind internal services to 127.0.0.1, use strong passwords, avoid privileged mounts, and monitor container activity to prevent such attacks.

PRODUCTION SECURITY CHECKLIST

DOCKER SECURITY

☐ All services bound to 127.0.0.1 (not 0.0.0.0)

☐ Containers run as non-root user

☐ Read-only filesystem enabled where possible

☐ tmpfs mounted with noexec,nosuid

☐ Resource limits set (CPU, memory, PIDs)

☐ Security options: no-new-privileges=true

☐ Capabilities dropped (cap_drop: ALL)

☐ Secrets in environment variables or Docker secrets

☐ Images scanned with Trivy/Grype

☐ Images signed with Docker Content Trust

☐ Multi-stage builds used

☐ Health checks implemented

☐ Logging configured and centralized

KUBERNETES SECURITY

☐ Pod Security Standards enforced (restricted)

☐ Security contexts set (runAsNonRoot, readOnlyRootFilesystem)

☐ Network policies implemented (default deny)

☐ Resource quotas and limit ranges set

☐ RBAC with minimal permissions

☐ Secrets externalized (Vault/Sealed Secrets)

☐ Admission controllers enabled

☐ Image pull policies set to specific versions

☐ Service accounts with minimal permissions

☐ Namespaces isolated

☐ Audit logging enabled

BARE METAL SECURITY

☐ SSH hardened (no root, keys only, non-standard port)

☐ Firewall configured (UFW/iptables)

☐ Fail2ban installed and configured

☐ Automatic security updates enabled

☐ Audit logging configured (auditd)

☐ File integrity monitoring (AIDE)

☐ Kernel hardened (sysctl)

☐ Rootkit scanners running (rkhunter, chkrootkit)

☐ AppArmor/SELinux enabled

☐ Intrusion detection system deployed (Suricata/OSSEC)

☐ Log aggregation configured

☐ Backups automated and encrypted

☐ Monitoring stack deployed (Prometheus/ELK)

☐ Compliance scanning scheduled (Lynis, OpenSCAP)

ONGOING OPERATIONS

☐ Vulnerability scanning automated

☐ Security patches applied weekly

☐ Access logs reviewed daily

☐ Incident response plan documented

☐ Disaster recovery plan tested

☐ Security awareness training completed

☐ Third-party security audit scheduled

☐ Penetration testing scheduled quarterly

☐ Backup restoration tested monthly

☐ Security metrics tracked and reviewed

INCIDENT RESPONSE READY

☐ Incident response playbook created

☐ Emergency contacts documented

☐ Forensics tools installed

☐ Backup communication channels established

☐ Post-incident review process defined


Docker Compose Security Best Practices with example!!

✅ Network Security

Avoid exposing containers directly to the internet.

# ❌ Bad - Exposed to internet
ports:
  - "5432:5432"

# ✅ Good - Localhost only
ports:
  - "127.0.0.1:5432:5432"

# ✅ Best - No port binding (internal communication only)
# Remove ports section entirely for internal services

✅ Container Hardening

services:
  app:
    security_opt:
      - no-new-privileges:true
    user: "1000:1000"
    read_only: true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    tmpfs:
      - /tmp:noexec,nosuid,size=64M
      - /run:noexec,nosuid,size=10M
  • Prevent privilege escalation
  • Run as a non-root user
  • Limit container capabilities
  • Mount /tmp as noexec to prevent malware execution

✅ Resource Limits

deploy:
  resources:
    limits:
      cpus: '2.0'
      memory: 2G
    reservations:
      cpus: '0.5'
      memory: 512M
pids_limit: 200
restart: unless-stopped
  • Prevent resource abuse
  • Avoid “always” restart loops

✅ Secrets Management

Never hardcode secrets in Docker Compose files.

# ❌ Bad
environment:
  DB_PASSWORD: mypassword123

# ✅ Good
env_file:
  - .env

# ✅ Better
secrets:
  - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

✅ Volume Security

volumes:
  - ./config:/app/config:ro
  - app_data:/var/lib/app
  # - /var/run/docker.sock:/var/run/docker.sock  # ❌ DANGEROUS
  • Use read-only mounts
  • Prefer named volumes
  • Avoid mounting Docker socket

✅ Network Isolation

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true
  • Keep backend services private
  • Isolate internal communication

✅ Complete Secure Docker Compose Example

version: '3.8'

services:
  web:
    image: myapp:latest
    user: "1000:1000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    ports:
      - "127.0.0.1:8080:8080"
    env_file:
      - .env
    secrets:
      - db_password
    networks:
      - frontend
      - backend
    tmpfs:
      - /tmp:noexec,nosuid,size=100M
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]

  db:
    image: postgres:16-alpine
    user: "70:70"
    read_only: true
    networks:
      - backend
    env_file:
      - .env
    secrets:
      - db_password
    tmpfs:
      - /tmp:noexec,nosuid,size=64M
    volumes:
      - db_data:/var/lib/postgresql/data

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  app_data:
  db_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

Dockerfile Security Best Practices

✅ Base Image Security

  • Never use the latest tag
  • Use minimal or distroless images
# ✅ Secure Example
FROM node:20.10.0-alpine@sha256:abc123...

✅ Non-Root User

RUN addgroup -g 1000 appuser && \
    adduser -D -u 1000 -G appuser appuser
USER appuser

✅ Multi-Stage Builds

Reduce image size and attack surface.

FROM node:20-alpine AS builder
RUN npm ci --only=production && npm run build

FROM node:20-alpine
COPY --from=builder /app/dist ./dist
USER appuser

✅ Secrets Management

Use BuildKit secrets, never embed them in images.

RUN --mount=type=secret,id=mysecret \
    cat /run/secrets/mysecret > /app/config

✅ File Permissions

RUN chmod -R 755 /app && chmod 600 /app/secrets/*

✅ Health Checks

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/health || exit 1

Kubernetes Security Checklist

✅ Pod Security

Use restrictive Pod Security Contexts.

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  seccompProfile:
    type: RuntimeDefault

✅ Pod Security Standards (PSS)

Apply at the namespace level.

metadata:
  labels:
    pod-security.kubernetes.io/enforce: restricted

✅ Network Policies

Default deny, then allow selective ingress/egress.

kind: NetworkPolicy
policyTypes:
  - Ingress
  - Egress

✅ Secrets Management

Use External Secrets or Sealed Secrets instead of raw Kubernetes Secrets.

✅ RBAC

Assign minimal permissions using Roles and RoleBindings.

✅ Resource Quotas & Limit Ranges

Prevent resource overuse with quotas per namespace.

✅ Admission Controllers

Enable:

PodSecurity, LimitRanger, ResourceQuota, ServiceAccount, NodeRestriction

🧱 Bare-Metal Server Security Checklist

✅ SSH Security

  • Disable root login
  • Enforce key-based authentication
  • Restrict users and IPs
PermitRootLogin no
PasswordAuthentication no
AllowUsers deployuser adminuser

✅ Firewall (UFW)

ufw default deny incoming
ufw allow 22/tcp comment 'SSH'
ufw allow 80,443/tcp comment 'Web Traffic'
ufw limit 22/tcp

✅ Fail2ban

Block brute-force login attempts automatically.

✅ Automatic Security Updates

Use unattended-upgrades to auto-install patches.

✅ User Management

Create non-root users and enforce strong password policies.

✅ Audit Logging

Monitor critical file and authentication changes using auditd.

✅ File Integrity Monitoring

Use AIDE for detecting unauthorized changes.

✅ Kernel Hardening

Apply sysctl rules:

net.ipv4.ip_forward = 0
kernel.kptr_restrict = 2
net.ipv4.tcp_syncookies = 1

✅ Docker Host Security

Configure /etc/docker/daemon.json for secure defaults:

{
  "icc": false,
  "userns-remap": "default",
  "live-restore": true
}

✅ Rootkit Detection

Install and automate rkhunter and chkrootkit scans.

✅ AppArmor/SELinux

Always enable one for mandatory access control.


Security Scanning & Monitoring

✅ Trivy

trivy image myapp:latest
trivy config Dockerfile

✅ Grype

Alternative vulnerability scanner for CI/CD pipelines.

✅ Falco

Runtime threat detection for containers and Kubernetes.


Summary: Complete Container Security Checklist

LayerKey Practices
Docker ComposeLocalhost binding, no root, secrets, resource limits
DockerfileMinimal base, multi-stage, no secrets, healthcheck
KubernetesRestricted PSS, RBAC, network policies, quotas
Bare MetalHarden SSH, enable UFW, auditd, kernel sysctl
MonitoringTrivy, Falco, Grype, Docker Scout

Final Thoughts

Container security is a continuous process, not a one-time setup.
Follow these checklists regularly, integrate vulnerability scans into your CI/CD pipeline, and review security configurations quarterly.

By implementing these best practices, you’ll significantly reduce the attack surface across Docker, Kubernetes, and bare-metal infrastructure — achieving compliance and resilience in production.

Leave a Reply

Your email address will not be published. Required fields are marked *