TL;DR
Explore how containers revolutionize DevOps practices and learn best practices for container orchestration.
The Role of Containers in DevOps: Docker and Beyond
Containers have revolutionized how we build, ship, and run applications. This guide explores container technologies and their role in modern DevOps practices.
$1
$1
`` graph TD
A[Application] --> B[Container]
B --> C[Container Runtime]
C --> D[Host OS]
D --> E[Infrastructure]
mermaid
`
$1
` container:
characteristics:
- Lightweight
- Shares host OS kernel
- Fast startup
- Minimal overhead
virtual_machine:
characteristics:
- Complete OS
- Hardware virtualization
- More isolated
- Higher overhead
yaml
`
$1
$1
` FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
dockerfile
`Multi-stage build example
$1
` version: '3.8' services:
web:
build: .
ports:
- "3000:80"
environment:
NODE_ENV: production
depends_on:
- db
db:
image: postgres:13
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD} volumes:
db_data:
yaml
`docker-compose.yml
$1
$1
` FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
USER node
CMD ["node", "dist/main.js"]
dockerfile
`Optimized Dockerfile
$1
` security_practices:
image:
- Use official base images
- Scan for vulnerabilities
- Keep base images updated
runtime:
- Run as non-root
- Use read-only root filesystem
- Implement resource limits
secrets:
- Use secret management
- Never bake secrets into images
- Rotate credentials regularly
yaml
`
$1
$1
` apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: web-app:1.0.0
ports:
- containerPort: 80
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "0.5"
memory: "256Mi"
yaml
`deployment.yaml
$1
` apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
yaml
`service.yaml
$1
$1
` networks:
bridge:
description: Default network driver
use_case: Container-to-container communication
host:
description: Uses host network stack
use_case: Maximum performance
overlay:
description: Multi-host networking
use_case: Swarm services
yaml
`
$1
` apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080
yaml
`network-policy.yaml
$1
$1
` version: '3.8'
services:
app:
image: myapp
volumes:
- type: volume
source: app_data
target: /data
- type: bind
source: ./config
target: /config
read_only: true volumes:
app_data:
driver: local
driver_opts:
type: none
device: /path/to/data
o: bind
yaml
`docker-compose with volumes
$1
` apiVersion: v1
kind: PersistentVolume
metadata:
name: app-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
storageClassName: standard
hostPath:
path: /data/app-volume
yaml
`persistent-volume.yaml
$1
$1
` scrape_configs:
- job_name: 'containers'
static_configs:
- targets: ['localhost:9090']
metrics_path: /metrics
relabel_configs:
- source_labels: [__meta_docker_container_name]
target_label: container_name
yaml
`prometheus-config.yaml
$1
` @type tail
path /var/log/containers/*.log
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
read_from_head true
@type json
time_key time
time_format %Y-%m-%dT%H:%M:%S.%NZ
yaml
`fluentd-config.yaml
$1
$1
` name: Container Build on:
push:
branches: [ main ] jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
myregistry.azurecr.io/myapp:${{ github.sha }}
myregistry.azurecr.io/myapp:latest
yaml
`GitHub Actions workflow
$1
` stages:
- build
- test
- deploy build_container:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA deploy_container:
stage: deploy
script:
- kubectl set image deployment/myapp container=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
yaml
`deployment-pipeline.yml
$1
$1
` apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
yaml
`hpa.yaml
$1
` apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
yaml
`ingress.yaml
$1
$1
` development_workflow:
local:
- Use docker-compose for local development
- Mount source code as volumes
- Enable hot reload
testing:
- Run tests in containers
- Use same environment as production
- Implement integration tests
deployment:
- Use CI/CD pipelines
- Implement blue-green deployments
- Monitor container health
yaml
`
$1
` production_guidelines:
security:
- Regular security scans
- Implement least privilege
- Use container runtime security
performance:
- Resource optimization
- Cache management
- Performance monitoring
maintenance:
- Regular updates
- Backup strategies
- Disaster recovery plans
yaml
``
$1
Effective container usage in DevOps requires:
1. Understanding container fundamentals
2. Implementing security best practices
3. Proper orchestration and scaling
4. Robust monitoring and logging
5. Efficient CI/CD integration
Remember to:
Why This Matters
Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.
Trade-offs to Consider
Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.
When NOT to Use This
Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.
Decision Framework
Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.