Docker para principiantes: concepto, instalación y primeros comandos en Windows, Mac y Linux

DUGLAS MORENODUGLAS MORENO 👁 22

Docker para principiantes: concepto, instalación y primeros comandos en Windows, Mac y Linux

Introducción

Si alguna vez te encontraste con el problema de "en mi máquina funciona, pero en el servidor no", Docker es la solución que estabas buscando. En este tutorial vas a aprender qué es Docker, para qué sirve y cómo instalarlo en los tres sistemas operativos más usados: Windows, macOS y Linux. Además, verás ejemplos de comandos ejecutados en terminal con su salida esperada, para que puedas seguir paso a paso y comenzar a trabajar con contenedores de inmediato.

Este artículo está dirigido a desarrolladores, administradores de sistemas y cualquier persona interesada en empaquetar aplicaciones de forma portátil y reproducible. No se requieren conocimientos previos de virtualización, solo familiaridad básica con la línea de comandos.

Al finalizar, sabrás:

  • Qué es un contenedor y cómo se diferencia de una máquina virtual.
  • Cuál es la arquitectura de Docker (daemon, cliente, imágenes, registros).
  • Cómo instalar Docker Desktop en Windows y macOS, y el motor Docker en las principales distribuciones Linux.
  • Cómo ejecutar tus primeros contenedores, crear imágenes con Dockerfile y usar Docker Compose para aplicaciones multi‑contenedor.
  • Buenas prácticas y errores comunes que debes evitar.

¿Qué es Docker?

Docker es una plataforma de código abierto que permite crear, desplegar y ejecutar aplicaciones dentro de contenedores ligeros. Un contenedor es un paquete estándar que incluye todo lo necesario para que un software se ejecute: código, runtime, bibliotecas, variables de entorno y archivos de configuración.

A diferencia de las máquinas virtuales, que emulan un hardware completo y requieren un sistema operativo invitado completo, los contenedores comparten el kernel del sistema operativo anfitrión y solo aíslan el espacio de usuario. Esto los hace mucho más rápidos de iniciar, más ligeros en consumo de recursos y más fáciles de mover entre entornos.

Ventajas principales

  • Portabilidad: la misma imagen funciona en cualquier máquina con Docker instalado.
  • Consistencia: elimina el problema de "funciona en mi máquina" porque el entorno es idéntico.
  • Escalabilidad: puedes lanzar cientos de réplicas de un contenedor en segundos.
  • Eficiencia: aprovecha mejor el hardware, ya que no hay overhead de un hipervisor completo.
  • Integración con CI/CD: las imágenes se pueden almacenar en registros y desplegar automáticamente en pipelines.

Arquitectura básica

  • Docker Daemon (dockerd): servicio que gestiona la creación, ejecución y monitoreo de contenedores.
  • Docker Client (docker): la interfaz de línea de comandos que tú usas para comunicarte con el daemon.
  • Imagen: plantilla de solo lectura que contiene el sistema de archivos y la configuración para lanzar un contenedor.
  • Contenedor: instancia ejecutable de una imagen. Puede estar en ejecución o detenido.
  • Registro (Registry): servidor donde se almacenan y distribuyen imágenes (por ejemplo, Docker Hub).

Cuando ejecutas docker run, el cliente le indica al daemon que descargue (si es necesario) la imagen desde el registro, cree un contenedor a partir de ella y lo ponga en marcha.


Instalación de Docker

En Windows

Docker Desktop for Windows incluye el daemon, la CLI y una interfaz gráfica. Requiere Windows 10 versión 1903 o superior con WSL 2 habilitado.

  1. Habilitar WSL 2
    Abre PowerShell como administrador y ejecuta:

    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    Luego reinicia el equipo.

  2. Instalar un kernel de Linux actualizado
    Descarga el paquete desde https://aka.ms/wsl2kernel y ejecútalo.

  3. Establecer WSL 2 como versión predeterminada

    wsl --set-default-version 2
  4. Descargar e instalar Docker Desktop
    Ve a https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe, ejecuta el instalador y sigue el asistente.

  5. Verificar la instalación
    Abre PowerShell o CMD y ejecuta:

    docker version

    Salida esperada (algo similar):

    Client: Docker Engine - Community
     Version:           24.0.7
     API version:       1.43
     Go version:        go1.22.5
     Git commit:        1d8f0b3
     Built:             Thu Apr 25 20:12:34 2024
     OS/Arch:           windows/amd64
     Context:           default
    
    Server: Docker Engine - Community
     Version:           24.0.7
     API version:       1.43
     Go version:        go1.22.5
     Git commit:        1d8f0b3
     Built:             Thu Apr 25 20:12:34 2024
     OS/Arch:           linux/amd64

