Contenido

Tutorial de docker run: guía completa de opciones con resultados reales

docker run es el comando de Docker más utilizado y también el que tiene más opciones. Su formato básico es:

docker run [opciones] imagen[:tag] [comando] [argumentos del comando]

La parte que aparece después del nombre de la imagen reemplaza el comando predeterminado de la imagen (CMD):

$ docker run --rm alpine:3.23 cat /etc/alpine-release
3.23.6

--rm es una opción de Docker; cat /etc/alpine-release es el comando que se ejecuta dentro del contenedor y reemplaza el /bin/sh predeterminado de alpine.

Las opciones siempre deben escribirse antes del nombre de la imagen

Todo lo que escribas después del nombre de la imagen se interpretará como un comando dentro del contenedor:

$ docker run alpine:3.23 --rm echo hi
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "--rm": executable file not found in $PATH

Run 'docker run --help' for more information

Docker intenta ejecutar dentro del contenedor un programa llamado --rm, que, por supuesto, no encuentra (executable file not found). Si ves este tipo de error, comprueba primero dónde colocaste las opciones.

Modos de ejecución

OpciónDescripción
-d, --detachEjecuta en segundo plano y devuelve el ID del contenedor de inmediato
-i, --interactiveMantiene abierta la entrada estándar
-t, --ttyAsigna un terminal virtual
--rmElimina automáticamente el contenedor al terminar
--nameAsigna un nombre al contenedor; de lo contrario, se genera uno aleatorio (por ejemplo, dreamy_solomon)
docker run -it --rm ubuntu:26.04 bash      # Abre una sesión interactiva y elimina el contenedor al salir
docker run -d --name cache redis:8-alpine  # Servicio en segundo plano

Casi siempre se usan -it juntos para abrir un shell interactivo. Con solo -i, puedes enviar datos al contenedor mediante una tubería:

$ echo "hello" | docker run -i --rm alpine:3.23 cat
hello

Puertos: -p

El formato es -p puerto_host:puerto_contenedor. Estas tres formas muestran cómo funciona en la práctica:

$ docker run -d --name p1 -p 8080:80 nginx:1.30
27b89a4fae92dfe05bf051e11700033c7b9bb71f8747acc986d2a535cc1baa00

$ docker run -d --name p2 -p 127.0.0.1:8081:80 nginx:1.30
3327f3c1df4fa1e03fa3a120e5d889859fc0cb53d0aaf269826c81b25f4411c2

$ docker run -d --name p3 -P nginx:1.30
57c9a309c4758786361738b7b9a4231f404cb9bbab28f38cad39b4b6e996d9e0

$ docker port p1
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080

$ docker port p2
80/tcp -> 127.0.0.1:8081

$ docker port p3
80/tcp -> 0.0.0.0:32768
80/tcp -> [::]:32768
FormaResultado
-p 8080:80Enlaza todas las interfaces de red (0.0.0.0 y [::] para IPv6), por lo que otros equipos también pueden conectarse
-p 127.0.0.1:8081:80Solo enlaza la máquina local; únicamente este equipo puede conectarse
-PAsigna los puertos EXPOSE de la imagen a puertos aleatorios del host (en este caso, se asignó el 32768)

docker port nombre_contenedor muestra la asignación real. Para un puerto UDP, escribe -p 5353:53/udp.

En un host en la nube, -p 8080:80 permite conexiones externas; además, Docker modifica las reglas del firewall por su cuenta, así que es posible que la configuración de ufw no las bloquee. Para servicios que no deben exponerse, como una base de datos, enlaza 127.0.0.1 o no uses -p; en su lugar, conecta los contenedores mediante una red personalizada.

Datos: -v y --mount

-v ruta_host:ruta_contenedor monta una carpeta del host dentro del contenedor (bind mount). Prepara una carpeta site que contenga un archivo index.html:

$ ls site
index.html

$ docker run -d --name site -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html:ro" nginx:1.30
e91f46b91ff8f0f64d59d6605bfddea0ee5bca809de86d81cbd5051815e65dd1

