Docker para Principiantes: Contenedoriza Tus Apps
## ¿Qué es Docker?
Docker es una plataforma de automatización de despliegue de aplicaciones dentro de contenedores de software. Un contenedor empaqueta una aplicación con todo lo que necesita para ejecutarse: código, runtime, librerías, variables de entorno y archivos de configuración.
La diferencia clave con las máquinas virtuales es que los contenedores comparten el kernel del sistema operativo del host, haciéndolos mucho más ligeros, rápidos y eficientes.
¿Por qué usar Docker?
- **Consistencia**: "Funciona en mi máquina" deja de ser un problema. Si funciona en el contenedor, funciona en cualquier lugar.
- **Aislamiento**: Cada contenedor tiene su propio sistema de archivos y dependencias, sin conflictos.
- **Portabilidad**: Los contenedores ejecutan en cualquier sistema que tenga Docker instalado.
- **Velocidad**: Arrancar un contenedor toma segundos,不像 arrancar una VM que toma minutos.
- **Escalabilidad**: Fácilmente despliega múltiples instancias de tu aplicación.
- **Reproducibilidad**: Cada deploy es idéntico al anterior.
Instalación
Linux (Ubuntu/Debian)
# Actualizar el índice de paquetes
sudo apt update# Instalar dependencias sudo apt install -y ca-certificates curl gnupg
# Agregar la clave GPG oficial de Docker sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Agregar el repositorio echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Instalar Docker sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Agregar tu usuario al grupo docker (para evitar usar sudo) sudo usermod -aG docker $USER newgrp docker
# Verificar instalación docker --version docker run hello-world ```
Windows
- Descarga Docker Desktop desde [docker.com](https://www.docker.com/products/docker-desktop/).
- Ejecuta el instalador.
- Asegúrate de tener WSL2 habilitado (se recomienda) o Hyper-V.
- Reinicia el computer si es necesario.
- Abre Docker Desktop y verifica la instalación.
macOS
# Usando Homebrew (recomendado)
brew install --cask docker# O descarga desde docker.com/products/docker-desktop ```
Conceptos Fundamentales
Imágenes (Images)
Una imagen Docker es una plantilla de solo lectura que contiene todo lo necesario para ejecutar una aplicación. Las imágenes se construyen a partir de un Dockerfile y se almacenan en un registro como Docker Hub.
# Listar imágenes locales
docker images# Buscar imágenes en Docker Hub docker search nginx
# Descargar una imagen docker pull ubuntu:22.04 docker pull node:18-alpine docker pull postgres:15 ```
Contenedores (Containers)
Un contenedor es una instancia ejecutable de una imagen. Es como un proceso aislado con su propio sistema de archivos, red y espacio de procesos.
# Ejecutar un contenedor interactivo
docker run -it ubuntu:22.04 bash# Ejecutar un contenedor en background docker run -d --name mi-web nginx
# Ver contenedores ejecutándose docker ps
# Ver todos los contenedores (incluyendo los detenidos) docker ps -a
# Detener un contenedor docker stop mi-web
# Eliminar un contenedor docker rm mi-web ```
Dockerfiles
Un Dockerfile es un archivo de texto con instrucciones paso a paso para construir una imagen Docker.
# Dockerfile para una aplicación Node.js# 1. Usar una imagen base oficial de Node.js FROM node:18-alpine AS builder
# 2. Establecer el directorio de trabajo WORKDIR /app
# 3. Copiar archivos de dependencias primero (mejora el caché) COPY package*.json ./ COPY prisma ./prisma/
# 4. Instalar dependencias RUN npm ci RUN npx prisma generate
# 5. Copiar el código fuente COPY . .
# 6. Compilar la aplicación RUN npm run build
# 7. Etapa de producción (multi-stage build) FROM node:18-alpine AS runner
WORKDIR /app
# Copiar solo los archivos necesarios COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./
# Variables de entorno ENV NODE_ENV=production ENV PORT=3000
# Exponer el puerto EXPOSE 3000
# Comando para ejecutar la aplicación CMD ["npm", "start"] ```
Volumes (Volúmenes)
Los volúmenes permiten persistir datos fuera del contenedor y compartir datos entre contenedores.
# Crear un volumen nombrado
docker volume create mi-volumen# Montar un volumen al ejecutar un contenedor docker run -d \ --name mi-postgres \ -e POSTGRES_PASSWORD=secret \ -v mi-volumen:/var/lib/postgresql/data \ -p 5432:5432 \ postgres:15
# Montar un directorio local (bind mount) docker run -d \ -v $(pwd)/mi-codigo:/app \ -p 3000:3000 \ node:18-alpine ```
# Listar volúmenes
docker volume ls# Inspeccionar un volumen docker volume inspect mi-volumen
# Eliminar un volumen docker volume rm mi-volumen ```
Dockerfile de Ejemplo Completo
# ============================================
# Dockerfile para una API REST con Express
# ============================================# Imagen base FROM node:18-alpine
# Metadatos LABEL maintainer="System 777" LABEL description="API REST con Express.js"
# Variables de entorno ENV NODE_ENV=production ENV PORT=3000
# Crear usuario no-root para seguridad RUN addgroup -g 1001 -S nodejs RUN adduser -S nodeuser -u 1001
# Directorio de trabajo WORKDIR /app
# Copiar archivos de dependencias COPY package*.json ./
# Instalar dependencias RUN npm ci --only=production
# Copiar código fuente COPY . .
# Cambiar al usuario no-root USER nodeuser
# Exponer puerto EXPOSE 3000
# Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
# Comando de inicio CMD ["node", "server.js"] ```
Comandos Esenciales de Docker
Gestión de contenedores
# Ejecutar contenedor con nombre y puerto
docker run -d --name mi-api -p 8080:3000 mi-imagen# Ejecutar con variables de entorno docker run -d --name mi-app \ -e DATABASE_URL=postgresql://user:pass@db:5432/mydb \ -e NODE_ENV=production \ mi-imagen
# Ver logs en tiempo real docker logs -f mi-api
# Entrar a un contenedor ejecutándose docker exec -it mi-api sh
# Ver recursos consumidos docker stats
# Ver detalles de un contenedor docker inspect mi-api ```
Gestión de imágenes
# Construir imagen desde Dockerfile
docker build -t mi-api:v1 .# Construir sin caché docker build --no-cache -t mi-api:v1 .
# Etiquetar una imagen docker tag mi-api:v1 mi-registry.com/mi-api:latest
# Subir imagen a un registro docker push mi-registry.com/mi-api:latest
# Eliminar imágenes no utilizadas docker image prune ```
Docker Compose
Docker Compose permite definir y ejecutar aplicaciones multi-contenedor con un solo archivo YAML.
# docker-compose.yml
version: '3.8'services: # Base de datos PostgreSQL db: image: postgres:15-alpine container_name: mi-postgres restart: unless-stopped environment: POSTGRES_DB: miapp POSTGRES_USER: admin POSTGRES_PASSWORD: secret123 volumes: - postgres_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U admin -d miapp"] interval: 10s timeout: 5s retries: 5
# API Node.js api: build: context: ./api dockerfile: Dockerfile container_name: mi-api restart: unless-stopped environment: DATABASE_URL: postgresql://admin:secret123@db:5432/miapp NODE_ENV: production PORT: 3000 ports: - "8080:3000" depends_on: db: condition: service_healthy volumes: - ./api:/app - /app/node_modules
# Redis para caché redis: image: redis:7-alpine container_name: mi-redis restart: unless-stopped ports: - "6379:6379" volumes: - redis_data:/data
# Nginx como reverse proxy nginx: image: nginx:alpine container_name: mi-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/certs:/etc/nginx/certs:ro depends_on: - api
volumes: postgres_data: redis_data: ```
# Comandos de Docker Compose
docker compose up -d # Iniciar servicios en background
docker compose down # Detener y eliminar servicios
docker compose logs -f api # Ver logs de un servicio
docker compose ps # Ver servicios ejecutándose
docker compose exec api sh # Entrar a un contenedor
docker compose build --no-cache # Reconstruir imágenes
docker compose pull # Actualizar imágenes base
Buenas Prácticas
Seguridad
- **No ejecutes como root**: Crea un usuario no-root en tu Dockerfile.
- **No guardes secretos en imágenes**: Usa variables de entorno o Docker Secrets.
- **Escanea vulnerabilidades**: Usa
docker scouto Trivy para escanear imágenes. - **Usa imágenes oficiales**: Siempre usa imágenes verificadas de Docker Hub.
# Escanear imagen con Docker Scout
docker scout cves mi-api:latest# Usar Trivy trivy image mi-api:latest ```
Optimización
- **Multi-stage builds**: Reduce el tamaño de la imagen final.
- **Ordena las capas**: Coloca
COPY package.jsonantes deCOPY .para aprovechar el caché. - **Usa .dockerignore**: Excluye archivos innecesarios.
# .dockerignore
node_modules
npm-debug.log
.git
.env
.env.local
*.md
docker-compose.yml
Dockerfile
.dockerignore
dist
coverage
.nyc_output
Monitoreo
# Ver uso de recursos
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"# Limpiar recursos no utilizados docker system prune -a --volumes
# Ver discos usage docker system df ```
Casos de Uso Comunes
Desarrollo local con Docker
# Ejecutar un entorno de desarrollo completo
docker compose -f docker-compose.dev.yml up -d# Con Hot Reload montando el código fuente docker compose -f docker-compose.dev.yml logs -f api ```
CI/CD con Docker
# .github/workflows/deploy.yml
name: Deployon: push: branches: [main]
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t mi-api:$GITHUB_SHA . - name: Test image run: docker run -d -p 3000:3000 mi-api:$GITHUB_SHA - name: Deploy run: | docker compose pull docker compose up -d ```
Conclusión
Docker ha revolucionado la forma en que desarrollamos, desplegamos y escalamos aplicaciones. Con esta guía tienes las bases para empezar a contenedorizar tus proyectos. La clave es practicar: empieza con un Dockerfile simple para una de tus aplicaciones, luego avanza a Docker Compose para orquestar múltiples servicios.
Recursos recomendados: - **Docker Documentation**: docs.docker.com - **Docker Hub**: hub.docker.com - **Play with Docker**: labs.play-with-docker.com (entorno online para practicar)