#Lab: Docker Security Best Practices
Implement security best practices for containers.
#🎯 Objectives
- Run containers as non-root
- Scan images for vulnerabilities
- Implement resource limits
- Use read-only filesystems
#📋 Prerequisites
- Docker installed
#⏱️ Duration: 30 minutes
#Task 1: Non-Root Containers (10 min)
#Check Current User
bash
1# Default: runs as root
2docker run --rm alpine whoami
3# Output: root
4
5docker run --rm alpine id
6# Output: uid=0(root) gid=0(root)#Run as Specific User
bash
1# Run as nobody user
2docker run --rm --user nobody alpine whoami
3
4# Run with specific UID/GID
5docker run --rm --user 1000:1000 alpine id
6
7# Create Dockerfile with non-root user
8cat << 'EOF' > Dockerfile.secure
9FROM alpine:3.18
10RUN addgroup -g 1001 appgroup && \
11 adduser -u 1001 -G appgroup -D appuser
12USER appuser
13CMD ["whoami"]
14EOF
15
16docker build -t secure-app -f Dockerfile.secure .
17docker run --rm secure-app#Task 2: Resource Limits (5 min)
bash
1# Limit memory
2docker run -d --memory="128m" --name mem-limited nginx
3
4# Limit CPU
5docker run -d --cpus="0.5" --name cpu-limited nginx
6
7# Combined limits
8docker run -d \
9 --memory="256m" \
10 --memory-swap="256m" \
11 --cpus="1" \
12 --name limited nginx
13
14# Check resource usage
15docker stats --no-stream#Task 3: Read-Only Filesystem (5 min)
bash
1# Read-only root filesystem
2docker run -d \
3 --read-only \
4 --tmpfs /tmp \
5 --tmpfs /var/cache/nginx \
6 --tmpfs /var/run \
7 --name readonly-nginx nginx
8
9# Verify it's read-only
10docker exec readonly-nginx touch /test 2>&1 | head -1
11# Output: touch: /test: Read-only file system
12
13# But /tmp is writable
14docker exec readonly-nginx touch /tmp/test
15docker exec readonly-nginx ls /tmp/test#Task 4: Drop Capabilities (5 min)
bash
1# Drop all capabilities except needed ones
2docker run -d \
3 --cap-drop=ALL \
4 --cap-add=NET_BIND_SERVICE \
5 --name minimal-caps nginx
6
7# Check capabilities
8docker exec minimal-caps cat /proc/1/status | grep Cap
9
10# Comparison: full capabilities
11docker run --rm alpine cat /proc/1/status | grep Cap#Task 5: Image Scanning (5 min)
bash
1# Using Docker Scout (if available)
2docker scout cves nginx:latest
3
4# Using Trivy (install first: https://trivy.dev)
5# trivy image nginx:latest
6
7# Check for vulnerabilities in your image
8docker build -t myapp:test .
9# docker scout cves myapp:test#Security Checklist
- Containers run as non-root
- Memory and CPU limits set
- Read-only filesystem where possible
- Minimal capabilities
- Images scanned for vulnerabilities
- Secrets not baked into images
- Using specific image tags (not :latest)
#🧹 Cleanup
bash
1docker stop mem-limited cpu-limited limited readonly-nginx minimal-caps 2>/dev/null
2docker rm mem-limited cpu-limited limited readonly-nginx minimal-caps 2>/dev/null
3docker rmi secure-app 2>/dev/null
4rm -f Dockerfile.secure