En macOS

Docker Desktop for macOS también usa una máquina ligera Linux basada en HyperKit.

  1. Requisitos: macOS 10.15 (Catalina) o superior, al menos 4 GB de RAM.
  2. Descargar: https://desktop.docker.com/mac/main/amd64/Docker.dmg
  3. Instalar: arrastra el ícono de Docker a la carpeta de Aplicaciones.
  4. Iniciar: abre Docker desde Launchpad; el daemon se inicia en segundo plano.
  5. Verificar: abre Terminal y ejecuta:
    docker version
    Salida esperada (similar a la de Windows, pero con OS/Arch: darwin/amd64 o darwin/arm64 según tu CPU).

En Linux

En Linux puedes instalar el motor Docker (dockerd) directamente desde los repositorios de tu distribución o usar el script de conveniencia oficial.

Ubuntu/Debian

# 1. Actualizar el índice de paquetes
sudo apt-get update

# 2. Instalar paquetes necesarios para permitir el uso de repositorios HTTPS
sudo apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 3. Añadir la clave GPG oficial de Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. Configurar el repositorio
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. Actualizar nuevamente e instalar Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 6. Verificar que el daemon está activo
sudo systemctl status docker

Salida esperada del último comando (activo):

● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2024-06-01 10:15:00 CEST; 5min ago

Para usar Docker sin sudo, agrega tu usuario al grupo docker:

sudo usermod -aG docker $USER
newgrp docker  # o cierra y vuelve a abrir la sesión

Luego prueba:

docker run hello-world

Salida esperada:

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

Fedora

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl start docker
sudo systemctl enable docker

Arch Linux

sudo pacman -Syu
sudo pacman -S docker
sudo systemctl start docker
sudo systemctl enable docker

Primeros pasos con Docker

Una vez que Docker está instalado, lo primero es probar la imagen oficial hello-world.

docker run hello-world

Salida esperada (resumida):

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Ejecutar un contenedor interactivo

docker run -it ubuntu bash

La opción -it combina -i (interactiva) y -t (TTY). Verás el prompt cambiar a algo como root@<container-id>:/#. Dentro puedes ejecutar comandos de Linux normalmente.

Ejemplo dentro del contenedor:

apt-get update && apt-get install -y cowsay
cowsay "¡Hola desde Docker!"

Salida esperada:

 _________________
< ¡Hola desde Docker! >
 -----------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Para salir del contenedor sin detenerlo, usa Ctrl+P Ctrl+Q. Para terminar y eliminar el contenedor, escribe exit o ejecuta desde otra terminal:

docker stop <container-id>
docker rm <container-id>

Listar imágenes y contenedores

  • Ver imágenes locales:

docker images

Salida esperada (ejemplo):

REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 weeks ago 13.3kB
ubuntu latest 9c7d5f6a1b2c 3 days ago 77.8MB


- Ver contenedores en ejecución:
```run:bash
docker ps

Salida esperada (si ninguno está corriendo):

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
  • Ver todos los contenedores (incluidos los detenidos):

docker ps -a


---

## Crear tu propia imagen con Dockerfile

Un `Dockerfile` es un archivo de texto que contiene instrucciones para construir una imagen. Vamos a crear una imagen simple que sirva una aplicación Flask.

### Paso 1: Crear el directorio del proyecto
```run:bash
mkdir -p ~/docker-flask && cd ~/docker-flask

Paso 2: Escribir la aplicación (app.py)

cat > app.py << 'EOF'
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello from Dockerized Flask!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
EOF

