---
title: "Top 60+ Comandos de Docker que Todo Desarrollador DEBE Conocer en 2025"
description: "Domina más de 60 comandos de Docker en esta guía actualizada de 2025. Cubre desde contenedores básicos y Compose v2 hasta buildx, limpieza de disco y health checks."
date: 2024-07-10
categories: ["self-hosting"]
tags: ["docker","docker-compose"]
---

import Notice from "@components/widgets/Notice.astro";
import ListCheck from "@components/widgets/ListCheck.astro";
import Tabs from "@components/widgets/Tabs.astro";
import Tab from "@components/widgets/Tab.astro";

Si distribuyes software en contenedores, usas comandos de Docker todos los días. Ya sea que ejecutes unos pocos servicios en un [servidor casero](/es/contenedores-docker-servidor-casa/) o administres [contenedores Docker autoalojados para empresas](/es/contenedores-docker-empresas/), conocer la CLI ahorra tiempo y evita caídas.

Esta guía cubre más de 60 comandos de Docker: operaciones básicas con imágenes y contenedores, Compose v2, builds multiplataforma con buildx, limpieza de disco, health checks y autenticación en registries. Todo está actualizado para Docker Engine 28.x/29.x (2025). Si todavía ves `docker-compose` con guion en tutoriales viejos, eso ya murió del todo.

## Chuleta de referencia rápida

| Categoría | Comando | Descripción |
|----------|---------|-------------|
| **Info** | `docker version` | Muestra la versión del cliente y del servidor |
| **Info** | `docker info` | Información de Docker a nivel de sistema |
| **Imágenes** | `docker pull <image>:<tag>` | Descarga una imagen del registry |
| **Imágenes** | `docker images` | Lista las imágenes locales |
| **Imágenes** | `docker rmi <image>` | Elimina una imagen |
| **Imágenes** | `docker image prune` | Elimina las imágenes huérfanas |
| **Imágenes** | `docker build -t <name> .` | Construye una imagen desde un Dockerfile |
| **Imágenes** | `docker tag <src> <dst>` | Etiqueta una imagen |
| **Imágenes** | `docker push <image>` | Sube una imagen al registry |
| **Imágenes** | `docker history <image>` | Muestra el historial de capas de una imagen |
| **Contenedores** | `docker run -d --name <n> <img>` | Ejecuta un contenedor en segundo plano |
| **Contenedores** | `docker run -it <img> /bin/bash` | Ejecuta un contenedor interactivo |
| **Contenedores** | `docker ps` | Lista los contenedores en ejecución |
| **Contenedores** | `docker ps -a` | Lista todos los contenedores |
| **Contenedores** | `docker stop <container>` | Detiene un contenedor en ejecución |
| **Contenedores** | `docker start <container>` | Inicia un contenedor detenido |
| **Contenedores** | `docker restart <container>` | Reinicia un contenedor |
| **Contenedores** | `docker rm <container>` | Elimina un contenedor detenido |
| **Contenedores** | `docker exec -it <c> /bin/bash` | Ejecuta un comando en un contenedor |
| **Contenedores** | `docker logs -f <container>` | Sigue los logs de un contenedor |
| **Contenedores** | `docker inspect <container>` | Información de bajo nivel del contenedor |
| **Contenedores** | `docker stats` | Uso de recursos en vivo |
| **Contenedores** | `docker top <container>` | Procesos en ejecución del contenedor |
| **Contenedores** | `docker cp <c>:/path /host` | Copia archivos desde el contenedor |
| **Contenedores** | `docker update --restart=always <c>` | Actualiza la política de reinicio en caliente |
| **Redes** | `docker network ls` | Lista las redes |
| **Redes** | `docker network create <name>` | Crea una red |
| **Redes** | `docker network connect <net> <c>` | Conecta un contenedor a una red |
| **Volúmenes** | `docker volume ls` | Lista los volúmenes |
| **Volúmenes** | `docker volume create <name>` | Crea un volumen |
| **Volúmenes** | `docker run -v <vol>:/path <img>` | Monta un volumen |
| **Compose** | `docker compose up -d` | Inicia servicios (en segundo plano) |
| **Compose** | `docker compose down` | Detiene y elimina servicios |
| **Compose** | `docker compose ps` | Lista los servicios de compose |
| **Compose** | `docker compose logs -f` | Sigue los logs de compose |
| **Compose** | `docker compose --profile <p> up` | Inicia un perfil específico |
| **Buildx** | `docker buildx ls` | Lista las instancias de builder |
| **Buildx** | `docker buildx build --platform linux/amd64,linux/arm64` | Build multiplataforma |
| **Limpieza** | `docker system df` | Muestra el uso de disco |
| **Limpieza** | `docker system prune -a` | Elimina todos los recursos sin usar |
| **Limpieza** | `docker system prune -a --volumes` | Limpieza nuclear (incluye volúmenes) |
| **Registry** | `docker login` | Autenticación en el registry |
| **Registry** | `docker logout` | Cierra sesión en el registry |
| **Avanzados** | `docker save -o file.tar <img>` | Guarda una imagen en un tar |
| **Avanzados** | `docker load -i file.tar` | Carga una imagen desde un tar |
| **Avanzados** | `docker export <c> > file.tar` | Exporta el filesystem de un contenedor |
| **Avanzados** | `docker import file.tar` | Importa un filesystem de contenedor |
| **Avanzados** | `docker context create` | Gestiona daemons de Docker remotos |

