Securing Docker Containers: A Practical Guide
Securing Docker Containers: A Practical Guide
Container security is often overlooked until it's too late. This guide covers essential practices to harden your Docker containers and infrastructure.
1. Use Trusted Base Images
Always pull from official or verified publishers.
# BAD
FROM node:latest
# GOOD
FROM node:18-alpine
Why?
- Verified: Maintained by the official team
- Smaller: Alpine/Slim images have smaller attack surface
- Pinned: Specify version to avoid unexpected breaking changes
2. Run as Non-Root User
By default, Docker containers run as root. This is a security risk.
FROM node:18-alpine
WORKDIR /app
COPY . .
# Create a group and user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Change ownership
RUN chown -R appuser:appgroup /app
# Switch to non-root user
USER appuser
CMD ["npm", "start"]
3. Scan Images for Vulnerabilities
Integrate scanning into your CI/CD pipeline using tools like Trivy or Snyk.
Scanning with Trivy
# Install Trivy
apt-get install trivy
# Scan an image
trivy image my-app:latest
GitHub Actions Integration
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:latest'
format: 'table'
exit-code: '1'
ignore-unfixed: true
vuln-type: 'os,library'
severity: 'CRITICAL,HIGH'
4. Limit Resources
Prevent DoS attacks by limiting CPU and memory.
docker run -d \
--cpus="0.5" \
--memory="512m" \
my-app
Or in Docker Compose:
services:
app:
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
5. Network Security
Don't expose all ports. Use Docker networks to isolate containers.
services:
db:
image: postgres
networks:
- backend-net # Only accessible to backend services
api:
image: my-api
networks:
- backend-net
- frontend-net
ports:
- "8080:8080" # Only expose the API, not the DB
6. Secrets Management
Never bake secrets into images or use environment variables for sensitive data if possible. Use Docker Secrets or a vault.
# BAD
ENV DB_PASSWORD=secret
# GOOD (Use at runtime)
--entrypoint sh -c "export DB_PASSWORD=$(cat /run/secrets/db_password)"
7. Keep Docker Updated
Regularly update the Docker engine and container runtime to patch security vulnerabilities like runc escapes.
Conclusion
Container security is a multi-layer process:
- Secure the build (Dockerfile, Scanning)
- Secure the registry (Access Control, Signing)
- Secure the runtime (Resource limits, Non-root)
- Secure the host (OS patching, Network isolation)
By following these practices, you significantly reduce the request risk of a breach.