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ón | Descripción |
|---|---|
-d, --detach | Ejecuta en segundo plano y devuelve el ID del contenedor de inmediato |
-i, --interactive | Mantiene abierta la entrada estándar |
-t, --tty | Asigna un terminal virtual |
--rm | Elimina automáticamente el contenedor al terminar |
--name | Asigna 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
| Forma | Resultado |
|---|---|
-p 8080:80 | Enlaza 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:80 | Solo enlaza la máquina local; únicamente este equipo puede conectarse |
-P | Asigna 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:80permite 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, enlaza127.0.0.1o 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

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 resuelvemywebcomo172.19.0.2. - El segundo no incluye
--network, así que está en la red predeterminada y no encuentramyweb(bad address).
Evita nombres de contenedor como
weboapp, 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ámetro | Descripción |
|---|---|
--memory, -m | Límite de memoria, por ejemplo, 512m o 2g; si se supera, el proceso se termina (OOM, código de salida 137) |
--memory-swap | Límite total de memoria + swap |
--cpus | Número de CPU que se pueden usar; puede ser decimal, 0.5 representa media CPU |
--pids-limit | Nú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ámetro | Descripción |
|---|---|
--entrypoint | Anula ENTRYPOINT; suele usarse para inspeccionar una imagen que normalmente iniciaría un servicio directamente |
-u, --user | Ejecuta como el usuario especificado (UID:GID) |
-w, --workdir | Anula el directorio de trabajo |
-h, --hostname | Nombre 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ámetro | Descripción |
|---|---|
--init | Usa 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) |
--platform | Especifica la plataforma, por ejemplo, linux/amd64 |
--add-host | Añade una entrada en hosts, por ejemplo, --add-host host.docker.internal:host-gateway |
--label | Añade una etiqueta para facilitar el filtrado |
--pull always | Vuelve a descargar la imagen antes de cada ejecución |
--log-opt max-size=10m | Limita 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ía | Opción | Descripción |
|---|---|---|
| Seguridad | --cap-add / --cap-drop | Añade o elimina capacidades de Linux; consulta Buenas prácticas de seguridad para ver pruebas |
| Seguridad | --security-opt | Opciones de seguridad, como no-new-privileges y la configuración de seccomp |
| Seguridad | --privileged | Concede todos los permisos al contenedor y desactiva casi todo el aislamiento; evítala |
| Seguridad | --userns | Espacio de nombres de usuario que se usa |
| Comprobación de estado | --health-cmd | Comando de comprobación de estado, por ejemplo, --health-cmd "curl -f http://localhost/" |
| Comprobación de estado | --health-interval / --health-timeout / --health-retries | Intervalo 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-interval | Período de gracia y intervalo de comprobación durante el inicio |
| Comprobación de estado | --no-healthcheck | Desactiva el HEALTHCHECK configurado en la imagen |
| Red | --network-alias | Añade otro nombre en la red; consulta docker network |
| Red | --ip | Especifica una IP fija en una red personalizada |
| Red | --dns / --dns-search | Personaliza el servidor DNS y el dominio de búsqueda |
| Red | --expose | Declara un puerto (sin publicarlo en el host); equivale a EXPOSE en un Dockerfile |
| Red | -P, --publish-all | Publica todos los puertos declarados en puertos aleatorios del host |
| Detención | --stop-signal | Señal que envía docker stop; el valor predeterminado es SIGTERM |
| Detención | --stop-timeout | Segundos que espera docker stop; el valor predeterminado es 10 |
| Recursos | --cpuset-cpus | Usa solo las CPU especificadas, por ejemplo, 0,1 o 0-3 |
| Recursos | -c, --cpu-shares | Peso relativo de CPU (solo tiene efecto cuando hay competencia por recursos) |
| Recursos | --memory-reservation | Límite flexible de memoria |
| Recursos | --shm-size | Tamaño de /dev/shm; programas como PostgreSQL y los navegadores suelen necesitar un valor mayor |
| Recursos | --ulimit | Por ejemplo, --ulimit nofile=65535:65535 ajusta el límite de archivos abiertos |
| Recursos | --oom-kill-disable | Desactiva la terminación forzada cuando falta memoria (debe combinarse con --memory) |
| Dispositivos | --device | Pasa un dispositivo del host al contenedor, por ejemplo, /dev/ttyUSB0 |
| Dispositivos | --gpus | Usa la GPU, por ejemplo, --gpus all (requiere NVIDIA Container Toolkit) |
| Espacios de nombres | --pid host / --ipc / --uts | Comparte espacios de nombres del host o de otro contenedor; consulta Funcionamiento interno para conocer el principio |
| Sistema | --sysctl | Configura parámetros del kernel del contenedor, por ejemplo, net.core.somaxconn=1024 |
| Sistema | --umask | Umask de los procesos del contenedor |
| Montaje | --volumes-from | Monta todos los volúmenes de otro contenedor |
| Otros | --cidfile | Escribe el ID del contenedor en un archivo para que lo usen los scripts |
| Otros | --label-file | Lee las etiquetas de un archivo |
| Otros | --log-driver | Controlador de registros, por ejemplo, json-file, local o syslog |
| Otros | -q, --quiet | Oculta el progreso al descargar una imagen |
| Otros | --use-api-socket | Monta 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,-vy-eson las opciones que más se usan juntas.--memory,--cpusy--pids-limitlimitan los recursos.--entrypoint,-uy-wreemplazan 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