## Requisitos previos

Antes de ejecutar estos comandos:

<ListCheck>
- Docker Engine 24+ instalado (se recomienda 28.x o 29.x)
- Tu usuario está en el grupo `docker`, o estás usando `sudo`
- Verifica que el daemon está en ejecución: `docker version` debería mostrar las secciones Client y Server
</ListCheck>

```sh
$ docker version
Client:
 Version:           28.1.1
 API version:       1.49
 Go version:        go1.23.8
 OS/Arch:           linux/amd64

Server:
 Engine:
  Version:          28.1.1
  API version:      1.49 (minimum version 1.24)
  Go version:       go1.23.8
  OS/Arch:          linux/amd64
```

<Notice type="warning" title="Errores comunes al arrancar">
"Cannot connect to the Docker daemon" significa que el servicio no está en ejecución. Se corrige con `sudo systemctl start docker && sudo systemctl enable docker`. "permission denied" significa que tu usuario no está en el grupo docker. Se corrige con `sudo usermod -aG docker $USER` y luego cerrando sesión y volviendo a entrar.
</Notice>

La salida mostrada es de Docker 28.x. Tus números de versión serán distintos: no pasa nada. Los comandos son estables entre versiones.

## Sección 1: Comandos básicos de Docker

### 1.1 Versión e información de Docker

Entender qué versión de Docker estás ejecutando y la configuración a nivel de sistema es el primer paso.

- **`docker --version`**: comprobación rápida de que Docker está instalado y de qué versión.

  ```sh
  $ docker --version
  Docker version 28.1.1, build 4eba7b2
  ```

- **`docker version`**: información detallada de versión del cliente y del servidor (mostrada en Requisitos previos arriba).

- **`docker info`**: visión general a nivel de sistema: número de contenedores/imágenes, storage driver, logging driver, versión del kernel, memoria total.

  ```sh
  $ docker info
  Containers: 5
   Running: 3
   Paused: 0
   Stopped: 2
  Images: 12
  Storage Driver: overlay2
  Logging Driver: json-file
  Cgroup Driver: systemd
  Cgroup Version: 2
  Kernel Version: 6.8.0-49-generic
  Operating System: Ubuntu 24.04.1 LTS
  CPUs: 4
  Total Memory: 7.771GiB
  ```

  Si falta la sección `Server:`, el daemon de Docker no está en ejecución.

### 1.2 Ayuda de Docker

Docker tiene ayuda integrada para cada comando:

- **`docker --help`**: lista todos los comandos disponibles y los comandos de gestión.

- **`docker <command> --help`**: opciones detalladas de un comando concreto. Es el más útil de todos. Por ejemplo:

  ```sh
  $ docker run --help

  Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

  Run a command in a new container

  Options:
    -d, --detach                         Run container in background
    --name string                        Assign a name to the container
    -p, --publish list                   Publish a container's port(s) to the host
    -v, --volume list                    Bind mount a volume
    --rm                                 Remove container when it exits
    -i, --interactive                    Keep STDIN open
    -t, --tty                            Allocate a pseudo-TTY
    --restart string                     Restart policy (no, always, unless-stopped, on-failure)
    --env list                           Set environment variables
    --network string                     Connect to a network
    --health-cmd string                  Health check command
    --init                               Run an init process inside the container
    --gpus gpu-request                   GPU devices to add to the container
  ```

  Ante la duda, `docker <cmd> --help` es más rápido que buscar en la web.

## Sección 2: Trabajar con imágenes de Docker

### 2.1 Descargar imágenes

Descargar imágenes desde un registry suele ser el primer paso.

- **`docker pull <image>`**: descarga el tag `latest` por defecto.

  ```sh
  $ docker pull ubuntu
  Using default tag: latest
  latest: Pulling from library/ubuntu
  6d28e14ab8c8: Pull complete
  Digest: sha256:abc123...
  Status: Downloaded newer image for ubuntu:latest
  docker.io/library/ubuntu:latest
  ```

- **`docker pull <image>:<tag>`**: descarga una versión específica.

  ```sh
  $ docker pull nginx:alpine
  alpine: Pulling from library/nginx
  Digest: sha256:def456...
  Status: Downloaded newer image for nginx:alpine
  docker.io/library/nginx:alpine
  ```

<Notice type="warning" title="Límites de peticiones de Docker Hub">
Los pulls sin autenticar están limitados a 100 cada 6 horas por dirección IPv4 (o subred IPv6 /64). Las cuentas autenticadas gratuitas tienen 200 cada 6 horas. Si te topas con límites en CI/CD, ejecuta `docker login` primero. Las suscripciones de pago tienen pulls ilimitados.
</Notice>

### 2.2 Listar imágenes

- **`docker images`**: lista todas las imágenes locales.

  ```sh
  $ docker images
  REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
  nginx        alpine    a1b2c3d4e5f6   2 weeks ago    43MB
  ubuntu       latest    f6e5d4c3b2a1   3 weeks ago    77.9MB
  ```