Paso 3: Crear el Dockerfile

cat > Dockerfile << 'EOF'
# Usa la imagen oficial de Python como base
FROM python:3.12-slim

# Establece el directorio de trabajo dentro del contenedor
WORKDIR /app

# Copia solo el archivo de requerimientos primero para aprovechar caché
COPY requirements.txt .

# Instala dependencias
RUN pip install --no-cache-dir -r requirements.txt

# Copia el resto del código
COPY . .

# Expone el puerto que usará la aplicación
EXPOSE 5000

# Define el comando por defecto al iniciar el contenedor
CMD ["python", "app.py
]
EOF

Nota: las comillas simples dentro del here-doc evitan expansión de variables.

Paso 4: Crear el archivo de requerimientos

echo "flask" > requirements.txt

Paso 5: Construir la imagen

docker build -t mi-flask-app .

Salida esperada (fragmento):

Sending build context to Docker daemon  5.632kB
Step 1/7 : FROM python:3.12-slim
 ---> 8a69b636b6e5
Step 2/7 : WORKDIR /app
 ---> Using cache
 ---> 9d9b9b2f2b1c
Step 3/7 : COPY requirements.txt .
 ---> Using cache
 ---> e3b0c44298fc1c809afbfc41e140f5e4f21b2b3c5d6e7f8a9b0c1d2e3f4a5b6c
Step 4/7 : RUN pip install --no-cache-dir -r requirements.txt
 ---> Running in 9f8d7c6b5a4e
Collecting flask
  Downloading Flask-3.0.3-py3-none-any.whl (101 kB)
...
Successfully installed Flask-3.0.3 Werkzeug-3.0.2 ...
Removing intermediate container 9f8d7c6b5a4e
 ---> 2b1a0c9d8e7f6g5h4i3j2k1l0m9n8o7p
Step 5/7 : COPY . .
 ---> Using cache
 ---> a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Step 6/7 : EXPOSE 5000
 ---> Using cache
 ---> 7a8b9c0d1e2f3g4h5i6j7k8l9m0n1o2p
Step 7/7 : CMD ["python", "app.py
t]" ]
 ---> Using cache
 ---> 3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r
Successfully built 3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r
Successfully tagged mi-flask-app:latest

Paso 6: Ejecutar el contenedor

docker run -d -p 5000:5000 --name flask-app mi-flask-app
  • -d ejecuta en modo detached (en segundo plano).
  • -p 5000:5000 mapea el puerto 5000 del contenedor al mismo puerto del host.
  • --name flask-app asigna un nombre legible.

Salida esperada (ID del contenedor):

a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

Probar la aplicación

Abre tu navegador y visita http://localhost:5000 o usa curl:

curl http://localhost:5000

Salida esperada:

Hello from Dockerized Flask!"` (sin comillas).

