# devops / docker / security

Control Resources & Harden Security

By default, a Docker container can consume 100% of your host's CPU and RAM. A single memory leak or infinite loop can hang your entire server. Learn to lock down resources and build layered security to keep your infrastructure bulletproof.

$ docker stats safe-app
CPU %12.40% (Max 50.0%)
MEM USAGE140MiB / 512MiB
PRIVILEGESDropped
FILESYSTEMRead-Only
0.5
CPU Limit
512m
RAM Limit
# resources

CPU & Memory Limits

Resource control revolves around two critical concepts:
👉 Reservation = A soft promise ("at least this much").
👉 Limit = A hard stop ("never more than this").

GOLDEN RULE

Never allocate 100% of host resources to your containers. Always leave 20–30% free for the host OS and the Docker daemon to function.

KUBERNETES FYI

While Docker uses fractional CPUs (0.5), K8s uses millicores. 100m = 0.1 CPU (10%). 1000m = 1 full CPU core.

terminal
# Memory: Reserve 256MB, Hard Kill at 512MB
$ docker run -d --name web1 \
> --memory-reservation=256m \
> --memory=512m httpd
 
# CPU: Max 50% of 1 core
$ docker run -d --name web2 --cpus="0.5" httpd
 
# CPU Shares (Priority)
# Default is 1024. A container with 512 gets half priority.
$ docker run -d --name web3 --cpu-shares=512 httpd
 
# Prevent Slow Disk Swapping
# Forces the container to ONLY use RAM, no disk swap.
$ docker run -d --memory=512m --memory-swap=512m httpd
# monitoring

Observability & Capacity Planning

live view

Live Container Usage

Run docker stats in your terminal. It shows real-time CPU %, Memory usage, Network I/O, and Disk I/O for all running containers.

inspection

Inspect Hard Limits

Run docker inspect <container> to verify the exact parameters. Look under the HostConfig block for Memory, CpuQuota, and CpuShares.

🧮 Real Planning Example

  • Host Specs

    4 CPUs and 8 GB RAM.

  • OS Overhead

    Reserve 30% for OS.
    Usable CPU ≈ 2.8 | Usable RAM ≈ 5.6 GB

  • Workload

    Deploy 4 instances of your app.
    Give each --cpus=0.5 and --memory=1g.

  • Result

    Containers use 2 CPUs and 4 GB RAM total. You have a stable system, room for traffic spikes, and no crashes ✅.

# security

Security Layers & Best Practices

Even with limits, containers can be dangerous if hacked. A bad container can attack neighbors, steal secrets, or escape to the host machine. Security isn't a single switch; it is layered protection.

🛡️ 10 Security Best Practices

  • 1

    Minimal Base Images: Smaller image = fewer vulnerabilities. (e.g., FROM alpine:3.18)

  • 2

    Never Run as Root: Create a dedicated user in the Dockerfile. If hacked, the attacker gets a limited user. (e.g., USER appuser)

  • 3

    Keep Images Updated: Old images have known CVEs. Rebuild regularly with --no-cache.

  • 4

    Multi-Stage Builds: Builder gets the tools; the final image only gets the compiled app. Smaller and safer.

  • 5

    Drop Capabilities: Remove unnecessary Linux privileges at runtime. (--cap-drop=ALL)

  • 6

    Prevent Privilege Escalation: Stop attackers from gaining extra rights. (--security-opt=no-new-privileges)

  • 7

    Resource Limits: Protects against Denial of Service (DoS) attacks.

  • 8

    Network Hygiene: Expose only required ports. Avoid --network host unless absolutely necessary.

  • 9

    Image Scanning: Use tools like Trivy or Clair to scan images before deployment.

  • 10

    One Process Per Container: Avoid running SSH inside containers or bundling multiple services together.

# production

The Ultimate Secure Run Command

terminal
$ docker run -d --name safe-app \
> --memory=512m --cpus="0.5" \
> --security-opt=no-new-privileges \
> --cap-drop=ALL \
> --read-only \
> --tmpfs /tmp:rw,size=64m \
> myuser/app:1.0

Why is this so secure?

1. Limited CPU/RAM stops DoS attacks.
2. no-new-privileges blocks exploits like `sudo`.
3. cap-drop=ALL strips Linux kernel powers.
4. read-only makes the filesystem immutable; hackers can't download malware.
5. tmpfs provides just enough temporary RAM space for the app to write logs, disappearing instantly on exit.