Contenido
Tutorial de Docker para ejecutar tu primer contenedor: aprende a usar docker run
En esta sección ejecutarás un servidor web nginx y aprenderás a consultar, acceder, detener y eliminar contenedores. Cada paso incluye el resultado real de su ejecución.
Inicia nginx
docker run -d -p 8080:80 --name web nginx:1.30
$ docker run -d -p 8080:80 --name web nginx:1.30
Unable to find image 'nginx:1.30' locally
1.30: Pulling from library/nginx
ecc510c1e359: Pull complete
f4616bb1be1c: Pull complete
f1a6a629b824: Pull complete
3d774efa34e3: Pull complete
cb44c3fe542b: Pull complete
121907e00c1c: Pull complete
220a6ac36368: Pull complete
Digest: sha256:9bf97bd7714f5e24c1ccd545ecb9eb5435cb6d109c97cebb15e7e455e0239edb
Status: Downloaded newer image for nginx:1.30
b470f4d4563701824e59040cdfcd2154b4bbcca581e6d2d75cae5f2c23dbcfda
Esto es lo que ocurre, paso a paso:
- No tienes la imagen
nginx:1.30en tu equipo (Unable to find image ... locally), así que Docker la descarga de Docker Hub. - La imagen está compuesta por varias capas. Cada línea
Pull completeindica que se ha descargado una capa. - Cuando termina la descarga, Docker usa la imagen para crear un contenedor nuevo llamado
web. -dejecuta el contenedor en segundo plano, por lo que el comando termina enseguida e imprime solo el ID del contenedor (una larga cadena de caracteres hexadecimales).
Explicación de los parámetros
| Parámetro | Significado |
|---|---|
-d | detached: ejecuta en segundo plano |
-p 8080:80 | Asigna el puerto 8080 del host al puerto 80 del contenedor |
--name web | Asigna el nombre web al contenedor para poder administrarlo después con ese nombre |
nginx:1.30 | Nombre y versión (tag) de la imagen |
Ábrelo en el navegador
Abre el navegador e introduce http://localhost:8080:

El tráfico sigue esta ruta: navegador → puerto 8080 del host → Docker lo reenvía al puerto 80 del contenedor → nginx dentro del contenedor.
También puedes probarlo desde la terminal con curl:
$ curl -s http://localhost:8080 | head -n 4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
Consulta los contenedores en ejecución: docker ps
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b470f4d45637 nginx:1.30 "/docker-entrypoint.…" 7 seconds ago Up 7 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp web
| Campo | Significado |
|---|---|
| CONTAINER ID | Los primeros 12 caracteres del ID del contenedor; puedes usarlo en los comandos en lugar del nombre |
| IMAGE | Imagen utilizada |
| COMMAND | Comando que se ejecuta al iniciar el contenedor |
| CREATED / STATUS | Hora de creación y estado actual (Up indica que está en ejecución) |
| PORTS | Asignación de puertos; 0.0.0.0:8080->80/tcp corresponde a -p 8080:80, que acabas de usar |
| NAMES | Nombre del contenedor |
Consulta los registros: docker logs
nginx registra cada solicitud en los registros. Hace un momento te conectaste una vez desde el navegador y otra con curl:
$ docker logs web
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2026/10/12 14:38:25 [notice] 1#1: using the "epoll" event method
2026/10/12 14:38:25 [notice] 1#1: nginx/1.30.5
2026/10/12 14:38:25 [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19)
2026/10/12 14:38:25 [notice] 1#1: OS: Linux 5.4.0-216-generic
2026/10/12 14:38:25 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2026/10/12 14:38:25 [notice] 1#1: start worker processes
2026/10/12 14:38:25 [notice] 1#1: start worker process 28
172.17.0.1 - - [12/Oct/2026:14:38:29 +0000] "GET / HTTP/1.1" 200 896 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/130.0.6723.31 Safari/537.36" "-"
172.18.0.1 - - [12/Oct/2026:14:38:31 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.22.0" "-"
Las primeras líneas son mensajes de inicio de nginx; puedes ver que la versión es nginx/1.30.5. Las dos últimas son los registros de las solicitudes que acabas de hacer: una proviene del navegador (el User-Agent es el del navegador) y la otra de curl. Añade -f para seguir los nuevos registros en tiempo real (pulsa Ctrl + C para salir):
docker logs -f web
Entrar en un contenedor: docker exec
docker exec ejecuta comandos dentro de un contenedor en ejecución:
$ docker exec web nginx -v
nginx version: nginx/1.30.5
$ docker exec web ls /usr/share/nginx/html
50x.html
index.html
Añade -it para abrir una shell interactiva y explorar el contenedor:
$ docker exec -it web bash
root@b470f4d45637:/# cat /etc/os-release | head -n 2
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
NAME="Debian GNU/Linux"
root@b470f4d45637:/# ls /etc/nginx
conf.d
fastcgi_params
mime.types
modules
nginx.conf
scgi_params
uwsgi_params
root@b470f4d45637:/# ps aux
bash: line 1: ps: command not found
root@b470f4d45637:/# exit
exit
La salida permite ver varias cosas:
- La imagen oficial de nginx se basa en Debian 13 (trixie).
b470f4d45637, que aparece en el prompt, es el nombre de host del contenedor; de forma predeterminada, es el ID del contenedor.- El contenedor no incluye el comando
ps. La imagen oficial solo contiene lo necesario para ejecutar nginx, y se han eliminado muchas herramientas habituales. Es normal. Si necesitas herramientas de depuración, puedes instalarlas temporalmente (apt-get update && apt-get install -y procps) o usar docker top para consultar el contenedor desde fuera.
Escribe exit para salir; el contenedor seguirá ejecutándose.
Modificar el contenido de la página web
Cambia la página de inicio dentro del contenedor y vuelve a cargar el navegador:
$ docker exec web sh -c 'echo "<h1>Hello from my first container</h1>" > /usr/share/nginx/html/index.html'
$ curl -s http://localhost:8080
<h1>Hello from my first container</h1>

Modificar directamente los archivos dentro de un contenedor solo es útil para pruebas temporales. Al eliminar el contenedor, los cambios desaparecen. La forma correcta es montar los archivos de la página web en el contenedor (consulta Volume) o incluirlos en un Dockerfile.
Detener, iniciar y eliminar
$ docker stop web
web
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b470f4d45637 nginx:1.30 "/docker-entrypoint.…" 12 seconds ago Exited (0) Less than a second ago web
786dd898c04b hello-world "/hello" About a minute ago Exited (0) About a minute ago frosty_shirley
$ docker start web
web
$ curl -s http://localhost:8080
<h1>Hello from my first container</h1>
$ docker rm web
Error response from daemon: cannot remove container "web": container is running: stop the container before removing or force remove
$ docker rm -f web
web
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
786dd898c04b hello-world "/hello" About a minute ago Exited (0) About a minute ago frosty_shirley
docker stop: detiene el contenedor, pero este sigue existiendo. Puedes verlo condocker ps -ay su estado esExited.docker start: vuelve a iniciar un contenedor existente; la página de inicio que modificaste también sigue ahí.docker rm: elimina un contenedor detenido. Si lo usas con un contenedor en ejecución, aparecerá el errorcontainer is runningde arriba. Primero ejecutadocker stopo añade-fpara forzar su eliminación.
En la lista de docker ps -a también aparece el contenedor hello-world que ejecutaste en la sección anterior: terminó de ejecutarse (Exited (0)), pero no se eliminó. Los contenedores a los que no asignas un nombre con --name reciben uno aleatorio, como frosty_shirley.
Al eliminar el contenedor, también desaparece la página de inicio que modificaste. Si inicias un contenedor nuevo con la misma imagen, verás la página de bienvenida original de nginx.
Ejecutar un comando puntual
No todos los contenedores tienen que ejecutarse de forma continua. Este contenedor ejecuta un solo comando y termina; --rm hace que se elimine automáticamente al terminar:
$ docker run --rm ubuntu:26.04 cat /etc/os-release
Unable to find image 'ubuntu:26.04' locally
26.04: Pulling from library/ubuntu
06ad70e463aa: Pull complete
4e07a0f12b2c: Pull complete
Digest: sha256:f144425ff09be612d6d9ad965196e9cdc23dae1f42110a8a11a3e9a8198759f7
Status: Downloaded newer image for ubuntu:26.04
PRETTY_NAME="Ubuntu 26.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04.1 LTS (Resolute Raccoon)"
VERSION_CODENAME=resolute
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=resolute
LOGO=ubuntu-logo
Este contenedor Ubuntu solo incluye los archivos del espacio de usuario de Ubuntu; no tiene proceso de arranque ni escritorio, y tarda un instante en iniciarse y terminar.
Usar la interfaz gráfica de Docker Desktop
En Windows y macOS, también puedes realizar con el ratón en Docker Desktop todos los pasos anteriores.
Buscar y descargar una imagen
Escribe el nombre de la imagen en el cuadro de búsqueda de la parte superior, elige la versión que quieras (Tag) y pulsa Pull para descargarla o directamente Run:

Configurar y ejecutar un contenedor
Después de pulsar Run, despliega Optional settings para configurar el nombre del contenedor, los puertos, Volume y las variables de entorno. Estas opciones corresponden a --name, -p, -v y -e de docker run:

Ver y administrar contenedores
El menú de la izquierda, Containers, muestra todos los contenedores, igual que docker ps -a. Haz clic en el enlace de la columna Port(s) para abrirlo directamente en el navegador. Los botones de la derecha permiten detener, reiniciar y eliminar contenedores:

Al entrar en un contenedor, puedes ver pestañas como Logs (equivalente a docker logs), Exec (equivalente a docker exec) y Files (para explorar los archivos del contenedor):

La interfaz gráfica facilita consultar el estado, pero en la práctica se suelen usar comandos: puedes incluirlos en documentos y scripts, y en los servidores Linux solo puedes operar mediante comandos.
Usuarios de Windows: diferencias en la sintaxis de los comandos
Los comandos de este tutorial usan bash de Linux/macOS. En Windows, los comandos de Docker son exactamente iguales, pero la sintaxis del terminal (shell) es distinta:
| Sintaxis | Linux / macOS (bash) | Windows PowerShell | Windows CMD |
|---|---|---|---|
| Carpeta actual | $(pwd) | ${PWD} | %cd% |
| Continuación de línea | \ al final de la línea | ` al final de la línea | ^ al final de la línea |
| Variable de entorno | $HOME | $env:USERPROFILE | %USERPROFILE% |
Entrada desde un archivo < | Sí | No compatible | Sí |
Los comandos de este tutorial que requieren una sintaxis distinta incluyen pestañas para Linux / macOS, Windows PowerShell y Windows CMD. Al seleccionar una, toda la página cambia a esa misma sintaxis. Por ejemplo, para montar la carpeta site actual en nginx:
docker run -d -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d -p 8080:80 -v "${PWD}/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d -p 8080:80 -v "%cd%/site:/usr/share/nginx/html:ro" nginx:1.30
Algunos errores frecuentes (consulta los mensajes de error reales en Mensajes de error frecuentes):
- En PowerShell, escribir
"$PWD:/app"provoca un error; debes escribir"${PWD}:/app". - PowerShell no admite
<; para restaurar una base de datos, usadocker cp. Los capítulos sobre bases de datos incluyen las instrucciones. - Si un script de shell editado en Windows usa saltos de línea CRLF, al ejecutarlo en un contenedor aparecerá
no such file or directory.
También puedes usar Docker Desktop desde el terminal de WSL (por ejemplo, Ubuntu); en ese caso, puedes usar directamente la sintaxis de Linux de este tutorial.
Resumen
docker run -d -p puerto_host:puerto_contenedor --name nombre imageninicia un contenedor en segundo plano y asigna puertos.docker psmuestra los contenedores en ejecución;-atambién incluye los que están detenidos.docker logsmuestra la salida;docker exec -it contenedor shabre una sesión dentro del contenedor.docker stop/start/rm -fpermiten controlar y eliminar contenedores; cambiar directamente los archivos dentro de un contenedor solo es adecuado para pruebas temporales.
Ejercicios
- Inicia otro nginx y asigna el puerto 8081 del host:
docker run -d -p 8081:80 --name web2 nginx:1.30. Abrehttp://localhost:8081para comprobarlo. - Usa
docker pspara confirmar que ambos contenedores se están ejecutando a la vez y que cada uno tiene asignado un puerto distinto del host. - Elimina ambos contenedores:
docker rm -f web web2.
En la siguiente sección veremos las imágenes con más detalle: las reglas de nombres y etiquetas, cómo descargarlas, consultarlas y eliminarlas.
Preguntas frecuentes
¿No se abre http://localhost:8080?
Primero, usa docker ps para confirmar que el contenedor está en ejecución y que la columna PORTS muestra 0.0.0.0:8080->80/tcp. Si otro programa está usando el puerto 8080, docker run mostrará port is already allocated; cambia a -p 8081:80.
¿Por qué no hay comandos como ps o vim en el contenedor?
Las imágenes oficiales solo incluyen lo necesario para ejecutar el servicio, así ocupan menos y tienen menos vulnerabilidades. Para depurar, puedes usar docker exec para ejecutar las herramientas disponibles en la imagen, o iniciar otro contenedor que incluya herramientas.
¿Se pueden usar indistintamente el ID y el nombre del contenedor?
Sí. En los comandos puedes usar el nombre o los primeros caracteres del ID, siempre que no coincidan con los de otro contenedor.
Actualizado 14 de octubre de 2026