Docker se maneja casi por completo desde la línea de comandos, y una docena de comandos cubren el trabajo diario con contenedores. En este tutorial usarás un contenedor de Nginx como ejemplo para recorrer el ciclo de vida completo: descargar una imagen, ejecutar un contenedor, publicar un puerto, inspeccionarlo, entrar en él, detenerlo, eliminarlo y liberar el espacio que dejan imágenes y contenedores antiguos.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS y Docker Engine instalado desde el repositorio oficial, por ejemplo un VPS de CubePath. Si aún no lo tienes, sigue la guía de instalación de Docker en Linux.
- Un usuario no root con privilegios
sudo, añadido al grupodockerpara ejecutardockersinsudo.
AdvertenciaPertenecer al grupo
dockerequivale a tener acceso root en el servidor. Añade solo usuarios de confianza.
Comprueba que el cliente se comunica con el demonio:
docker version --format '{{.Server.Version}}'
28.4.0
Si aparece permission denied while trying to connect to the Docker daemon socket, tu usuario no está en el grupo docker o no has vuelto a iniciar sesión tras añadirlo.
Paso 1: Descargar y listar imágenes
Una imagen es la plantilla de solo lectura a partir de la que se crean los contenedores. Se identifica por nombre y etiqueta (nginx:1.28); si omites la etiqueta, Docker usa latest. Fijar la etiqueta hace que tus despliegues sean reproducibles.
Descarga la imagen de Nginx desde Docker Hub:
docker pull nginx:stable
Lista las imágenes locales:
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx stable 5c8f5ecbd0e2 2 weeks ago 192MB
Para ver cómo se construyó una imagen y el tamaño de cada capa, usa docker image history nginx:stable.
Paso 2: Ejecutar un contenedor
docker run crea un contenedor a partir de una imagen y lo arranca. Ejecuta Nginx en segundo plano (-d), con un nombre fijo (--name) y publicando el puerto 80 del contenedor en el 8080 del servidor (-p):
docker run -d --name web -p 8080:80 nginx:stable
Docker imprime el ID completo del contenedor. Comprueba que responde:
curl -I http://localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.28.0
Estas son las opciones de docker run que más usarás:
| Opción | Uso |
|---|---|
-d | Ejecutar en segundo plano |
--name web | Asignar un nombre en lugar de uno aleatorio |
-p 8080:80 | Publicar el puerto 80 del contenedor en el 8080 del host |
-p 127.0.0.1:8080:80 | Publicar solo en localhost (detrás de un proxy inverso) |
-e CLAVE=valor | Definir una variable de entorno |
-v nombre:/ruta | Montar un volumen para datos persistentes |
--restart unless-stopped | Rearrancar el contenedor tras un fallo o un reinicio del servidor |
--rm | Eliminar el contenedor al terminar (útil para tareas puntuales) |
-it | Sesión interactiva con terminal |
ImportanteLos puertos publicados con
-pse abren mediante reglas de iptables propias de Docker, que no pasan por UFW. Un contenedor publicado en8080:80es accesible desde Internet aunque UFW no permita el puerto 8080. Si el servicio solo debe ser accesible localmente, publícalo en127.0.0.1.
Para una tarea puntual, como abrir una shell en una imagen limpia de Ubuntu que se elimina al salir:
docker run --rm -it ubuntu:24.04 bash
Escribe exit para salir.
Paso 3: Listar contenedores
Muestra los contenedores en ejecución:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f91c2d7b10 nginx:stable "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp web
Añade -a para incluir también los detenidos, y --format para mostrar solo las columnas que te interesan:
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
Puedes filtrar, por ejemplo, los contenedores que han terminado:
docker ps -a --filter status=exited
Paso 4: Ver logs y consumo de recursos
Los contenedores deben escribir sus logs en la salida estándar, y Docker los recoge. Para ver los últimos 20 y seguir los nuevos en tiempo real (sal con Ctrl+C):
docker logs --tail 20 -f web
172.17.0.1 - - [25/Sep/2026:10:14:02 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/8.5.0" "-"
--since 10m limita la salida a los últimos 10 minutos, y -t añade marcas de tiempo.
Para ver el consumo de CPU, memoria y red de todos los contenedores en un instante:
docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a3f91c2d7b10 web 0.00% 9.1MiB / 3.83GiB 0.23% 3.2kB / 1.6kB 0B / 8kB 3
Sin --no-stream, la tabla se actualiza continuamente, como top.
Paso 5: Inspeccionar y ejecutar comandos dentro del contenedor
docker inspect devuelve toda la configuración del contenedor en JSON. Con --format extraes un campo concreto, por ejemplo su IP en la red interna o su política de reinicio:
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' web
172.17.0.2
no
docker exec ejecuta un comando dentro de un contenedor que ya está en marcha. Comprueba la configuración de Nginx:
docker exec web nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Para abrir una shell interactiva (usa sh si la imagen no incluye bash):
docker exec -it web bash
Para copiar archivos entre el servidor y el contenedor, usa docker cp:
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
NotaLos cambios que hagas dentro de un contenedor se pierden al eliminarlo. Para modificar la configuración de forma permanente, monta el archivo desde el host con
-vo crea tu propia imagen con un Dockerfile.
Paso 6: Detener, reiniciar y eliminar contenedores
Detén el contenedor. Docker envía SIGTERM y, si el proceso no termina en 10 segundos, SIGKILL:
docker stop web
Vuelve a arrancarlo con la misma configuración, o reinícialo:
docker start web
docker restart web
Un contenedor creado sin --restart no vuelve a arrancar cuando se reinicia el servidor. Puedes cambiar la política sin recrearlo:
docker update --restart unless-stopped web
Para eliminar el contenedor, primero detenlo y después bórralo (o usa docker rm -f web para hacer las dos cosas):
docker stop web
docker rm web
Comprueba que ya no aparece:
docker ps -a --filter name=web
La salida debe mostrar solo la línea de cabecera. La imagen nginx:stable sigue en el disco; elimínala con docker image rm nginx:stable si ya no la necesitas.
Paso 7: Liberar espacio en disco
Con el tiempo se acumulan contenedores detenidos, imágenes antiguas y caché de compilación. Consulta cuánto ocupa cada tipo de objeto:
docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 6 2 1.41GB 1.02GB (72%)
Containers 3 2 1.1kB 0B (0%)
Local Volumes 2 1 240MB 118MB (49%)
Build Cache 14 0 312MB 312MB
Elimina los contenedores detenidos, las redes sin uso, las imágenes huérfanas (<none>) y la caché de compilación:
docker system prune
Docker pedirá confirmación y mostrará el espacio recuperado. Para borrar también las imágenes que no usa ningún contenedor, añade -a. Los volúmenes nunca se eliminan con este comando salvo que añadas --volumes, y conviene no hacerlo sin revisar antes docker volume ls: ahí suelen estar las bases de datos.
Si prefieres limpiar por tipo:
docker container prune
docker image prune -a
docker builder prune
Solución de problemas
Bind for 0.0.0.0:8080 failed: port is already allocated. Otro contenedor o proceso usa ese puerto. Localízalo con docker ps --filter publish=8080 o sudo ss -ltnp 'sport = :8080' y usa otro puerto del host.
El contenedor se detiene nada más arrancar. Revisa docker ps -a (columna STATUS, con el código de salida) y docker logs nombre. Suele ser un error de configuración o una variable de entorno obligatoria que falta.
Conflict. The container name "/web" is already in use. Existe un contenedor detenido con ese nombre. Elimínalo con docker rm web o elige otro nombre.
Conclusión
Ya conoces los comandos para gestionar el ciclo de vida completo de un contenedor: descargar imágenes, ejecutar contenedores con puertos y políticas de reinicio, revisar sus logs y recursos, entrar en ellos y limpiar lo que ya no usas. Como siguientes pasos, aprende a crear tus propias imágenes con un Dockerfile, a guardar datos persistentes con volúmenes y a definir aplicaciones con varios contenedores mediante Docker Compose.