$ curl -s http://localhost:8080 | head -n 3
<!doctype html>
<html><head><meta charset="utf-8"><title>My site</title>
<style>body{font-family:system-ui,sans-serif;max-width:640px;margin:60px auto;padding:0 16px;color:#1f2937}h1{color:#1d63ed}</style></head>

Comandos para Windows (selecciona una pestaña para cambiar):

docker run -d --name site -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d --name site -p 8080:80 -v "${PWD}/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d --name site -p 8080:80 -v "%cd%/site:/usr/share/nginx/html:ro" nginx:1.30
nginx muestra la página montada mediante bind mount
nginx muestra el contenido de site/index.html en el host

El :ro del final indica solo lectura. Si intentas escribir en esta carpeta desde el contenedor, se rechazará la operación:

$ docker exec site sh -c "echo test > /usr/share/nginx/html/x.txt"
sh: 1: cannot create /usr/share/nginx/html/x.txt: Read-only file system

Otra forma de montar datos es usar un Volume gestionado por Docker (-v nombre:ruta_contenedor), adecuado para conservar datos como los de una base de datos:

docker run -d -v pgdata:/var/lib/postgresql postgres:18

--mount ofrece la misma función con una sintaxis más larga y explícita. Para conocer las diferencias y cuándo usar cada opción, consulta Volume y Bind Mount.

Variables de entorno: -e y --env-file

$ docker run --rm -e GREETING=hello -e APP_ENV=dev alpine:3.23 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=18f035817c43
GREETING=hello
APP_ENV=dev
HOME=/root

-e nombre_variable (sin especificar un valor) reutiliza la variable de entorno del mismo nombre que esté definida en el host:

$ APP_ENV=prod docker run --rm -e APP_ENV alpine:3.23 sh -c 'echo $APP_ENV'
prod

Si tienes muchas variables, usa --env-file archivo. Consulta Variables de entorno y archivos .env para obtener más información.

Redes

Los contenedores de una misma red personalizada pueden conectarse entre sí usando sus nombres:

$ docker network create mynet
2ecd542737519b0b8919061077814e007a72e2d07973f0840608b1b5454c678e

$ docker run -d --name myweb --network mynet nginx:1.30
9a6ca3dca3a003e28b9870f3eec436cf7023a6872e8ddd4cee971d29f845583b

$ docker run --rm --network mynet alpine:3.23 ping -c 2 myweb
PING myweb (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.094 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.064 ms

--- myweb ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.064/0.079/0.094 ms

$ docker run --rm alpine:3.23 ping -c 1 -W 2 myweb
ping: bad address 'myweb'
  • El primer contenedor de ping está en mynet; el DNS integrado de Docker resuelve myweb como 172.19.0.2.
  • El segundo no incluye --network, así que está en la red predeterminada y no encuentra myweb (bad address).

Evita nombres de contenedor como web o app, que coinciden con palabras que son dominios de nivel superior (TLD). Si no se unen a la misma red, el DNS externo puede resolver estos nombres a direcciones extrañas (por ejemplo, 127.0.53.53), lo que dificulta aún más la depuración.

docker run --network host nginx:1.30     # Usa directamente la red del host (Linux)
docker run --network none alpine:3.23    # Sin red

Consulta Redes y comunicación entre contenedores.

Política de reinicio

docker run -d --restart unless-stopped nginx:1.30

Los valores disponibles son no, on-failure, always y unless-stopped. Consulta el comportamiento concreto en Ciclo de vida de los contenedores.

Límites de recursos

$ docker run -d --name limited --memory 64m --cpus 0.5 nginx:1.30
2e65ce89f346cb7d9d57f1e6ad529d63ad53d1d914b6d3178dc3344a1d3325f0

$ docker stats --no-stream limited
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O       BLOCK I/O         PIDS
2e65ce89f346   limited   0.00%     3.922MiB / 64MiB    6.13%     736B / 126B   1.77MB / 8.19kB   2

MEM USAGE / LIMIT muestra 3.922MiB / 64MiB: el límite de memoria está activo. nginx usa menos de 4 MB cuando está inactivo.

ParámetroDescripción
--memory, -mLímite de memoria, por ejemplo, 512m o 2g; si se supera, el proceso se termina (OOM, código de salida 137)
--memory-swapLímite total de memoria + swap
--cpusNúmero de CPU que se pueden usar; puede ser decimal, 0.5 representa media CPU
--pids-limitNúmero máximo de procesos dentro del contenedor

Para ver qué ocurre cuando se supera el límite de memoria, consulta el ejemplo de OOM en Ver registros y depurar.

Anular los valores predeterminados de la imagen

$ docker run --rm --entrypoint sh nginx:1.30 -c "nginx -v; whoami"
nginx version: nginx/1.30.5
root

$ docker run --rm -u 1000:1000 alpine:3.23 id
uid=1000 gid=1000 groups=1000

$ docker run --rm -w /tmp alpine:3.23 pwd
/tmp

$ docker run --rm -h myhost alpine:3.23 hostname
myhost
ParámetroDescripción
--entrypointAnula ENTRYPOINT; suele usarse para inspeccionar una imagen que normalmente iniciaría un servicio directamente
-u, --userEjecuta como el usuario especificado (UID:GID)
-w, --workdirAnula el directorio de trabajo
-h, --hostnameNombre del host del contenedor

A menudo se usa -u para que los archivos creados por el contenedor te pertenezcan y no pertenezcan a root:

docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/work" -w /work node:24-alpine npm install

Sistema de archivos de solo lectura

$ docker run --rm --read-only alpine:3.23 touch /hello
touch: /hello: Read-only file system

--read-only hace que todo el sistema de archivos del contenedor sea de solo lectura. Aunque alguien se apodere del programa, no podrá modificar archivos. Para permitir escrituras donde sea necesario, usa --tmpfs /tmp o un Volume. Consulta Buenas prácticas de seguridad.

Otros parámetros útiles

ParámetroDescripción
--initUsa un proceso init pequeño como PID 1 para reenviar señales correctamente (docker stop no tiene que esperar 10 segundos; consulta Ciclo de vida de los contenedores)
--platformEspecifica la plataforma, por ejemplo, linux/amd64
--add-hostAñade una entrada en hosts, por ejemplo, --add-host host.docker.internal:host-gateway
--labelAñade una etiqueta para facilitar el filtrado
--pull alwaysVuelve a descargar la imagen antes de cada ejecución
--log-opt max-size=10mLimita el tamaño del archivo de registro

Referencia rápida de más opciones

Esta lista se basa en docker run --help (Docker 29) e incluye opciones útiles de este capítulo que no se explican en detalle. Para ver la lista completa, ejecuta docker run --help.

CategoríaOpciónDescripción
Seguridad--cap-add / --cap-dropAñade o elimina capacidades de Linux; consulta Buenas prácticas de seguridad para ver pruebas
Seguridad--security-optOpciones de seguridad, como no-new-privileges y la configuración de seccomp
Seguridad--privilegedConcede todos los permisos al contenedor y desactiva casi todo el aislamiento; evítala
Seguridad--usernsEspacio de nombres de usuario que se usa
Comprobación de estado--health-cmdComando de comprobación de estado, por ejemplo, --health-cmd "curl -f http://localhost/"
Comprobación de estado--health-interval / --health-timeout / --health-retriesIntervalo de comprobación, tiempo de espera y número de fallos consecutivos para marcar el estado como unhealthy
Comprobación de estado--health-start-period / --health-start-intervalPeríodo de gracia y intervalo de comprobación durante el inicio
Comprobación de estado--no-healthcheckDesactiva el HEALTHCHECK configurado en la imagen
Red--network-aliasAñade otro nombre en la red; consulta docker network
Red--ipEspecifica una IP fija en una red personalizada
Red--dns / --dns-searchPersonaliza el servidor DNS y el dominio de búsqueda
Red--exposeDeclara un puerto (sin publicarlo en el host); equivale a EXPOSE en un Dockerfile
Red-P, --publish-allPublica todos los puertos declarados en puertos aleatorios del host
Detención--stop-signalSeñal que envía docker stop; el valor predeterminado es SIGTERM
Detención--stop-timeoutSegundos que espera docker stop; el valor predeterminado es 10
Recursos--cpuset-cpusUsa solo las CPU especificadas, por ejemplo, 0,1 o 0-3
Recursos-c, --cpu-sharesPeso relativo de CPU (solo tiene efecto cuando hay competencia por recursos)
Recursos--memory-reservationLímite flexible de memoria
Recursos--shm-sizeTamaño de /dev/shm; programas como PostgreSQL y los navegadores suelen necesitar un valor mayor
Recursos--ulimitPor ejemplo, --ulimit nofile=65535:65535 ajusta el límite de archivos abiertos
Recursos--oom-kill-disableDesactiva la terminación forzada cuando falta memoria (debe combinarse con --memory)
Dispositivos--devicePasa un dispositivo del host al contenedor, por ejemplo, /dev/ttyUSB0
Dispositivos--gpusUsa la GPU, por ejemplo, --gpus all (requiere NVIDIA Container Toolkit)
Espacios de nombres--pid host / --ipc / --utsComparte espacios de nombres del host o de otro contenedor; consulta Funcionamiento interno para conocer el principio
Sistema--sysctlConfigura parámetros del kernel del contenedor, por ejemplo, net.core.somaxconn=1024
Sistema--umaskUmask de los procesos del contenedor
Montaje--volumes-fromMonta todos los volúmenes de otro contenedor
Otros--cidfileEscribe el ID del contenedor en un archivo para que lo usen los scripts
Otros--label-fileLee las etiquetas de un archivo
Otros--log-driverControlador de registros, por ejemplo, json-file, local o syslog
Otros-q, --quietOculta el progreso al descargar una imagen
Otros--use-api-socketMonta el socket de la API de Docker y las credenciales de inicio de sesión en el contenedor (equivale a tener permisos de root en el host; consulta Buenas prácticas de seguridad)

Ejemplos de combinaciones habituales

# 1. Contenedor de herramientas de un solo uso: ejecuta un comando en la carpeta actual
docker run --rm -v "$(pwd):/data" -w /data alpine:3.23 ls -la

# 2. Base de datos para desarrollo local, solo acepta conexiones locales
docker run -d --name devdb --restart unless-stopped \
  -p 127.0.0.1:5432:5432 \
  -e POSTGRES_PASSWORD=dev \
  -v devdb:/var/lib/postgresql \
  postgres:18

# 3. Servicio de producción con límites de recursos y tamaño de registros
docker run -d --name api --restart unless-stopped \
  --memory 1g --cpus 2 \
  --log-opt max-size=10m --log-opt max-file=3 \
  --env-file .env -p 3000:3000 \
  myorg/api:1.4.2
# 1. Contenedor de herramientas de un solo uso: ejecuta un comando en la carpeta actual
docker run --rm -v "${PWD}:/data" -w /data alpine:3.23 ls -la

# 2. Base de datos para desarrollo local, solo acepta conexiones locales
docker run -d --name devdb --restart unless-stopped `
  -p 127.0.0.1:5432:5432 `
  -e POSTGRES_PASSWORD=dev `
  -v devdb:/var/lib/postgresql `
  postgres:18

# 3. Servicio de producción con límites de recursos y tamaño de registros
docker run -d --name api --restart unless-stopped `
  --memory 1g --cpus 2 `
  --log-opt max-size=10m --log-opt max-file=3 `
  --env-file .env -p 3000:3000 `
  myorg/api:1.4.2
# 1. Contenedor de herramientas de un solo uso: ejecuta un comando en la carpeta actual
docker run --rm -v "%cd%:/data" -w /data alpine:3.23 ls -la

# 2. Base de datos para desarrollo local, solo acepta conexiones locales
docker run -d --name devdb --restart unless-stopped ^
  -p 127.0.0.1:5432:5432 ^
  -e POSTGRES_PASSWORD=dev ^
  -v devdb:/var/lib/postgresql ^
  postgres:18

# 3. Servicio de producción con límites de recursos y tamaño de registros
docker run -d --name api --restart unless-stopped ^
  --memory 1g --cpus 2 ^
  --log-opt max-size=10m --log-opt max-file=3 ^
  --env-file .env -p 3000:3000 ^
  myorg/api:1.4.2

Cuando hay muchas opciones, el comando se vuelve difícil de mantener. Si necesitas ejecutar algo durante mucho tiempo o varios contenedores juntos, te recomendamos usar Docker Compose y guardar la configuración en un archivo.

Resumen

  • Las opciones van antes del nombre de la imagen; lo que viene después es el comando que se ejecutará dentro del contenedor.
  • -d, --rm, --name, -p, -v y -e son las opciones que más se usan juntas.
  • --memory, --cpus y --pids-limit limitan los recursos.
  • --entrypoint, -u y -w reemplazan los valores predeterminados de la imagen.

Ejercicios

Ejercicio 1: Escribe un comando que ejecute nginx:1.30-alpine en segundo plano, con el nombre site, accesible solo desde el puerto 8080 local, con un límite de memoria de 128 MB y que no conserve el contenedor al terminar.

Respuesta
docker run -d --rm --name site -p 127.0.0.1:8080:80 --memory 128m nginx:1.30-alpine

--rm elimina automáticamente el contenedor cuando se detiene.

Ejercicio 2: ENTRYPOINT de la imagen postgres:18 inicia la base de datos. ¿Cómo puedes entrar solo en su shell sin iniciar la base de datos?

Respuesta
docker run --rm -it --entrypoint sh postgres:18

--entrypoint reemplaza el ENTRYPOINT de la imagen.

Preguntas frecuentes

¿Por qué no funciona una opción escrita después del nombre de la imagen?

El contenido que aparece después del nombre de la imagen se interpreta como un comando que se ejecutará dentro del contenedor. Las opciones de docker run siempre deben escribirse antes del nombre de la imagen.

¿Cuál es la diferencia entre -p 8080:80 y -p 127.0.0.1:8080:80?

La primera opción enlaza todas las interfaces de red, por lo que otros equipos también pueden conectarse; la segunda solo enlaza la máquina local. Para servicios que no necesitan exponerse, como una base de datos, usa la segunda o no añadas -p.

¿Cuántas opciones tiene docker run?

La salida de docker run --help de Docker 29 enumera alrededor de 100 opciones. En este capítulo verás las más usadas; la sección «Más opciones de un vistazo» reúne otras opciones útiles.

Actualizado 14 de octubre de 2026