### Detener y eliminar
```run:bash
docker stop flask-app
docker rm flask-app

Docker Compose: orquestar múltiples contenedores

Cuando tu aplicación necesita más de un servicio (por ejemplo, una web y una base de datos), Docker Compose simplifica la definición y ejecución.

Instalación del plugin

En la mayoría de las instalaciones recientes, el plugin docker compose ya viene incluido. Verifica con:

docker compose version

Salida esperada:

Docker Compose version v2.24.5

Ejemplo: Flask + Redis

Crearemos un proyecto que tenga una aplicación Flask que incremente un contador almacenado en Redis.

Estructura de archivos

myproject/
├── docker-compose.yml
├── app.py
└── requirements.txt

app.py

cat > app.py << 'EOF'
from flask import Flask
import redis
import os

app = Flask(__name__)

# Conexión a Redis usando el nombre del servicio definido en compose
r = redis.Redis(host=os.getenv('REDIS_HOST', 'redis'), port=6379, db=0)

@app.route('/')
def hello():
    count = r.incr('hits')
    return f'Hello! This page has been viewed {count} times.
'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
EOF

requirements.txt

echo -e "flask
redis" > requirements.txt

docker-compose.yml

cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  web:
    build: .
    ports:
      - "5000:5000"
    environment:
      - REDIS_HOST=redis
    depends_on:
      - redis

  redis:
    image: "redis:7-alpine"
    ports:
      - "6379:6379"
EOF

Construir y levantar

docker compose up --build

Salida esperada (fragmento):

[+] Building 0.3s (5/5) FINISHED
 => [internal] load build definition from Dockerfile
 => => transferring dockerfile: 32B
 => [internal] load .dockerignore
 => => transferring context: 2B
 => [internal] load metadata for docker.io/library/python:3.12-slim
 => [1/4] FROM docker.io/library/python:3.12-slim
 => [2/4] WORKDIR /app
 => [3/4] COPY requirements.txt .
 => [4/4] RUN pip install --no-cache-dir -r requirements.txt
 => exporting to image
 => => exporting layers
 => => writing image sha256:9f8d7c6b5a4e...
 => => naming to docker.io/library/myproject_web

[+] Running 2/2
 ✔ Container myproject-web-1  Started
 ✔ Container myproject-redis-1  Started

Ahora visita http://localhost:5000 y verás el contador incrementarse en cada recarga.

Para detener y eliminar todo:

docker compose down

Buenas prácticas y errores comunes

Buenas prácticas

  1. Usa imágenes oficiales y mantenidas siempre que sea posible (por ejemplo, python:3.12-slim en lugar de python:latest).
  2. Aprovecha la capa de caché: copia primero los archivos que cambian menos (como requirements.txt) antes del código fuente.
  3. Etiqueta tus imágenes con versiones semánticas (mi-app:1.0.0) además de latest.
  4. Mantén los contenedores efímeros: no guardes estado dentro del sistema de archivos del contenedor; usa volúmenes o bases de datos externas.
  5. Limita los privilegios: evita ejecutar procesos como root dentro del contenedor cuando no sea necesario (USER en Dockerfile).
  6. Usa .dockerignore para excluir archivos innecesarios (como .git, node_modules, archivos de log) del contexto de construcción.
  7. Monitoriza el tamaño: imágenes más pequeñas se descargan más rápido y reducen la superficie de ataque.

Errores comunes

  • Olvidar exponer puertos: si no usas -p o EXPOSE, la aplicación no será accesible desde el host.
  • Usar rutas absolutas dentro del contenedor sin crear el directorio: siempre asegúrate de que el WORKDIR exista o créalo con RUN mkdir -p /ruta.
  • Confundir docker run con docker start: run crea un nuevo contenedor cada vez; start solo reanuda uno detenido.
  • No limpiar imágenes y contenedores sin uso: ejecuta periódicamente docker system prune para liberar espacio.
  • Ejecutar bases de datos en modo de producción sin persistencia: recuerda montar un volumen (-v ./data:/var/lib/postgresql/data) para que los datos sobrevivan a reinicios.
  • Usar latest en producción: puede traer cambios inesperados; prefiera tags específicos.

Conclusión

Docker ha revolucionado la forma en que desarrollamos, probamos y desplegamos aplicaciones. En este tutorial aprendiste:

  • Qué es Docker y por qué los contenedores son más ligeros y portátiles que las máquinas virtuales.
  • Cómo instalar Docker en Windows, macOS y las distribuciones Linux más populares.
  • Cómo ejecutar tu primer contenedor, trabajar con imágenes y contenedores mediante la CLI.
  • Cómo crear una imagen personalizada usando un Dockerfile y publicar un servicio web simple.
  • Cómo orquestar múltiples contenedores con Docker Compose, ilustrado con una aplicación Flask que usa Redis.
  • Buenas prácticas para mantener tus imágenes seguras, pequeñas y eficientes, y los errores que más suelen aparecer al comenzar.

Con estas bases ya estás listo para empaquetar tus propios proyectos, crear entornos de desarrollo reproducibles y desplegar a escala en la nube o en tus propios servidores. El próximo paso podría ser explorar registros privados, integrar Docker en tus pipelines de CI/CD o aprender sobre orquestadores como Kubernetes para gestionar clústeres de contenedores a gran escala.

¡Así que manos a la obra y comienza a contenedorizar!


¿Te quedó alguna duda? Déjala en los comentarios y con gusto te ayudamos.

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario