Back to Blog
Guide7 min read2026-05-01

Container Security: What Every Developer Needs to Know

From image hardening to runtime protection, here is everything developers need to secure containers in production.

Container Security: What Every Developer Needs to Know

Containers changed how we ship software. They also changed the threat model. Traditional security focused on securing servers — containers require you to think about images, orchestration, networking, and runtime all at once. This guide demystifies container security for developers who want to ship confidently.

PandaStack runs Docker containers in production for thousands of applications. Here's what we've learned about securing them.

Why Container Security Is Different

Containers are not VMs. They share the host kernel, which means:

  • A vulnerability in the kernel can affect every container on the host
  • Misconfigured containers can escape to the host
  • Shared image layers mean a vulnerability in a base image affects all images that build on it

Securing containers requires action at multiple layers: build time, registry, and runtime.

Step 1: Harden Your Dockerfile

Security starts at build time. Use multi-stage builds to keep your final image lean:

# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Final stage — no build tools
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
RUN adduser -D appuser
USER appuser
EXPOSE 3000
CMD ["node", "src/index.js"]

Multi-stage builds exclude compilers, package managers, and test dependencies from production images.

Step 2: Scan Images in CI

Integrate vulnerability scanning into your build pipeline:

# Install Trivy
brew install trivy

# Scan before push
trivy image --exit-code 1 --severity HIGH,CRITICAL my-app:latest

The --exit-code 1 flag fails the build if high or critical vulnerabilities are found.

Step 3: Use a Private Container Registry

Push images to a private registry, not Docker Hub public repos. Enforce image signing:

# Sign image with cosign
cosign sign --key cosign.key my-registry.io/my-app:latest

# Verify before deploy
cosign verify --key cosign.pub my-registry.io/my-app:latest

Only allow signed images to run in production.

Step 4: Limit Container Capabilities

Containers inherit Linux capabilities they don't need. Drop them all, then add back only what's required:

docker run   --cap-drop ALL   --cap-add NET_BIND_SERVICE   --security-opt no-new-privileges   my-app:latest

The no-new-privileges flag prevents privilege escalation via setuid binaries.

Step 5: Use Read-Only Root Filesystems

If your app doesn't need to write to the container filesystem, don't allow it:

docker run --read-only --tmpfs /tmp --tmpfs /var/run my-app:latest

This prevents attackers from writing malicious files if they gain code execution.

Step 6: Never Mount the Docker Socket

Mounting /var/run/docker.sock into a container gives it full control over the Docker daemon — effectively root on the host. Avoid it. Use dedicated APIs or sidecars for any use case that seems to require it.

Step 7: Network Segmentation

Containers should only communicate with the services they need. Use Docker networks to isolate groups:

# Create isolated network
docker network create --driver bridge app-network

# Attach only the containers that need to communicate
docker run --network app-network my-api
docker run --network app-network my-db

On PandaStack, containers in the same deployment environment share a private network — external access is controlled through the platform's routing layer.

Step 8: Manage Secrets at Runtime

Never bake secrets into images. Inject them at runtime:

# Via PandaStack CLI
npm install -g @pandastack/cli
panda env:set API_KEY=my-secret-key --app my-app

Secrets are encrypted at rest and injected as environment variables at container startup — they never appear in image layers or build logs.

Step 9: Set Resource Limits

Prevent a compromised or buggy container from consuming all host resources (a form of denial-of-service):

docker run --memory="256m" --memory-swap="256m" --cpus="0.25" my-app

Step 10: Monitor Container Behavior at Runtime

Static security checks at build time catch known vulnerabilities. Runtime monitoring catches unexpected behavior — unusual network calls, new processes spawning, filesystem changes in unexpected locations.

PandaStack provides built-in monitoring and alerting for all container deployments. Configure thresholds and notification channels at [dashboard.pandastack.io](https://dashboard.pandastack.io).

Summary

Container security spans the full lifecycle: harden your Dockerfile, scan images in CI, use a private registry with signing, drop capabilities, use read-only filesystems, segment networks, manage secrets properly, set resource limits, and monitor at runtime. Build these practices into your workflow from day one. Full platform documentation at [docs.pandastack.io](https://docs.pandastack.io).

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

More in Guide

Browse all Guide articles →

See also