- **`docker images -a`**: incluye las capas intermedias de build.

- **`docker images --filter "dangling=true"`**: muestra imágenes sin tag que no referencia ningún contenedor. Se pueden eliminar con seguridad.

### 2.3 Eliminar imágenes

- **`docker rmi <image>`**: elimina una imagen por nombre o ID.

  ```sh
  $ docker rmi nginx:alpine
  Untagged: nginx:alpine
  Deleted: sha256:a1b2c3d4e5f6...
  ```

  Si un contenedor sigue usando la imagen, verás "image is being used by running container": detén y elimina el contenedor primero.

- **`docker image prune`**: elimina todas las imágenes huérfanas (sin tag). Añade `-a` para eliminar todas las imágenes sin usar.

Para profundizar en cómo recuperar espacio en disco de la capa de almacenamiento de Docker, consulta [cómo recuperar espacio en disco de Docker overlay2](/es/limpiar-docker-overlay2/).

### 2.4 Construir imágenes

- **`docker build -t <name>:<tag> .`**: construye una imagen desde un Dockerfile en el directorio actual.

  ```sh
  $ docker build -t myapp:1.0 .
  [+] Building 12.5s (8/8) FINISHED
  ```

<Notice type="info" title="BuildKit ahora es el builder por defecto">
Desde Docker Engine 23.0 (febrero de 2023), BuildKit es el builder por defecto. Ya no necesitas `DOCKER_BUILDKIT=1`. BuildKit te da builds más rápidos, mejor caché y soporte para builds multi-etapa de serie.
</Notice>

- **`docker build --no-cache -t myapp:1.0 .`**: rebuild desde cero, ignorando la caché de capas. Útil cuando cambian las versiones de las dependencias.

- **`docker build -f Dockerfile.prod -t myapp:prod .`**: usa un Dockerfile concreto.

