Todos los artículos

Docker para desarrolladores: del caos al contenedor en 30 minutos

Aprende a contenerizar cualquier aplicación con Docker desde cero. Explora imágenes, contenedores, volúmenes y Docker Compose con ejemplos prácticos.

Docker para desarrolladores: del caos al contenedor en 30 minutos

Si alguna vez escuchaste “en mi máquina sí funciona”, este artículo es para ti. Docker resuelve exactamente ese problema: empaqueta tu aplicación junto con todo lo que necesita para correr, garantizando que funcione igual en cualquier entorno.

¿Qué es Docker y por qué importa?

Docker es una plataforma de contenedorización. Un contenedor es como una caja sellada que incluye tu código, sus dependencias, las variables de entorno y la configuración del sistema operativo necesaria. No importa si el servidor destino usa Ubuntu, CentOS o Windows — el contenedor corre igual.

Antes de Docker, desplegar una aplicación implicaba:

  • Documentar manualmente las dependencias
  • Rezar para que las versiones coincidieran
  • Pasar horas depurando errores de entorno

Con Docker, el proceso se reduce a docker build y docker run.

Conceptos clave antes de empezar

Imagen vs Contenedor

Una imagen es la plantilla: define el sistema base, las dependencias y los comandos de inicio. Un contenedor es una instancia en ejecución de esa imagen. Puedes tener 10 contenedores corriendo a partir de la misma imagen.

Dockerfile

El Dockerfile es el recetario que Docker sigue para construir tu imagen:

# Imagen base
FROM node:20-alpine

# Directorio de trabajo dentro del contenedor
WORKDIR /app

# Copiar dependencias primero (mejor caché)
COPY package*.json ./
RUN npm ci --only=production

# Copiar el resto del código
COPY . .

# Puerto que expone el contenedor
EXPOSE 3000

# Comando de inicio
CMD ["node", "server.js"]

Construir y correr

# Construir la imagen con el tag "mi-app:latest"
docker build -t mi-app:latest .

# Correr un contenedor en segundo plano, mapeando el puerto 3000
docker run -d -p 3000:3000 --name mi-app mi-app:latest

# Ver contenedores activos
docker ps

# Ver logs en tiempo real
docker logs -f mi-app

Docker Compose: múltiples servicios, una sola configuración

La mayoría de las aplicaciones reales necesitan más de un servicio: un servidor web, una base de datos, un caché. Docker Compose orquesta todos en un solo archivo docker-compose.yml:

version: "3.9"

services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Levantar todo el stack:

docker compose up -d

Apagar y limpiar:

docker compose down

Volúmenes: persistencia de datos

Por defecto, cuando un contenedor muere, sus datos desaparecen. Los volúmenes resuelven eso montando una carpeta del host (o un volumen gestionado por Docker) dentro del contenedor:

# Montar la carpeta local ./data en /app/data del contenedor
docker run -v ./data:/app/data mi-app:latest

Buenas prácticas que marcan la diferencia

1. Usa imágenes Alpine siempre que puedas. node:20-alpine pesa ~50 MB vs ~900 MB de node:20. Menos peso = builds más rápidos y menos superficie de ataque.

2. Ordena las capas del Dockerfile estratégicamente. Docker cachea capa por capa. Pon las instrucciones que cambian menos (instalar dependencias) antes de las que cambian más (copiar tu código).

3. Usa .dockerignore. Igual que .gitignore, evita copiar node_modules, .git y archivos innecesarios a la imagen:

node_modules
.git
dist
*.log
.env

4. No corras contenedores como root. Agrega un usuario sin privilegios en tu Dockerfile:

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

5. Separa la imagen de build de la de producción con multi-stage builds:

# Etapa 1: build
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

# Etapa 2: producción (solo el resultado)
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --only=production
CMD ["node", "dist/server.js"]

Comandos que usarás todos los días

ComandoQué hace
docker psLista contenedores activos
docker ps -aLista todos los contenedores
docker imagesLista las imágenes locales
docker exec -it <nombre> shAbre una shell dentro del contenedor
docker logs -f <nombre>Logs en tiempo real
docker stop <nombre>Detiene un contenedor
docker rm <nombre>Elimina un contenedor detenido
docker rmi <imagen>Elimina una imagen
docker system pruneLimpia todo lo que no se usa

¿Y ahora qué?

Con esto ya puedes contenerizar cualquier aplicación web. El siguiente paso natural es aprender sobre registros de imágenes (Docker Hub, GitLab Registry) y orquestación con Kubernetes o Docker Swarm para ambientes de producción a escala.

Docker no es solo una herramienta de moda — es el estándar de la industria para entregar software de forma consistente y predecible.

¿Necesitas ayuda con esto?

En Zerep construimos productos digitales, capacitamos equipos y ayudamos a negocios a crecer en internet.

Ver servicios Contáctanos

Zerep

Agencia de ingeniería de software. Construimos productos digitales, capacitamos equipos y ayudamos a negocios a crecer en internet.

TRABAJA CON NOSOTROS

Cotiza ahora, empieza hoy

Escríbenos y te respondemos en menos de 24 horas. Sin compromisos, sin letras chiquitas.

Ayudamos a tu marca a crecer en redes sociales y buscadores, con el uso de las mejores herramientas del mercado.

Google
Slack
GitHub
GitLab
Atlassian
Spotify
PayPal
Airbnb
Dropbox
Shopify