Saltar al contenido principal

Docker para desarrolladores: qué es y cómo empezar

5 min readIgnacio Avilés

Docker es una herramienta que ha revolucionado la manera en que los desarrolladores construyen, distribuyen y ejecutan aplicaciones. En este post te explicaré qué es Docker y sus conceptos clave para que puedas empezar a usarlo en tu flujo de trabajo.

¿Qué es Docker?

Docker es una plataforma de código abierto que permite automatizar el despliegue, escalado y gestión de aplicaciones mediante contenedores. Permite empaquetar aplicaciones con todas sus dependencias en unidades estandarizadas llamadas contenedores.

La diferencia con una máquina virtual es que los contenedores comparten el kernel del sistema operativo anfitrión, por lo que son mucho más ligeros y arrancan en segundos. Si te interesa ver cómo el kernel expone esa información de procesos, en Explorando /proc lo cuento con detalle.

Conceptos clave

1. Contenedores

Los contenedores son paquetes ligeros, autónomos y ejecutables que incluyen todo lo necesario para ejecutar un software: el código, el runtime, las herramientas del sistema, las librerías y la configuración.

2. Imágenes

Las imágenes de Docker son los planos de los contenedores. Son plantillas de solo lectura que contienen un conjunto de instrucciones para crear un contenedor. Las imágenes se almacenan en registros como Docker Hub.

3. Dockerfile

Un Dockerfile es un archivo de texto que contiene todos los comandos necesarios para construir una imagen. Automatiza el proceso de creación de imágenes de Docker.

La relación entre las tres piezas es un flujo de una sola dirección:

flowchart LR
    A[Dockerfile] -->|docker build| B[Imagen]
    B -->|docker push| R[(Registro<br/>Docker Hub)]
    R -->|docker pull| B
    B -->|docker run| C1[Contenedor 1]
    B -->|docker run| C2[Contenedor 2]

De una misma imagen puedes levantar tantos contenedores como quieras, y cada uno arranca desde el mismo estado.

Ventajas de usar Docker

  • Consistencia entre entornos de desarrollo, pruebas y producción.
  • Mejor colaboración entre equipos de desarrollo y operaciones.
  • Despliegue y escalado más rápidos.
  • Uso eficiente de los recursos del sistema.

Comandos Docker esenciales

Una vez instalado Docker, estos son los comandos que más vas a usar:

# Descargar una imagen de Docker Hub
docker pull python:3.13-slim

# Listar imágenes descargadas
docker images

# Ejecutar un contenedor
docker run -p 5000:5000 mi-app

# Listar contenedores en ejecución
docker ps

# Listar todos los contenedores (incluyendo detenidos)
docker ps -a

# Detener un contenedor
docker stop <id-del-contenedor>

# Eliminar un contenedor
docker rm <id-del-contenedor>

# Ver los logs de un contenedor
docker logs <id-del-contenedor>

# Abrir una shell dentro de un contenedor en ejecución
docker exec -it <id-del-contenedor> sh

Ejemplo: dockerizando una aplicación web con Python

Veamos un ejemplo básico de cómo containerizar una aplicación Flask.

1. La aplicación

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return '¡Hola desde Docker!'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

Y un requirements.txt con las dependencias:

flask

2. El Dockerfile

FROM python:3.13-slim
WORKDIR /app

# Primero las dependencias: esta capa se cachea mientras no cambien
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Después el código, que cambia mucho más a menudo
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

El orden importa: Docker cachea cada instrucción como una capa. Si copias el código antes de instalar las dependencias, cada cambio en app.py vuelve a ejecutar el pip install completo.

3. Construir y ejecutar

docker build -t mi-flask-app .
docker run -p 5000:5000 mi-flask-app

Este ejemplo demuestra lo fácil que es containerizar una aplicación con Docker, garantizando que funcionará igual en cualquier entorno.

Errores comunes al empezar

  • "La app arranca, pero no puedo entrar desde el navegador". Casi siempre es una de dos: la app escucha en 127.0.0.1 dentro del contenedor (por eso el ejemplo usa host='0.0.0.0'), o te olvidaste del -p 5000:5000.
  • "Mis cambios no se ven". El contenedor usa la imagen que construiste, no tu carpeta. Tienes que volver a hacer docker build, o montar el código como volumen en desarrollo (-v $(pwd):/app).
  • "Perdí los datos de la base de datos". Todo lo que se escribe dentro de un contenedor desaparece cuando lo borras. Para datos que deben sobrevivir, usa volúmenes.
  • Imágenes enormes. Usa variantes -slim o -alpine de la imagen base y añade un .dockerignore (con .git, node_modules, .venv…) para no copiar basura a la imagen.
  • permission denied al usar docker en Linux. Tu usuario no está en el grupo docker. Añádelo con sudo usermod -aG docker $USER y vuelve a iniciar sesión.

Siguiente paso: Docker Compose

Cuando tu aplicación necesita varios servicios (por ejemplo, un servidor web + una base de datos), usar docker run para cada uno se vuelve tedioso. Docker Compose permite definir y levantar todos los servicios con un solo comando:

# compose.yaml
services:
  web:
    build: .
    ports:
      - "5000:5000"
    depends_on:
      - db
  db:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: secreto
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:
docker compose up

Con este archivo, levantas toda la infraestructura de tu app en un solo comando, y el volumen db-data hace que los datos de MySQL sobrevivan aunque borres el contenedor.

Conclusión

Docker simplifica enormemente el trabajo de los desarrolladores al eliminar el clásico "en mi máquina funciona". Si también trabajas con Node.js, puedes aplicar los mismos conceptos para dockerizar tu servidor Express o para aislar tu base de datos MySQL en un contenedor.

Y si vas más allá de las apps web, los contenedores también son la primera línea de defensa cuando ejecutas agentes de IA en tu máquina: en el caso del agente de OpenAI que hackeó a Hugging Face repaso cómo configurarlos para que un agente no pueda salir de su caja. Para proyectos Python, también te puede interesar uv, que acelera mucho la instalación de dependencias dentro de la imagen.

$ subscribe --newsletter

Recibe los nuevos posts en tu email

Un email cuando publico algo nuevo. Sin ruido, sin relleno.

Sin spam. Baja en cualquier momento. Política de privacidad.

comentarios