Para builds multiplataforma avanzados y secrets de build, consulta la [Sección 8: Build moderno con Docker Buildx](#sección-8-build-moderno-con-docker-buildx). Para aprender sobre los build args y las [variables de entorno en Docker (ARG vs ENV)](/es/variables-entorno-docker/), revisa la guía dedicada. También puedes aprender a [copiar varios archivos en una sola capa de Dockerfile](/es/copiar-varios-archivos-una-capa-dockerfile/) para reducir el tamaño de la imagen.

## Sección 3: Gestionar contenedores de Docker

### 3.1 Ejecutar contenedores

El comando `docker run` es el comando de Docker más importante. Estas son las variantes esenciales:

- **`docker run <image>`**: crea e inicia un contenedor. Ejecuta el comando por defecto de la imagen.

- **`docker run -d <image>`**: modo detached (segundo plano). Devuelve el ID del contenedor.

- **`docker run -it <image> /bin/bash`**: modo interactivo con TTY. Te deja en una shell dentro del contenedor.

- **`docker run --name myapp -d -p 8080:80 nginx`**: contenedor con nombre y mapeo de puertos (host 8080 → contenedor 80).

- **`docker run --rm -it ubuntu /bin/bash`**: elimina automáticamente el contenedor al salir. Bueno para depuración desechable.

- **`docker run -e MY_VAR=value -d <image>`**: pasa variables de entorno. Consulta [variables de entorno en Docker (ARG vs ENV)](/es/variables-entorno-docker/) para el desglose completo.

<Notice type="success" title="Comando run listo para producción">
Aquí tienes un `docker run` que cubre lo básico para un servicio en producción:

```sh
docker run -d \
  --name myapp \
  --restart unless-stopped \
  --health-cmd="curl -f http://localhost:3000/health || exit 1" \
  --health-interval=30s \
  --health-retries=3 \
  -p 3000:3000 \
  myapp:latest
```

Esto te da: reinicio automático ante fallos, monitorización de salud y mapeo de puertos. Para más sobre ejecutar apps en Docker, mira [desplegar FileBrowser con Docker](/es/desplegar-filebrowser-docker/) como ejemplo práctico.
</Notice>

Flags adicionales que vale la pena conocer:

| Flag | Qué hace |
|------|-------------|
| `--restart unless-stopped` | Reinicio automático tras un fallo o un reinicio (solo se detiene si lo paras explícitamente) |
| `--health-cmd`, `--health-interval`, `--health-retries` | Define los health checks del contenedor |
| `--init` | Ejecuta tini como PID 1: maneja procesos zombie limpiamente |
| `--shm-size 256m` | Aumenta la memoria compartida (necesario para navegadores, PostgreSQL, algunas cargas de ML) |
| `--add-host host.docker.internal:host-gateway` | Permite al contenedor alcanzar la máquina host |
| `--gpus all` | Da acceso a la GPU al contenedor (requiere nvidia-container-toolkit) |
| `--user 1000:1000` | Ejecuta como un UID/GID concreto en lugar de root |

Para gestionar usuarios dentro de contenedores, consulta [cómo añadir usuarios a un contenedor Docker](/es/anadir-usuarios-contenedor-docker/). Para [ejecutar apps de Python en Docker](/es/docker-ejecutar-python/), tenemos una guía dedicada.

### 3.2 Listar contenedores

- **`docker ps`**: lista los contenedores en ejecución.

  ```sh
  $ docker ps
  CONTAINER ID   IMAGE          COMMAND                  STATUS         NAMES
  a1b2c3d4e5f6   nginx:alpine   "/docker-entrypoint.…"   Up 2 hours     web-server
  f6e5d4c3b2a1   postgres:16    "docker-entrypoint.s…"   Up 5 hours     db
  ```

- **`docker ps -a`**: lista todos los contenedores (incluidos los detenidos).

- **`docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"`**: formato de salida personalizado. Más limpio que el por defecto.

- **`docker ps --filter "status=exited"`**: filtra por estado. Útil para encontrar contenedores que limpiar.

### 3.3 Detener e iniciar contenedores

- **`docker stop <container>`**: parada graceful (SIGTERM, luego SIGKILL tras el timeout). El timeout por defecto es de 10 segundos.

- **`docker stop --timeout 30 <container>`**: espera 30 segundos antes de forzar el kill. Da a las apps más tiempo para cerrarse limpiamente.

<Notice type="warning" title="--time está obsoleto">
El flag `--time` de `docker stop` y `docker restart` quedó obsoleto en Docker 28.4. Usa `--timeout` en su lugar. El flag viejo aún funciona por ahora pero se eliminará en v30.
</Notice>

- **`docker start <container>`**: inicia un contenedor detenido (conserva su configuración).

- **`docker restart <container>`**: detiene y luego inicia. Equivalente a `docker stop` + `docker start`.

- **`docker kill <container>`**: parada forzada inmediata (SIGKILL). Sin apagado graceful. Úsalo cuando un contenedor se queda atascado.

### 3.4 Eliminar contenedores

- **`docker rm <container>`**: elimina un contenedor detenido.

- **`docker rm -f <container>`**: fuerza la eliminación de un contenedor en ejecución (envía SIGKILL primero).

- **`docker container prune`**: elimina todos los contenedores detenidos de golpe. La versión interactiva pide confirmación.

  ```sh
  $ docker container prune --force
  Deleted Containers:
  a1b2c3d4e5f6...
  f6e5d4c3b2a1...

  Total reclaimed space: 152.3MB
  ```

## Sección 4: Inspección y logs

### 4.1 Inspeccionar contenedores e imágenes

`docker inspect` devuelve JSON detallado sobre cualquier objeto de Docker. La salida en bruto es enorme: usa templates de Go para extraer lo que necesitas.

- **`docker inspect <container>`**: salida JSON completa (normalmente cientos de líneas). Pásala por `jq` para legibilidad.

- **`docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>`**: obtiene la dirección IP del contenedor.

- **`docker inspect --format='{{.State.Status}}' <container>`**: obtiene el estado del contenedor (running, exited, etc.).

- **`docker inspect --format='{{json .State.Health}}' <container> | jq`**: obtiene el estado del health check.

- **`docker inspect --format='{{.HostConfig.RestartPolicy.Name}}' <container>`**: comprueba la política de reinicio.

### 4.2 Ver logs

- **`docker logs <container>`**: vuelca todos los logs.

- **`docker logs -f <container>`**: sigue (tail) los logs en tiempo real. Pulsa Ctrl+C para parar.

- **`docker logs --tail 100 <container>`**: muestra solo las últimas 100 líneas.

- **`docker logs --since 1h <container>`**: logs de la última hora.

- **`docker logs --since 2025-01-15T10:00:00 --until 2025-01-15T11:00:00 <container>`**: logs de una ventana de tiempo concreta.

- **`docker logs --timestamps <container>`**: prefija cada línea con una marca de tiempo.

Combina flags: `docker logs -f --tail 50 --timestamps myapp` es un patrón habitual para depurar en vivo.

## Sección 5: Redes

### 5.1 Gestionar redes

Las redes de Docker permiten a los contenedores hablar entre sí por nombre (resolución DNS en redes bridge definidas por el usuario).

- **`docker network ls`**: lista todas las redes.

  ```sh
  $ docker network ls
  NETWORK ID     NAME      DRIVER    SCOPE
  abc123def456   bridge    bridge    local
  789ghi012jkl   host      host      local
  345mno678pqr   none      null      local
  ```

- **`docker network create mynet`**: crea una red bridge definida por el usuario.

- **`docker network create --driver bridge --subnet 172.20.0.0/16 mynet`**: con subred personalizada.

- **`docker network rm mynet`**: elimina una red.

- **`docker network inspect mynet`**: información detallada de una red (contenedores conectados, direcciones IP).

<Notice type="warning" title="Docker se salta tu firewall">
Docker manipula iptables directamente para enrutar el tráfico de los contenedores. Esto significa que los puertos publicados (`-p 8080:80`) pueden saltarse UFW y otros firewalls del host. Si expones contenedores a internet, entiende las implicaciones. Consulta [Docker se salta tu firewall](/es/docker-evita-firewall/) para la explicación completa y las soluciones.
</Notice>

### 5.2 Conectar y desconectar contenedores

- **`docker network connect mynet mycontainer`**: conecta un contenedor en ejecución a una red adicional. El contenedor ahora tiene interfaces en ambas redes.

- **`docker network disconnect mynet mycontainer`**: desconecta de una red.

- **`docker run --network mynet --name app -d myimage`**: inicia un contenedor directamente en una red concreta.

## Sección 6: Volúmenes y gestión de datos

### 6.1 Gestionar volúmenes

Los volúmenes son la forma preferida de persistir datos. Sobreviven a la eliminación de contenedores y los gestiona Docker.

- **`docker volume ls`**: lista todos los volúmenes.

- **`docker volume create mydata`**: crea un volumen con nombre.

- **`docker volume inspect mydata`**: muestra detalles del volumen (punto de montaje en el host, driver, etiquetas).

- **`docker volume rm mydata`**: elimina un volumen. Solo funciona si ningún contenedor lo está usando.

### 6.2 Usar volúmenes

Hay dos sintaxis para montar volúmenes:

- **`-v` (forma abreviada de bind mount)**:

  ```sh
  docker run -v mydata:/var/lib/postgresql/data -d postgres:16
  docker run -v /host/path:/container/path -d myimage
  ```

- **`--mount` (explícita, recomendada)**:

  ```sh
  docker run --mount type=volume,source=mydata,target=/var/lib/postgresql/data -d postgres:16
  docker run --mount type=bind,source=/host/path,target=/container/path -d myimage
  ```

Usa `--mount` en producción: es más explícita, soporta más opciones y da mensajes de error más claros. La forma abreviada `-v` está bien para desarrollo local rápido.

## Sección 7: Docker Compose (v2)

<Notice type="error" title="Docker Compose v1 ha muerto">
`docker-compose` (con guion) era el binario Python de v1. Quedó obsoleto en julio de 2023 y se eliminó de todas las versiones de Docker Desktop. Usa `docker compose` (con espacio): el plugin Go de v2. Si ves tutoriales viejos usando `docker-compose`, tradúcelo mentalmente a `docker compose`. La clave `version:` en compose.yaml también está obsoleta: Compose v2 la ignora.
</Notice>

### 7.1 Comandos básicos de Compose v2

<Tabs>
<Tab name="v1 antigua (obsoleta)">
```sh
docker-compose up -d
docker-compose down
docker-compose ps
docker-compose logs -f
```
</Tab>
<Tab name="v2 nueva (usa esta)">
```sh
docker compose up -d
docker compose down
docker compose ps
docker compose logs -f
```
</Tab>
</Tabs>

- **`docker compose up -d`**: inicia todos los servicios en modo detached. Crea contenedores, redes y volúmenes según lo definido en `compose.yaml`.

- **`docker compose down`**: detiene y elimina contenedores y redes. Añade `--volumes` para eliminar también los volúmenes con nombre (¡pérdida de datos!).

- **`docker compose ps`**: lista los servicios y su estado.

- **`docker compose logs -f`**: sigue los logs de todos los servicios. Añade un nombre de servicio para filtrar: `docker compose logs -f web`.

- **`docker compose config`**: valida e imprime el archivo compose resuelto. Útil para cazar errores de YAML antes de desplegar.

Para gestionar apps de Docker Compose en producción, herramientas como [Dockge](/es/instalar-dockge/) o [Dokploy](/es/dokploy-app-docker-compose/) te dan una UI web. Para [gestionar secrets en Docker Compose](/es/secretos-docker-compose/), consulta la guía dedicada.

### 7.2 Gestionar servicios

- **`docker compose build`**: construye o reconstruye los servicios que tienen una sección `build:`.

- **`docker compose pull`**: descarga las últimas imágenes de todos los servicios.

- **`docker compose restart`**: reinicia todos los servicios (o uno concreto: `docker compose restart web`).

- **`docker compose start` / `docker compose stop`**: inicia/detiene sin eliminar contenedores. A diferencia de `up`/`down`, los contenedores persisten.

- **`docker compose top`**: muestra los procesos en ejecución dentro de cada contenedor de servicio.

- **`docker compose exec web /bin/bash`**: ejecuta un comando dentro de un contenedor de servicio en ejecución.

- **`docker compose run --rm web python manage.py migrate`**: ejecuta un comando puntual en un servicio. `--rm` elimina el contenedor al terminar.

### 7.3 Novedades de Compose v2

<Notice type="info" title="Compose watch para desarrollo">
`docker compose up --watch` monitoriza tus archivos fuente y sincroniza o reconstruye automáticamente cuando cambian. Esto sustituye montajes complejos de bind-mount + nodemon/fswatch. Define qué vigilar en la sección `develop.watch` de tu compose.yaml. Disponible desde Compose 2.22.0 (GA).
</Notice>

- **`docker compose up --watch`**: inicia servicios con modo watch. Los cambios en el código fuente disparan sincronización automática (para archivos estáticos) o rebuild (para código que afecta a la imagen).

- **`docker compose --profile dev up`**: solo inicia los servicios etiquetados con el perfil `dev`. Útil para servicios opcionales como herramientas de depuración o bases de datos de pruebas.

  ```yaml
  services:
    web:
      build: .
    debug-tools:
      image: busybox
      profiles: ["dev"]
  ```

- **`docker compose --env-file .env.staging up`**: usa un archivo de entorno personalizado en lugar del `.env` por defecto.

## Sección 8: Build moderno con Docker Buildx

`docker buildx` es el sistema de build moderno de Docker. Desde Docker 23.0, `docker build` es esencialmente un alias de `docker buildx build`. Pero para builds multiplataforma, caché remota y secrets de build, necesitas la interfaz completa de `buildx`.

### 8.1 Lo básico de Buildx

- **`docker buildx ls`**: lista las instancias de builder disponibles.

  ```sh
  $ docker buildx ls
  NAME/NODE     DRIVER/ENDPOINT     STATUS    BUILDKIT   PLATFORMS
  default       docker                                    linux/amd64, linux/arm64
  ```

- **`docker buildx create --use --name mybuilder`**: crea un builder nuevo y cambia a él. Necesario para builds multiplataforma.

- **`docker buildx build -t myapp:latest .`**: construye usando el builder activo. Igual que `docker build` pero con las funciones de buildx disponibles.

### 8.2 Builds multiplataforma

Construye imágenes para varias arquitecturas en un solo comando:

```sh
docker buildx build --platform linux/amd64,linux/arm64 \
  -t myuser/myapp:latest \
  --push .
```

Esto usa emulación QEMU para compilar de forma cruzada. Funciona, pero los builds emulados son lentos: un build ARM64 en un host x86 puede ser 5-10 veces más lento que nativo.

<Notice type="info" title="Los builders ARM nativos son más rápidos">
Si construyes imágenes ARM64 con regularidad, plantéate usar un builder ARM nativo. Las instancias ARM64 de [Hetzner Cloud](https://go.bitdoze.com/hetzner) (desde unos 4 EUR/mes) funcionan bien como builders buildx remotos y son mucho más rápidas que la emulación QEMU en x86.
</Notice>

_Los precios de los VPS subieron en general en 2026 — si estás replanteándote un servidor alquilado, mira [qué cambió y cuándo gana un mini PC](/es/subidas-precios-vps/)._

Sin `--push`, la imagen se queda en local (las imágenes multiplataforma necesitan un registry; no se pueden cargar localmente). También puedes usar `--load` para builds de una sola plataforma.

### 8.3 Secrets de build y caché remota

- **`docker buildx build --secret id=mytoken,src=./token.txt -t myapp .`**: pasa secrets durante el build sin incrustarlos en las capas. En tu Dockerfile: `RUN --mount=type=secret,id=mytoken cat /run/secrets/mytoken`.

- **`docker buildx build --cache-to type=registry,ref=myuser/myapp:cache --cache-from type=registry,ref=myuser/myapp:cache -t myapp .`**: exporta e importa la caché de build vía un registry. Esencial en CI/CD para no reconstruir desde cero cada vez.

- **`docker buildx bake`**: construye múltiples targets desde un `docker-bake.hcl`, JSON o archivo compose. Útil para proyectos con muchas imágenes relacionadas.

- **`docker buildx prune`**: limpia la caché de build. Añade `--all` para borrarlo todo.

## Sección 9: Espacio en disco y limpieza de Docker

Esta es la sección que más necesitan los operadores de VPS. Docker acumula imágenes, contenedores, volúmenes y caché de build rápidamente: sobre todo en VPS baratos con disco limitado.

### 9.1 Comprobar el uso de disco

- **`docker system df`**: muestra el desglose del uso de disco.

  ```sh
  $ docker system df
  TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
  Images          12        5         3.45GB    2.1GB (60%)
  Containers      8         3         152MB     98MB (64%)
  Local Volumes   6         2         1.2GB     800MB (66%)
  Build Cache     15        0         512MB     512MB (100%)
  ```

- **`docker system df -v`**: desglose detallado por imagen, contenedor, volumen y entrada de caché.

Ejecuta esto semanalmente. En un [VPS de Hetzner de 5 EUR/mes](https://go.bitdoze.com/hetzner) con 40 GB de disco, Docker puede comerse fácilmente 10-15 GB si no lo vigilas.

### 9.2 Purgar recursos sin usar

<Notice type="warning" title="El prune de volúmenes borra datos permanentemente">
`docker volume prune` y `docker system prune -a --volumes` borran permanentemente los datos de los volúmenes: bases de datos, archivos subidos, todo lo almacenado en volúmenes. Verifica siempre qué se va a eliminar antes de confirmar. Haz backup de los volúmenes primero si los datos importan.
</Notice>

```sh
# Elimina todos los contenedores detenidos
docker container prune --force

# Elimina imágenes huérfanas (sin tag, sin referencias)
docker image prune --force

# Elimina TODAS las imágenes sin usar (no solo las huérfanas)
docker image prune -a --force

# Elimina volúmenes sin usar (PÉRDIDA DE DATOS: ten cuidado)
docker volume prune --force

# Elimina redes sin usar
docker network prune --force

# Elimina la caché de build
docker builder prune --force

# Elimina TODOS los recursos sin usar (imágenes, contenedores, redes, caché: NO volúmenes)
docker system prune -a --force

# La opción nuclear: todo lo sin usar, incluidos los volúmenes
docker system prune -a --volumes --force
```

### 9.3 Estrategias de limpieza seguras para VPS

El enfoque más seguro: purgado por antigüedad. Conserva lo reciente, limpia el resto.

```sh
# Elimina recursos sin usar de más de 7 días
docker system prune -a --filter "until=168h" --force
```

Para un cron job semanal:

```sh
# /etc/cron.d/docker-cleanup
0 3 * * 0 root docker system prune -a --filter "until=168h" --force > /var/log/docker-prune.log 2>&1
```

En hosting VPS económico como [Hetzner](https://go.bitdoze.com/hetzner) o [Hostinger VPS](https://go.bitdoze.com/hostinger-vps), el disco es la limitación, no la CPU ni la RAM. Un cron job de limpieza es un seguro barato. Para más enfoques, consulta [cómo limpiar todos los recursos de Docker](/es/limpiar-docker-completo/) y [recuperar espacio en disco de Docker overlay2](/es/limpiar-docker-overlay2/). Si ejecutas Docker en un panel gestionado, revisa los [mejores paneles de servidor autoalojados](/es/mejores-paneles-autoalojados/) para herramientas de limpieza integradas.

## Sección 10: Health checks de Docker y preparación para producción

Los health checks permiten a Docker (y a los orquestadores) saber si tu aplicación funciona de verdad: no solo que "el proceso está en ejecución".

### 10.1 Añadir health checks a los contenedores

En un Dockerfile:

```dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1
```

O vía `docker run`:

```sh
docker run -d \
  --health-cmd="curl -f http://localhost:3000/health || exit 1" \
  --health-interval=30s \
  --health-timeout=3s \
  --health-start-period=10s \
  --health-retries=3 \
  --name myapp \
  -p 3000:3000 \
  myapp:latest
```

Parámetros clave:
- `--interval`: cada cuánto se ejecuta el check (por defecto: 30s)
- `--timeout`: cuánto esperar por una respuesta (por defecto: 30s)
- `--start-period`: periodo de gracia antes de que los health checks cuenten como fallos (por defecto: 0s)
- `--retries`: fallos consecutivos antes de marcar como unhealthy (por defecto: 3)

En Compose:

```yaml
services:
  web:
    image: myapp:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 3s
      start_period: 10s
      retries: 3
```

### 10.2 Monitorizar la salud de los contenedores

```sh
# Comprueba el estado de salud vía inspect
docker inspect --format='{{json .State.Health}}' myapp | jq

# Filtra contenedores por estado de salud
docker ps --filter "health=healthy"
docker ps --filter "health=unhealthy"
docker ps --filter "health=starting"
```

Desde Docker 29.5.0, `docker ps --format` soporta `.HealthStatus` directamente:

```sh
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.HealthStatus}}"
```

Los health checks son críticos cuando usas políticas `--restart`. Sin ellos, Docker reinicia una app rota atascada en un bucle de crash indefinidamente. Con un health check, el contenedor reporta `unhealthy` y puedes actuar en consecuencia.

## Sección 11: Docker Hub y autenticación en registries

### 11.1 Docker Login

- **`docker login`**: login interactivo en Docker Hub (pide usuario y contraseña).

- **`docker login --username myuser --password-stdin`**: no interactivo para CI/CD:

  ```sh
  echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin
  ```

- **`docker login ghcr.io --username myuser --password-stdin`**: inicia sesión en GitHub Container Registry.

  ```sh
  echo "$GITHUB_TOKEN" | docker login ghcr.io --username "$GITHUB_USERNAME" --password-stdin
  ```

- **`docker logout`** / **`docker logout ghcr.io`**: elimina las credenciales guardadas.

### 11.2 Límites de peticiones y mirrors de registry

<Notice type="warning" title="Límites de peticiones de Docker Hub">
Límites de pulls (cada 6 horas por IP/cuenta):
- **Sin autenticar**: 100 pulls
- **Cuenta gratuita autenticada**: 200 pulls
- **Suscripción de pago**: Ilimitados (uso razonable)

Si tus pipelines de CI/CD fallan con "toomanyrequests" o "rate limit exceeded", autentícate primero con `docker login`. Para entornos de alto volumen, plantéate una caché pull-through o un mirror de registry.
</Notice>

Para comprobar el estado actual de tu límite, inspecciona las cabeceras de respuesta:

```sh
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/ubuntu:pull" | jq -r .token)
curl -s -I -H "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/library/ubuntu/manifests/latest" | grep -i ratelimit
```

## Sección 12: Comandos avanzados

### 12.1 Docker Exec

Ejecuta comandos dentro de un contenedor en ejecución:

- **`docker exec -it mycontainer /bin/bash`**: shell interactiva. El uso más común.

- **`docker exec -it mycontainer sh`**: usa `sh` si bash no está disponible (imágenes Alpine).

- **`docker exec -u root -it mycontainer /bin/bash`**: exec como otro usuario.

- **`docker exec mycontainer cat /etc/hosts`**: ejecuta un comando puntual sin modo interactivo.

### 12.2 Docker Export e Import

Exporta el filesystem de un contenedor como un archivo tar. Esto captura el estado del filesystem pero **no** los volúmenes, los metadatos ni el historial de la imagen.

- **`docker export mycontainer > mycontainer.tar`**: exporta el filesystem.

- **`docker import mycontainer.tar myimage:restored`**: importa como una imagen nueva.

Caso de uso: migrar el filesystem de un contenedor a otro host, o crear un snapshot mínimo de imagen. Para backup a nivel de imagen, usa `save`/`load` en su lugar (conserva los metadatos).

### 12.3 Docker Save y Load

Guarda una imagen (con todas sus capas y metadatos) en un archivo tar:

- **`docker save -o myimage.tar myimage:latest`**: guarda una imagen.

- **`docker load -i myimage.tar`**: carga una imagen desde un archivo tar.

A diferencia de `export`/`import`, `save`/`load` conserva la imagen completa: capas, tags, metadatos. Usa esto para transferencias offline o entornos air-gapped.

### 12.4 Contextos de Docker

Gestiona conexiones a múltiples daemons de Docker desde una sola máquina. Se acabó el malabarismo con variables de entorno `DOCKER_HOST`.

```sh
# Lista los contextos
docker context ls

# Crea un contexto para un VPS remoto
docker context create my-vps --docker "host=ssh://user@vps-ip"

# Cambia a él
docker context use my-vps

# Ahora todos los comandos docker apuntan al daemon remoto
docker ps
docker compose up -d

# Vuelve al local
docker context use default
```

Esto es útil si ejecutas contenedores en un VPS remoto pero desarrollas en local. Los contextos basados en SSH funcionan de serie: solo asegúrate de tener tu clave SSH configurada.

### 12.5 Docker Init, Scout y otros comandos modernos

<Notice type="info" title="Comandos solo de Desktop">
`docker init` y `docker scout` requieren Docker Desktop o la instalación del plugin por separado en servidores Linux headless. En un VPS típico, puede que no estén disponibles de serie.
</Notice>

- **`docker init`**: genera el esqueleto de un Dockerfile, compose.yaml y .dockerignore para tu proyecto. Te guía con un asistente interactivo. Solo disponible en Docker Desktop (4.18+).

- **`docker scout quickview <image>`**: escaneo rápido de vulnerabilidades de una imagen.

- **`docker scout cves <image>`**: lista los CVEs encontrados en una imagen. Requiere el plugin Docker Scout.

- **`docker cp <container>:/path /host/path`**: copia archivos de un contenedor al host. Funciona en ambas direcciones: `docker cp /host/file container:/path`.

- **`docker update --restart=always <container>`**: cambia la política de reinicio en un contenedor en ejecución sin recrearlo.

- **`docker update --cpus 2 --memory 512m <container>`**: ajusta los límites de CPU y memoria en un contenedor en ejecución.

- **`docker port <container>`**: lista los mapeos de puertos de un contenedor.

- **`docker rename <old-name> <new-name>`**: renombra un contenedor.

- **`docker history <image>`**: muestra el historial de build de una imagen (tamaño y comando de cada capa).

- **`docker stats --no-stream`**: snapshot puntual del uso de recursos. Útil en scripts:

  ```sh
  docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
  ```

Para ejecutar herramientas CLI de IA y agentes de código de forma segura dentro de contenedores, consulta [entornos Docker seguros para herramientas CLI de IA](/es/docker-podman-entorno-seguro-ia/).

## Solución de errores comunes de Docker

| Error | Causa | Solución |
|-------|-------|-----|
| `Cannot connect to the Docker daemon` | El daemon no está en ejecución | `sudo systemctl start docker` |
| `permission denied while trying to connect` | El usuario no está en el grupo docker | `sudo usermod -aG docker $USER` y vuelve a iniciar sesión |
| `no space left on device` | Disco lleno | Ejecuta `docker system df` y luego `docker system prune -a`. Consulta la [guía de limpieza de Docker](/es/limpiar-docker-completo/) |
| `port is already allocated` | Puerto en uso | `docker ps` para encontrar el contenedor que lo usa, luego `docker stop` o cambia el mapeo `-p` |
| `toomanyrequests` / límite de tasa | Demasiados pulls sin autenticar | `docker login` primero, o usa un mirror de registry |
| `network xxx not found` | El nombre del proyecto Compose cambió | Ejecuta `docker compose down` limpiamente antes de renombrar, comprueba `docker network ls` |
| `image is being used by running container` | No se puede eliminar una imagen en uso | Detén y elimina el contenedor primero: `docker rm -f <container>` |

## Conclusión

Ya tienes una referencia que cubre más de 60 comandos de Docker: desde la gestión diaria de contenedores hasta Compose v2, builds multiplataforma con buildx, limpieza de disco, health checks y autenticación en registries. Guarda en favoritos la tabla de referencia rápida de arriba para consultas rápidas.

Docker cambia rápido. Los mayores cambios desde 2023: Compose v1 ha muerto, BuildKit es el builder por defecto, y el image store de containerd es el nuevo por defecto en instalaciones nuevas de Docker 29. Si aún mantienes viejos hábitos, es un buen momento para actualizar.

Para más guías de Docker, echa un vistazo a [más de 100 de los mejores contenedores Docker para un servidor casero](/es/contenedores-docker-servidor-casa/): es un buen punto de partida para decidir qué ejecutar realmente.