Container Security & DevSecOps Fundamentals

Cybersecurity
December 1, 2025 4 min read by terdiam

Container security is not an afterthought—it must be integrated into every stage of your application lifecycle. This guide covers essential DevSecOps practices for securing containerized applications.

Introduction

As containerization becomes more prevalent, security threats evolve. From vulnerable base images to runtime exploits, containers present unique security challenges. DevSecOps integrates security into development and operations workflows, making security a shared responsibility.

1. Image Security

Use Minimal Base Images

Start with minimal base images to reduce the attack surface:

# Bad: Uses full OS image
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3 pip
RUN pip install flask

# Good: Uses minimal Python image
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

Scan for Vulnerabilities

Use tools like Trivy to scan images:

trivy image myapp:latest
trivy image --severity HIGH,CRITICAL myapp:latest

Non-Root User

Always run containers as non-root:

RUN useradd -m -u 1000 appuser
USER appuser

2. Build Security

Multi-Stage Builds

Use multi-stage builds to minimize image size and exposure:

# Build stage
FROM golang:1.21 as builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 go build -o app .

# Runtime stage
FROM scratch
COPY --from=builder /build/app /app
ENTRYPOINT ["/app"]

Supply Chain Security

Implement signed commits and signed container images:

# Sign container image
cosign sign myregistry.azurecr.io/myapp:latest

# Verify signature
cosign verify myregistry.azurecr.io/myapp:latest

3. Registry Security

Private Registries

Use private container registries with proper authentication:

apiVersion: v1
kind: Secret
metadata:
  name: regcred
type: kubernetes.io/dockercfg
data:
  .dockercfg: <base64-encoded-config>

Image Signing and Attestation

Implement image signing for supply chain security:

# Sign image with cosign
cosign sign --key cosign.key myregistry.azurecr.io/myapp:latest

# Verify with public key
cosign verify --key cosign.pub myregistry.azurecr.io/myapp:latest

4. Runtime Security

Pod Security Standards

Enforce security standards at the pod level:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'MustRunAs'
  fsGroup:
    rule: 'MustRunAs'
  readOnlyRootFilesystem: true

Network Policies

Restrict traffic with network policies:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-network-policy
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
    - podSelector:
        matchLabels:
          app: frontend
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: TCP
      port: 53

5. CI/CD Pipeline Security

Container Scanning in Pipeline

Integrate scanning into your CI/CD:

stages:
  - build
  - scan
  - deploy

build:
  stage: build
  script:
    - docker build -t myapp:$CI_COMMIT_SHA .

scan:
  stage: scan
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:$CI_COMMIT_SHA
  allow_failure: false

deploy:
  stage: deploy
  script:
    - kubectl apply -f k8s/

Secret Management

Never store secrets in code or container images:

# Use external secret management
# HashiCorp Vault
vault kv get secret/database/credentials

# AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id db/prod/password

# Kubernetes Secrets
kubectl create secret generic db-credentials \
  --from-literal=password=$DB_PASSWORD

6. Compliance and Auditing

Logging and Monitoring

Implement comprehensive logging:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  verbs: ["create", "update", "patch", "delete"]
  omitStages:
  - RequestReceived

Regular Audits

  • Automated vulnerability scanning
  • Penetration testing
  • Compliance checks against standards (CIS, PCI-DSS)
  • Code review and security reviews

7. Incident Response

Prepare for Incidents

  • Document security incidents response procedures
  • Have rollback plans ready
  • Maintain backups
  • Test disaster recovery procedures

Best Practices Summary

  1. Start Secure: Begin with secure base images and minimal dependencies
  2. Scan Everything: Scan images, dependencies, and code regularly
  3. Least Privilege: Run containers as non-root with minimal permissions
  4. Network Segmentation: Use network policies to restrict traffic
  5. Secret Management: Never hardcode secrets
  6. Audit and Monitor: Log all activities and monitor for anomalies
  7. Continuous Learning: Stay updated with security advisories and best practices

Conclusion

Container security requires a holistic approach spanning development, deployment, and operations. By implementing these DevSecOps practices, you can significantly reduce the attack surface and build more resilient systems.

Remember: security is a journey, not a destination. Continuously improve your practices, stay informed about emerging threats, and make security a core value in your organization.

#security #docker #kubernetes #devsecops

Have thoughts or want to discuss?

I'd love to hear your thoughts on this article or discuss related topics.

Send Me a Message