1. Pengenalan Docker Security
Container Docker menawarkan isolasi yang lebih ringan dibanding VM, tetapi tetap memiliki permukaan serangan (attack surface) yang perlu dijaga. Keamanan container bukan hanya tentang mengamankan aplikasi di dalamnya, tetapi juga tentang mengamankan seluruh supply chain — dari base image, build process, runtime, hingga orchestration.
Dalam tutorial Docker Dasar dan Docker Compose Advanced, kita telah mempelajari cara membuat dan mengelola container. Kali ini kita fokus pada aspek keamanan yang kritis untuk production deployment.
Defense in Depth
Konsep defense in depth berarti menerapkan beberapa lapisan keamanan, sehingga jika satu lapisan gagal, lapisan lain tetap melindungi sistem:
┌─────────────────────────────────────────────────────────┐ │ DOCKER SECURITY LAYERS │ │ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ LAYER 1: Host Security │ │ │ │ - OS hardening, kernel updates, firewall │ │ │ │ ┌───────────────────────────────────────────────┐ │ │ │ │ │ LAYER 2: Docker Daemon Security │ │ │ │ │ │ - Rootless mode, TLS, audit logging │ │ │ │ │ │ ┌───────────────────────────────────────────┐ │ │ │ │ │ │ │ LAYER 3: Image Security │ │ │ │ │ │ │ │ - Trusted base, scanning, minimal images │ │ │ │ │ │ │ │ ┌───────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ LAYER 4: Container Runtime Security │ │ │ │ │ │ │ │ │ │ - Non-root, capabilities, read-only │ │ │ │ │ │ │ │ │ │ ┌───────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ LAYER 5: Application Security │ │ │ │ │ │ │ │ │ │ │ │ - Secrets, env vars, auth │ │ │ │ │ │ │ │ │ │ │ └───────────────────────────────────┘ │ │ │ │ │ │ │ │ │ └───────────────────────────────────────┘ │ │ │ │ │ │ │ └───────────────────────────────────────────┘ │ │ │ │ │ └───────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘
Anatomy of a Container Attack
| Vektor Serangan | Risiko | Mitigasi |
|---|---|---|
| Vulnerable base image | CVE exploit dari library lama | Image scanning, update berkala |
| Container running as root | Privilege escalation ke host | Non-root user, rootless Docker |
| Secrets in environment vars | Bocor via inspect/logs | Docker secrets, external vault |
| Privileged container | Full access ke host kernel | Hindari --privileged, drop capabilities |
| Unrestricted network | Container bisa ke mana saja | Network policies, internal networks |
| Mutable filesystem | Malware bisa menulis ke disk | Read-only root filesystem |
| Docker socket exposure | Full control atas Docker daemon | Jangan mount socket, gunakan proxy |
Docker socket (/var/run/docker.sock) adalah root access ke host. Jangan pernah mount socket ke dalam container kecuali benar-benar diperlukan (misalnya monitoring agent). Siapapun yang bisa mengakses socket memiliki kontrol penuh atas semua container dan host.
2. Threat Model Container
Sebelum menerapkan keamanan, kita perlu memahami apa yang perlu dilindungi. Docker container memiliki beberapa komponen yang masing-masing memiliki risiko keamanan tersendiri.
Komponen Keamanan Docker
# =========================== # DOCKER ATTACK SURFACE # =========================== # 1. DOCKER DAEMON (dockerd) # - Berjalan sebagai root secara default # - Mengelola semua container, images, networks # - Akses ke Docker daemon = akses ke semua container # 2. DOCKER IMAGES # - Base image bisa mengandung vulnerabilities # - Malicious images dari untrusted registry # - Supply chain attack via compromised dependencies # 3. DOCKER CONTAINERS # - Running as root = root di host (jika escape) # - Shared kernel = kernel exploit berdampak semua container # - Excessive capabilities # 4. DOCKER NETWORK # - Default bridge: semua container bisa saling akses # - Exposed ports ke host # - Unencrypted communication antar container # 5. DOCKER SECRETS & CONFIG # - Secrets di environment variables terlihat di docker inspect # - Config files bisa bocor via image layers # - Hardcoded credentials di Dockerfile # 6. HOST INTERACTION # - Volume mounts = akses ke host filesystem # - Docker socket = full host control # - Host networking = bypass isolation
Security Checklist Awal
| Area | Checklist | Prioritas |
|---|---|---|
| Images | Gunakan official images, scan vulnerabilities, pin versi | 🔴 Kritis |
| Runtime | Non-root user, drop capabilities, read-only FS | 🔴 Kritis |
| Secrets | Jangan pakai ENV, gunakan Docker secrets atau vault | 🔴 Kritis |
| Network | Internal networks, firewall rules, encrypted traffic | 🟡 Tinggi |
| Resources | Limit CPU, memory, PID, ulimit | 🟡 Tinggi |
| Logging | Audit logging, centralized logs, alert | 🟡 Tinggi |
| Updates | Patch OS, Docker engine, dan base images berkala | 🟡 Tinggi |
3. Rootless Docker Mode
Secara default, Docker daemon (dockerd) berjalan sebagai root. Ini berarti jika ada vulnerability di Docker daemon atau container runtime, attacker bisa mendapatkan akses root ke host. Rootless mode menjalankan Docker daemon sebagai user biasa, sehingga bahkan jika terjadi container escape, attacker hanya mendapatkan akses sebagai user tersebut.
Perbandingan Root vs Rootless
| Aspek | Root Mode (Default) | Rootless Mode |
|---|---|---|
| Daemon User | 🔴 root | 🟢 regular user |
| Container Escape Impact | 🔴 Full root access | 🟢 Limited user access |
| Port Binding (<1024) | 🟢 Langsung bisa | 🟡 Butuh sysctl atau port mapping |
| Cgroup Management | 🟢 Penuh | 🟡 Terbatas (butuh cgroup v2) |
| Overlay Network | 🟢 Penuh | 🟡 Terbatas |
| AppArmor/SELinux | 🟢 Didukung | 🟡 Terbatas |
| Performance | 🟢 Native | 🟡 Slight overhead |
Instalasi Rootless Docker
# =========================== # INSTALL ROOTLESS DOCKER # =========================== # 1. Install dependencies sudo apt-get install -y uidmap dbus-user-session fuse-overlayfs slirp4netns # 2. Pastikan user memiliki subuid/subgid mapping grep $(whoami) /etc/subuid || sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(whoami) # 3. Install rootless Docker (sebagai user, BUKAN root) dockerd-rootless-setuptool.sh install # 4. Set environment variables (tambahkan ke ~/.bashrc) export PATH=/home/$(whoami)/bin:$PATH export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock # 5. Verifikasi docker info | grep -i "root dir" # Output: Docker Root Dir: /home/user/.local/share/docker # 6. Cek Docker daemon berjalan sebagai user ps aux | grep dockerd # Output: user 12345 dockerd --rootless # 7. Test container docker run --rm hello-world
User Namespace Remapping
Alternatif lain adalah menggunakan user namespace remapping pada Docker daemon biasa:
# /etc/docker/daemon.json
{
"userns-remap": "default",
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
# Setelah edit, restart Docker daemon
sudo systemctl restart docker
# Verifikasi user namespace remapping
docker run --rm alpine cat /proc/1/uid_map
# Output: 0 100000 65536
# Artinya: root(0) di container = UID 100000 di host
Rootless mode memerlukan beberapa konfigurasi tambahan untuk fitur tertentu seperti AppArmor dan port di bawah 1024. Untuk production, kombinasikan rootless mode dengan user namespace remapping untuk keamanan berlapis.
4. Image Vulnerability Scanning
Image scanning adalah proses menganalisis Docker image untuk menemukan known vulnerabilities (CVE) pada packages dan library yang digunakan. Ini adalah langkah pertama dalam mengamankan supply chain container.
Tools Image Scanning
| Tool | Tipe | Kelebihan |
|---|---|---|
Trivy | Open-source CLI | Cepat, mudah, scan image/filesystem/repo |
Grype | Open-source CLI | Ringan, integrasi SBOM dengan Syft |
Docker Scout | Integrated (Docker) | Terintegrasi langsung di Docker Desktop/CLI |
Snyk Container | Commercial + Free tier | Fix suggestions, CI/CD integration |
Clair | Open-source server | Registry integration, API-based |
Menggunakan Trivy
# =========================== # INSTALL TRIVY # =========================== # Ubuntu/Debian sudo apt-get install -y wget apt-transport-https gnupg wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee /etc/apt/sources.list.d/trivy.list sudo apt-get update && sudo apt-get install trivy # macOS brew install trivy # =========================== # SCAN DOCKER IMAGES # =========================== # Scan image untuk vulnerabilities trivy image node:20-alpine # Output: tabel vulnerabilities dengan severity (CRITICAL, HIGH, MEDIUM, LOW) # Scan dengan severity filter trivy image --severity CRITICAL,HIGH nginx:latest # Scan dan output JSON (untuk CI/CD) trivy image --format json --output result.json node:20-alpine # Scan image lokal yang baru di-build trivy image myapp:v1.0 # Scan dengan exit code (CI/CD pipeline) # Exit code 1 jika ditemukan CRITICAL vulnerability trivy image --exit-code 1 --severity CRITICAL myapp:v1.0 # Scan Dockerfile untuk best practices trivy config --policy-bundle-repository ghcr.io/aquasecurity/trivy-policies Dockerfile # Scan filesystem (dependencies) trivy fs --scanners vuln ./my-project/
Docker Scout
# Docker Scout (terintegrasi di Docker CLI) # Login ke Docker Scout docker scout login # Quick view vulnerabilities docker scout quickview node:20-alpine # Detail CVE list docker scout cves node:20-alpine # Hanya CVE yang bisa di-fix docker scout cves --only-fixed node:20-alpine # Rekomendasi base image yang lebih aman docker scout recommendations node:20-alpine # Compare image versions docker scout compare --to node:18-alpine node:20-alpine
Secure Dockerfile Patterns
# ===========================
# SECURE DOCKERFILE BEST PRACTICES
# ===========================
# 1. Gunakan specific version tags (BUKAN latest)
FROM node:20.11-alpine3.19
# 2. Gunakan slim/distroless images untuk mengurangi attack surface
FROM gcr.io/distroless/nodejs20-debian12
# 3. Multi-stage build untuk mengurangi ukuran image
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM gcr.io/distroless/nodejs20-debian12
COPY --from=builder /app/dist /app/dist
COPY --from=builder /app/node_modules /app/node_modules
WORKDIR /app
CMD ["dist/server.js"]
# 4. Buat user non-root
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -s /bin/sh -D appuser
USER appuser
# 5. Copy file dengan permission yang tepat
COPY --chown=appuser:appgroup . .
# 6. Jangan install package yang tidak perlu
RUN apk add --no-cache curl && \
rm -rf /var/cache/apk/*
# 7. Scan image setelah build
# trivy image --exit-code 1 --severity CRITICAL myapp:v1.0
5. Secrets Management
Secrets seperti password, API keys, dan certificates harus dikelola dengan aman. Docker menyediakan beberapa mekanisme untuk ini, masing-masing cocok untuk skenario berbeda.
❌ Cara yang SALAH (Jangan Lakukan)
# ❌ JANGAN hardcode secrets di Dockerfile ENV DB_PASSWORD=supersecret123 ENV API_KEY=ak_1234567890abcdef # ❌ JANGAN copy file secrets ke image COPY .env /app/.env COPY secrets/ /app/secrets/ # ❌ JANGAN kirim secrets via build args (masih terlihat di history) ARG DB_PASSWORD RUN echo "Setting up with $DB_PASSWORD"
✅ Docker Secrets (Swarm Mode)
# docker-compose.yml dengan secrets
# Secrets di-mount sebagai file di /run/secrets/
services:
api:
image: myapp/api
secrets:
- db_password
- jwt_secret
- tls_cert
- tls_key
environment:
# Baca secret dari file (bukan dari ENV langsung)
- DB_PASSWORD_FILE=/run/s...rd
- JWT_SECRET_FILE=/run/secrets/jwt_secret
volumes:
- tls-cert:/tls:ro
postgres:
image: postgres:16
secrets:
- db_password
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
# Dari file di host
db_password:
file: ./secrets/db_password.txt
jwt_secret:
file: ./secrets/jwt_secret.txt
# External (sudah ada di Swarm)
tls_cert:
external: true
tls_key:
external: true
✅ Build-Time Secrets dengan BuildKit
# Dockerfile — BuildKit secrets (TIDAK tersimpan di image)
# Secrets hanya tersedia selama build, hilang setelahnya
# Install private dependencies
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci --only=production
# Clone dari private repo
RUN --mount=type=secret,id=ssh_key,target=/root/.ssh/id_rsa \
git clone git@github.com:private/repo.git /app
# Set certificate
RUN --mount=type=secret,id=ca_cert,target=/usr/local/share/ca-certificates/custom.crt \
update-ca-certificates
# Build dengan BuildKit secrets DOCKER_BUILDKIT=1 docker build \ --secret id=npmrc,src=$HOME/.npmrc \ --secret id=ssh_key,src=$HOME/.ssh/id_rsa \ -t myapp:v1.0 . # Pastikan .dockerignore exclude secrets echo "secrets/" >> .dockerignore echo ".env" >> .dockerignore echo ".npmrc" >> .dockerignore echo "*.pem" >> .dockerignore echo "*.key" >> .dockerignore
✅ External Secrets Manager
# =========================== # SECRETS MANAGEMENT OPTIONS # =========================== # 1. Docker Swarm Secrets (built-in) # - Cocok untuk Docker Swarm deployment # - Encrypted at rest and in transit # - Mounted sebagai file di /run/secrets/ # 2. HashiCorp Vault # - Enterprise-grade secrets management # - Dynamic secrets (rotating credentials) # - Audit logging lengkap # - Integration dengan Kubernetes, Docker, CI/CD # 3. AWS Secrets Manager / SSM Parameter Store # - Managed service, tidak perlu operasi infrastruktur # - Automatic rotation # - IAM-based access control # 4. Azure Key Vault / Google Secret Manager # - Cloud-native solutions # - Integration dengan respective CI/CD tools # 5. SOPS (Secrets OPerationS) oleh Mozilla # - Encrypted files yang aman untuk git # - Support AWS KMS, GCP KMS, Azure Key Vault # - Bisa di-decrypt saat CI/CD pipeline
Hindari mengirim secrets melalui docker run -e SECRET=value karena secret akan terlihat di docker inspect, ps aux, dan process listing. Gunakan Docker secrets atau external vault untuk production.
6. Container Hardening
Container hardening berarti membatasi apa yang bisa dilakukan container di runtime. Semakin sedikit akses yang dimiliki container, semakin kecil dampak jika terjadi kompromi.
Complete Security-Hardened Dockerfile
# ===========================
# SECURITY-HARDENED DOCKERFILE
# BeebaneLabs Production Template
# ===========================
# Multi-stage build untuk minimal image
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Final stage - distroless-like
FROM node:20-alpine AS production
# Install security updates
RUN apk update && apk upgrade && apk add --no-cache \
dumb-init \
&& rm -rf /var/cache/apk/*
# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup -s /sbin/nologin
WORKDIR /app
# Copy only production dependencies
COPY --from=deps --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=build --chown=appuser:appgroup /app/dist ./dist
COPY --from=build --chown=appuser:appgroup /app/package.json ./
# Set environment
ENV NODE_ENV=production
ENV PORT=3000
# Expose port
EXPOSE 3000
# Switch to non-root user
USER 1001:1001
# Health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => { process.exit(r.statusCode === 200 ? 0 : 1) })"
# Use dumb-init as PID 1 (proper signal handling)
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]
Docker Compose Security Hardening
services:
api:
build: ./backend
# Non-root user
user: "1001:1001"
# Read-only root filesystem
read_only: true
# tmpfs untuk directory yang perlu write
tmpfs:
- /tmp:noexec,nosuid,size=100m
- /app/.cache:noexec,nosuid,size=50m
# Drop ALL capabilities, add only what's needed
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # Hanya jika bind port < 1024
# Prevent privilege escalation
security_opt:
- no-new-privileges:true
# Limit PIDs (prevent fork bomb)
pids_limit: 100
# Resource limits
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
# Logging
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
restart: unless-stopped
postgres:
image: postgres:16-alpine
user: "70:70" # postgres user in alpine
read_only: true
tmpfs:
- /tmp:noexec,nosuid
- /run/postgresql:noexec,nosuid
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
security_opt:
- no-new-privileges:true
pids_limit: 100
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
# JANGAN expose port ke host di production
# ports:
# - "5432:5432" ← JANGAN
expose:
- "5432" ← Hanya internal network
networks:
- data
Kernel Security Parameters
# /etc/sysctl.d/99-docker-security.conf # Terapkan di host untuk meningkatkan keamanan container # Prevent IP spoofing net.ipv4.conf.all.rp_filter = 1 # Disable IP forwarding (kecuali diperlukan) net.ipv4.ip_forward = 0 # Disable ICMP redirects net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 # Enable SYN cookies (protect against SYN flood) net.ipv4.tcp_syncookies = 1 # Limit kernel pointer exposure kernel.kptr_restrict = 2 # Disable core dumps fs.suid_dumpable = 0 # Apply sudo sysctl --system
7. Network Security
Network security di Docker melibatkan segmentasi traffic, pembatasan akses, dan enkripsi komunikasi antar container.
Network Security Best Practices
services:
api:
networks:
frontend: # Hanya frontend dan backend
backend:
# JANGAN gunakan host networking
# network_mode: host ← JANGAN
postgres:
networks:
data: # Hanya data network
# JANGAN expose port ke host
expose:
- "5432" # Internal only
redis:
networks:
data:
expose:
- "6379"
# Password-protect Redis
command: redis-server --requirepass ${REDIS_PASSWORD}
networks:
# Frontend network - bisa akses internet
frontend:
driver: bridge
internal: false
# Backend network - internal only
backend:
driver: bridge
internal: true
# Data network - paling terisolasi
data:
driver: bridge
internal: true # Tidak bisa akses internet
driver_opts:
com.docker.network.bridge.enable_icc: "true"
com.docker.network.bridge.enable_ip_masquerade: "false"
TLS untuk Docker Daemon
# Generate CA certificate
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
# Generate server certificate
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=docker-host" -sha256 -new -key server-key.pem -out server.csr
echo "subjectAltName=DNS:docker-host,IP:192.168.1.10,IP:127.0.0.1" > extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
# Configure Docker daemon untuk TLS
cat > /etc/docker/daemon.json <<'EOF'
{
"tls": true,
"tlscacert": "/etc/docker/certs/ca.pem",
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"tlsverify": true
}
EOF
sudo systemctl restart docker
8. Runtime Security & Monitoring
Setelah container berjalan, kita perlu memonitor aktivitas yang mencurigakan dan mendeteksi anomali.
Runtime Security Tools
| Tool | Fungsi | Tipe |
|---|---|---|
Falco | Runtime threat detection berdasarkan system calls | Open-source |
sysdig | System exploration dan troubleshooting | Open-source |
Aqua Security | Full lifecycle container security | Commercial |
Twistlock/Prisma | Container security platform | Commercial |
Docker Bench | CIS Docker Benchmark compliance checker | Open-source |
Docker Bench for Security
# Jalankan Docker Bench Security (CIS Benchmark)
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /etc:/etc:ro \
--label docker_bench_security \
docker/docker-bench-security
# Output berisi rekomendasi terorganisir:
# [WARN] 1.1.1 - Ensure Docker is up to date
# [PASS] 1.1.2 - Ensure only trusted users are in docker group
# [WARN] 2.1 - Ensure network traffic is restricted between containers
# ...
Falco Runtime Monitoring
# Install Falco di host curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" | sudo tee /etc/apt/sources.list.d/falcosecurity.list sudo apt-get update && sudo apt-get install -y falco # Jalankan Falco sudo systemctl start falco # Contoh rules yang terdeteksi: # - Container melakukan shell exec # - File sensitive diakses (/etc/shadow, /etc/passwd) # - Network connection ke suspicious IP # - K8s API call dari container # - Binary baru dijalankan di container
Audit Logging
# Enable Docker daemon audit logging
# /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5",
"labels": "service,environment",
"tag": "{{.ImageName}}/{{.Name}}/{{.ID}}"
}
}
# Linux audit rules untuk Docker
sudo auditctl -w /usr/bin/docker -p rwxa -k docker
sudo auditctl -w /var/lib/docker -p rwxa -k docker
sudo auditctl -w /etc/docker -p rwxa -k docker
sudo auditctl -w /var/run/docker.sock -p rwxa -k docker
sudo auditctl -w /usr/bin/dockerd -p rwxa -k docker
# Cek audit logs
sudo ausearch -k docker --interpret
# Docker events untuk monitoring real-time
docker events --since '1h' --filter 'type=container'
docker events --filter 'event=start' --filter 'event=stop'
9. Compliance & Benchmarking
CIS Docker Benchmark adalah standar keamanan yang diakui secara luas untuk Docker deployment. Benchmark ini mencakup 6 bagian utama:
CIS Docker Benchmark Overview
| Section | Topik | Contoh Rekomendasi |
|---|---|---|
| 1. Host Configuration | Keamanan host OS | Partisi terpisah, update OS, audit logging |
| 2. Docker Daemon | Konfigurasi daemon | TLS, userns-remap, content trust |
| 3. Docker Files | Dockerfile best practices | Non-root user, minimal packages, HEALTHCHECK |
| 4. Container Images | Image security | Trusted base, scan vulnerabilities, pin version |
| 5. Container Runtime | Runtime hardening | Read-only FS, no-privileged, resource limits |
| 6. Security Operations | Operational security | Image signing, content trust, audit |
Automated Compliance Check
# Docker Content Trust (image signing)
export DOCKER_CONTENT_TRUST=1
# Pull hanya signed images
docker pull nginx:latest # Akan verifikasi signature
# Docker Scout compliance
docker scout recommendations myapp:v1.0
# Manual security checklist
echo "=== Docker Security Audit ==="
# 1. Cek Docker daemon running as root?
ps -eo user,comm | grep dockerd
# 2. Cek containers running as root?
docker ps --format '{{.Names}}' | while read name; do
echo -n "$name: running as "
docker exec $name whoami 2>/dev/null || echo "N/A"
done
# 3. Cek containers dengan --privileged?
docker inspect --format='{{.HostConfig.Privileged}}' $(docker ps -q)
# 4. Cek containers dengan host network?
docker inspect --format='{{.HostConfig.NetworkMode}}' $(docker ps -q)
# 5. Cek exposed ports
docker ps --format "table {{.Names}}\t{{.Ports}}"
# 6. Cek volume mounts dari host
docker inspect --format='{{.Mounts}}' $(docker ps -q)
# 7. Cek resource limits
docker inspect --format='{{.HostConfig.Memory}} {{.HostConfig.CpuQuota}}' $(docker ps -q)
10. Security di CI/CD Pipeline
Integrasikan security scanning ke dalam CI/CD pipeline untuk mendeteksi vulnerabilities sebelum deployment. Lihat juga tutorial GitLab CI/CD dan Jenkins untuk panduan CI/CD lengkap.
GitLab CI Security Stage
# .gitlab-ci.yml - Security scanning stages
stages:
- build
- test
- security
- deploy
build-image:
stage: build
script:
- docker build -t myapp:$CI_COMMIT_SHA .
image-scan:
stage: security
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
# Scan image untuk vulnerabilities
- trivy image --exit-code 1 --severity CRITICAL,HIGH myapp:$CI_COMMIT_SHA
# Generate report
- trivy image --format json --output trivy-report.json myapp:$CI_COMMIT_SHA
artifacts:
paths:
- trivy-report.json
when: always
dockerfile-lint:
stage: security
image:
name: hadolint/hadolint:latest-debian
entrypoint: [""]
script:
- hadolint Dockerfile --strict
dependency-check:
stage: security
script:
- npm audit --audit-level=high
- trivy fs --exit-code 1 --severity CRITICAL ./node_modules/
Security Pipeline Checklist
# =========================== # CI/CD SECURITY PIPELINE # =========================== # PRE-BUILD: # ✓ Lint Dockerfile (hadolint) # ✓ Scan dependencies (npm audit, trivy fs) # ✓ Check for secrets in code (gitleaks, trufflehog) # BUILD: # ✓ Use multi-stage build # ✓ Don't include secrets in build context # ✓ Use BuildKit secret mounts # ✓ Pin base image versions # POST-BUILD: # ✓ Scan image for CVEs (trivy, grype) # ✓ Sign image (cosign, Docker Content Trust) # ✓ Push to secure registry # PRE-DEPLOY: # ✓ Verify image signature # ✓ Check compliance (CIS benchmark) # ✓ Run integration tests # POST-DEPLOY: # ✓ Runtime monitoring (Falco) # ✓ Audit logging # ✓ Periodic re-scan of running containers
11. Quiz Pemahaman
Uji pemahaman Anda tentang Docker Security:
1. Mengapa menjalankan container sebagai root berbahaya?
2. Apa fungsi cap_drop: ALL di Docker Compose?
3. Mengapa Docker socket tidak boleh di-mount ke container?
4. Apa keuntungan multi-stage build dari sisi keamanan?
5. Apa itu Docker Content Trust?