Docker: Guía Completa de Containerización para DevOps

Docker ha revolucionado la manera en que desarrollamos, desplegamos y escalamos aplicaciones. Esta guía cubre desde conceptos básicos hasta técnicas avanzadas para optimizar tu workflow DevOps.

Fundamentos de Docker

Instalación y Configuración

# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# Verificar instalación
docker --version
docker run hello-world

Comandos Esenciales

# Gestión de imágenes
docker images
docker pull nginx:alpine
docker rmi image_id

# Gestión de contenedores
docker ps -a
docker run -d --name webserver -p 80:80 nginx:alpine
docker stop webserver
docker rm webserver

Creación de Imágenes Optimizadas

Dockerfile Multistage

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

FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
USER node
CMD ["npm", "start"]

Mejores Prácticas de Seguridad

# Imagen base mínima
FROM alpine:3.18

# Crear usuario no privilegiado
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nextjs -u 1001

# Instalar dependencias específicas
RUN apk add --no-cache nodejs npm

# Configurar directorio de trabajo
WORKDIR /app
COPY --chown=nextjs:nodejs . .

# Cambiar a usuario no privilegiado
USER nextjs

EXPOSE 3000
CMD ["node", "server.js"]

Docker Compose para Desarrollo

Stack LAMP Completo

# docker-compose.yml
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./src:/var/www/html
    depends_on:
      - php

  php:
    build:
      context: .
      dockerfile: php.Dockerfile
    volumes:
      - ./src:/var/www/html
    depends_on:
      - db
      - redis

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: appdb
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - "3306:3306"

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

volumes:
  mysql_data:
  redis_data:

networks:
  default:
    driver: bridge

Variables de Entorno y Secrets

# docker-compose.prod.yml
version: '3.8'

services:
  app:
    image: myapp:latest
    environment:
      - NODE_ENV=production
      - DATABASE_URL_FILE=/run/secrets/db_url
    secrets:
      - db_url
      - api_key

secrets:
  db_url:
    external: true
  api_key:
    external: true

Networking y Comunicación

Redes Personalizadas

# Crear red personalizada
docker network create --driver bridge mynetwork

# Ejecutar contenedores en la red
docker run -d --name db --network mynetwork mysql:8.0
docker run -d --name app --network mynetwork myapp:latest

# Inspeccionar red
docker network inspect mynetwork

Service Discovery

# docker-compose con service discovery
version: '3.8'

services:
  frontend:
    image: nginx:alpine
    depends_on:
      - backend
    environment:
      - BACKEND_URL=http://backend:3000

  backend:
    image: node:18-alpine
    environment:
      - DB_HOST=database
      - REDIS_URL=redis://cache:6379

  database:
    image: postgres:15-alpine

  cache:
    image: redis:7-alpine

Gestión de Volúmenes y Datos

Estrategias de Persistencia

# Volúmenes nombrados para datos críticos
docker volume create postgres_data
docker run -d --name db \
  -v postgres_data:/var/lib/postgresql/data \
  postgres:15-alpine

# Bind mounts para desarrollo
docker run -d --name web \
  -v $(pwd)/src:/var/www/html \
  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx:alpine

Backup y Restauración

# Backup de volumen
docker run --rm \
  -v postgres_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/postgres_backup.tar.gz -C /data .

# Restauración de backup
docker run --rm \
  -v postgres_data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/postgres_backup.tar.gz -C /data

Monitoreo y Logs

Configuración de Logging

# docker-compose con logging centralizado
version: '3.8'

services:
  app:
    image: myapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      - "traefik.enable=true"

  logspout:
    image: gliderlabs/logspout
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: syslog+tls://logs.papertrailapp.com:12345

Health Checks

# Dockerfile con health check
FROM nginx:alpine

COPY nginx.conf /etc/nginx/nginx.conf
COPY . /usr/share/nginx/html

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

EXPOSE 80

CI/CD con Docker

Pipeline GitLab CI

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

build:
  stage: build
  services:
    - docker:20.10.16-dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

test:
  stage: test
  script:
    - docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test

deploy:
  stage: deploy
  script:
    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker-compose up -d
  only:
    - main

Optimización de Performance

Caché de Capas

# Optimización de build cache
FROM node:18-alpine

WORKDIR /app

# Copiar solo package.json primero
COPY package*.json ./
RUN npm ci --only=production

# Copiar código después
COPY . .

# Build en capas separadas
RUN npm run build

EXPOSE 3000
CMD ["npm", "start"]

Imagen Multi-Arch

# Build para múltiples arquitecturas
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 \
  -t myapp:latest --push .

Seguridad Avanzada

Escaneo de Vulnerabilidades

# Instalar Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin

# Escanear imagen
trivy image nginx:alpine
trivy image --severity HIGH,CRITICAL myapp:latest

Configuración Segura

# Ejecutar con restricciones de seguridad
docker run --read-only --tmpfs /tmp \
  --cap-drop=ALL --cap-add=NET_BIND_SERVICE \
  --no-new-privileges \
  --user 1001:1001 \
  myapp:latest

Conclusión

Docker en DevOps requiere:

  • Imágenes optimizadas y seguras
  • Orquestación eficiente con Compose
  • Estrategias sólidas de persistencia
  • Integración en pipelines CI/CD
  • Monitoreo y observabilidad continua

Dominar estos conceptos te permitirá crear workflows DevOps robustos y escalables.