Containerization & Kubernetes with Security Hardening
This skill provides comprehensive patterns for containerizing applications and deploying to Kubernetes in 2025, focusing on zero-trust security, multi-stage optimization, production hardening, and cloud-native best practices that work across different cloud providers.
When to Use This Skill
Use this skill when you need to:
- Create secure multi-stage Docker builds
- Deploy applications to Kubernetes with security hardening
- Implement zero-trust security patterns
- Set up GitOps workflows with ArgoCD/Flux
- Optimize container images for production
- Configure cluster security with Pod Security Standards
- Implement secure networking with service meshes
- Set up monitoring and observability
- Deploy to multiple cloud providers (AWS, GCP, Azure, DO)
Secure Multi-Stage Docker Builds
1. Security-First Multi-Stage Builds
# Dockerfile with security hardening
# Build stage
FROM python:3.11-slim AS builder
# Set build-time security arguments
ARG DEBIAN_FRONTEND=noninteractive
ARG DEBCONF_NONINTERACTIVE_SEEN=true
ARG BUILDPLATFORM
ARG TARGETPLATFORM
# Install build dependencies with security updates
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
ca-certificates \
curl \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
truncate -s 0 /var/log/apt/history.log
# Create non-root user for build
RUN groupadd -r builder && \
useradd -r -g builder builder
# Set working directory
WORKDIR /app
# Copy dependency files
COPY requirements.txt requirements-dev.txt ./
# Install Python dependencies in virtual environment
RUN python -m venv /opt/venv && \
/opt/venv/bin/pip install --no-cache-dir -U pip && \
/opt/venv/bin/pip install --no-cache-dir -r requirements.txt
# Production stage
FROM python:3.11-slim AS production
# Security labels
LABEL maintainer="security-team@company.com" \
version="1.0.0" \
security.scan="enabled" \
org.opencontainers.image.vendor="Company"
# Install runtime dependencies with security updates
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
libpq5 \
ca-certificates \
curl \
dumb-init \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
truncate -s 0 /var/log/apt/history.log
# Copy virtual environment from builder
COPY --from=builder /opt/venv /opt/venv
# Create non-root user for runtime
RUN groupadd -r appuser && \
useradd -r -g appuser -s /bin/sh appuser
# Set working directory
WORKDIR /app
# Copy application code
COPY --chown=appuser:appuser app/ ./app/
COPY --chown=appuser:appuser alembic/ ./alembic/
COPY --chown=appuser:appuser alembic.ini .
# Set permissions
RUN chmod -R 755 /app && \
chmod -x /app/alembic.ini
# Switch to non-root user
USER appuser
# Set PATH
ENV PATH="/opt/venv/bin:$PATH"
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Security scan before running
RUN python -c "import urllib.request; urllib.request.urlopen('https://security-scan.example.com/scan')"
# Expose port
EXPOSE 8000
# Use dumb-init as PID 1
ENTRYPOINT ["dumb-init", "--"]
# Run the application
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers=4", "--access-log=-"]
2. Docker Security Best Practices
# Dockerfile.security
# Base security hardening
FROM python:3.11-slim AS base
# Kernel security settings
RUN sysctl -w net.ipv4.ip_forward=1 && \
sysctl -w net.ipv6.conf.all.forwarding=1 && \
sysctl -w net.ipv4.conf.all.send_redirects=0 && \
sysctl -w net.ipv4.conf.default_accept_source_route=0 && \
sysctl -w kernel.dmesg_restrict=1
# Remove setuid/setgid binaries
RUN find / -type f -perm /6000 -exec chmod a-s {} \; || true && \
find / -type f -perm /4000 -exec chmod a+r {} \; || true
# Security scanning
RUN apt-get update && \
apt-get install -y trivy && \
trivy image --severity HIGH,CRITICAL python:3.11-slim
# Production application with security
FROM base AS production
# Add security labels
LABEL \
security.stack.linux.docker.image-version="1" \
security.stack.linux.docker.kernel-version="6.x" \
security.stack.linux.docker.os-version="Debian 12" \
security.stack.cis.docker.version="1.6.0"
# Implement runtime security
RUN apt-get update && \
apt-get install -y \
apparmor-profiles \
fail2ban \
rkhunter \
chkrootkit \
&& \
apt-get clean
# Configure fail2ban
COPY fail2ban.conf /etc/fail2ban/jail.local
# Configure AppArmor
COPY apparmor-profiles /etc/apparmor.d/
# Security runtime checks
RUN python -c "
import subprocess
import sys
# Check for vulnerable packages
result = subprocess.run(['apt', 'list', '--upgradable'],
capture_output=True, text=True)
if result.stdout.strip():
print('WARNING: Packages need updates:', result.stdout.strip())
sys.exit(1)
"
3. Zero-Trust Kubernetes Deployment
# manifests/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
name: production
security-tier: "high"
environment: "production"
annotations:
pod-security.kubernetes.io/enforce: "restricted"
pod-security.kubernetes.io/audit: "restricted"
pod-security.kubernetes.io/warn: "restricted"
---
# manifests/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: production-apps
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "daemonsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies"]
verbs: ["get", "list", "create", "update", "patch"]
---
apiVersion: rbac.authorization.kubernetes.io/v1
kind: ClusterRoleBinding
metadata:
name: production-apps-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: production-apps
subjects:
- kind: ServiceAccount
name: default
namespace: production
---
# manifests/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# Deny all ingress and egress by default
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to: []
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to: []
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 53
---
# manifests/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
labels:
app: secure-app
tier: application
version: v1
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
tier: application
version: v1
security.stack.company.com/container-security-level: "high"
security.stack.company.com/network-segment: "application"
annotations:
container.security.kubernetes.io/scc: "restricted"
seccomp.security.kubernetes.io/profile: "runtime/default"
kubernetes.io/psp: "restricted"
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
readOnlyRootFilesystem: fals