Contenido
Tutorial de limpieza de espacio en disco de Docker: usa prune para liberar espacio
Tras usar Docker durante un tiempo, se acumulan imágenes antiguas, contenedores detenidos, caché de compilación y volúmenes sin uso, que pueden ocupar decenas de GB. En esta sección, primero averiguarás qué consume espacio y luego lo limpiarás de forma segura. Todas las salidas son el resultado de ejecutar los comandos en orden en el mismo entorno.
Comprueba cuánto espacio se usa
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 13 3 2.886GB 2.377GB (82%)
Containers 4 1 98.3kB 16.38kB (16%)
Local Volumes 4 1 40.61MB 40.61MB (100%)
Build Cache 151 0 3.554GB 2.954GB
| Campo | Significado |
|---|---|
TOTAL | Cantidad total |
ACTIVE | Cantidad que usan los contenedores |
SIZE | Espacio ocupado |
RECLAIMABLE | Parte que se puede liberar (sin uso) |
En este entorno hay 13 imágenes y solo 3 están en uso; se pueden recuperar 2.377 GB (82 %). La caché de compilación ocupa aún más: 2.954 GB. Añade -v para ver los detalles de cada imagen, contenedor y volumen: docker system df -v.
Imágenes y contenedores actuales:
$ docker images
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
adminer:latest 74f29c416e14 164MB 43.8MB
alpine:3.23 85fe1e81d675 26.6MB 8.21MB U
hello-node:latest 4063457524bb 245MB 62.2MB
myapp:latest 80cb5c41a286 54.9MB 24.8MB U
mysql:8.4 24989179f588 1.12GB 254MB
nginx:1.30 9bf97bd7714f 242MB 66.5MB
nginx:1.30-alpine 0985e772fb9f 93.7MB 27MB U
node:24-alpine ebfe2f904627 242MB 62MB
postgres:18 74935e722416 650MB 169MB
python:3.14-slim a2b82f3c4855 180MB 45.7MB
redis:8-alpine 3811787313eb 161MB 39.6MB
registry:3 ddf754342cfc 86.9MB 20.7MB
ubuntu:26.04 f144425ff09b 162MB 45.6MB
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc43746c9a29 alpine:3.23 "true" 7 seconds ago Exited (0) 6 seconds ago anon1
7e269fff858b nginx:1.30-alpine "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 80/tcp web
bf5ff318eb63 alpine:3.23 "echo done" 8 seconds ago Exited (0) 7 seconds ago old2
b580380c1fd2 myapp "cat /version.txt" 9 seconds ago Exited (0) 8 seconds ago old1
La U de la columna EXTRA significa In Use (en uso por un contenedor). De los contenedores, solo web está en ejecución; los otros tres ya terminaron (Exited), pero siguen ocupando espacio.
Limpieza por componente
| Comando | Qué elimina |
|---|---|
docker container prune | Todos los contenedores detenidos |
docker image prune | Imágenes colgantes (sin nombre, <none>) |
docker image prune -a | Todas las imágenes que no usa ningún contenedor |
docker builder prune | Caché de compilación |
docker volume prune | Volúmenes anónimos sin uso |
docker volume prune -a | Todos los volúmenes sin uso (incluidos los que tienen nombre) |
docker network prune | Redes personalizadas sin uso |
Cada comando pide confirmación primero (Are you sure you want to continue? [y/N]). Añade -f para omitirla, algo útil en scripts. En los siguientes ejemplos se usa -f.
Eliminar contenedores detenidos
$ docker container prune -f
Deleted Containers:
cc43746c9a2993bda0fb21ab3f161b78603353714f396f86fa8c4b5caf90e25a
bf5ff318eb6331a05239ad7fa39420ff96dc1c8f84b9a3548ce38a0f71a2d63a
b580380c1fd2dc6cca2dc6e009bb877c3eb2df1cf388664a32c8932aff8169fa
Total reclaimed space: 16.38kB
Se eliminaron los tres contenedores detenidos. El contenedor web, que sigue en ejecución, no se ve afectado.
Si usas Docker Desktop, también puedes seleccionar los contenedores en la pantalla Containers y hacer clic en Delete:

Docker 29: las reconstrucciones ya no dejan imágenes <none>
Antes, al reconstruir una imagen varias veces con el mismo nombre (por ejemplo, al ejecutar docker build -t myapp .), las versiones antiguas pasaban a ser «imágenes colgantes» llamadas <none>, que había que eliminar con docker image prune. Prueba en Docker 29:
$ docker build -q --build-arg VERSION=4 -t myapp:latest .
sha256:3f33bc33eb36171280e9b90d904e25c58b2dcf509390536580ffacafc35d4595
$ docker images --filter dangling=true
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
$ docker ps -a --filter name=old1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b580380c1fd2 80cb5c41a286 "cat /version.txt" 26 seconds ago Exited (0) 26 seconds ago old1
Se reconstruyó myapp:latest cuatro veces seguidas, pero --filter dangling=true no devuelve nada. Docker 29 usa por defecto el almacenamiento de imágenes de containerd; cuando una imagen nueva sustituye el nombre, la versión anterior ya no se conserva como <none>. En el caso de los contenedores que aún usan una versión anterior (old1), la columna IMAGE muestra el ID de la imagen.
Por eso, en Docker 29, normalmente hay poco que limpiar con docker image prune (sin -a). Lo que realmente ocupa espacio son las imágenes que no se usan pero aún tienen nombre y la caché de compilación.
Eliminar volúmenes anónimos
$ docker volume ls
DRIVER VOLUME NAME
local 6f6f8ce590c609d4f39b3a676282da88866c8ab20a064132f7746c3cf6717f2c
local 991c93cb6ebeac8570e9c15a89b4225c2bb5e20cbfde2f5bf665fa4dfa23a1aa
local 5396795eeeaab8415295814207a02f75f6ea136d5c34574ba9b16ecdc1b975f9
local cleanup-demo_pgdata
$ docker volume prune -f
Deleted Volumes:
5396795eeeaab8415295814207a02f75f6ea136d5c34574ba9b16ecdc1b975f9
991c93cb6ebeac8570e9c15a89b4225c2bb5e20cbfde2f5bf665fa4dfa23a1aa
6f6f8ce590c609d4f39b3a676282da88866c8ab20a064132f7746c3cf6717f2c
Total reclaimed space: 0B
$ docker volume ls
DRIVER VOLUME NAME
local cleanup-demo_pgdata
- Los tres primeros nombres largos son volúmenes anónimos. Por ejemplo, el Dockerfile de la imagen
postgresdeclaraVOLUME; aunque no montes nada al ejecutar el contenedor, Docker crea automáticamente un volumen anónimo. Este permanece después de eliminar el contenedor (consulta Volúmenes y persistencia de datos). docker volume prunesolo elimina volúmenes anónimos que no se estén usando.cleanup-demo_pgdataes un volumen con nombre del proyecto Compose. Aunque después dedocker compose downya no haya ningún contenedor que lo use, no se ha eliminado.
Eliminar la caché de compilación
$ docker builder du | tail -n 3
Private: 2.996GB
Reclaimable: 3.596GB
Total: 3.596GB
$ docker builder prune -f --filter until=1h | tail -n 3
lv85kuv5xx5h65k941qjoxecz true 98.69kB About an hour ago
kc9tcgw8l1aq9dz1agx096se0 true 870kB About an hour ago
Total: 1.662GB
$ docker builder prune -f | tail -n 3
6os07ml167zpcfh09ushitk2b true 8.285kB 38 minutes ago
7ir7u28j6esk2x7pyu6q38kvk true 74.75MB 38 minutes ago
Total: 1.334GB
docker builder dumuestra que la caché de compilación ocupa 3.596 GB en total, y que todo ese espacio se puede recuperar.--filter until=1hsolo elimina la caché que no se ha usado durante más de 1 hora; liberó 1.662 GB.- Sin filtro, se liberaron otros 1.334 GB.
El coste de eliminar la caché de compilación es que la próxima compilación tendrá que volver a ejecutar todos los pasos (por ejemplo, ejecutar de nuevo npm ci y pip install), así que tardará más. Sin embargo, no afectará a ninguna imagen ni contenedor.
Limpiar todo de una vez: docker system prune
docker system prune
Elimina los contenedores detenidos, las redes sin usar, las imágenes colgantes y la caché de compilación.
docker system prune -a
También elimina todas las imágenes que no se estén usando. La próxima vez que las necesites, tendrás que volver a descargarlas.
Comprobación práctica: ¿--volumes eliminará los datos de la base de datos?
Muchos tutoriales (incluidas versiones anteriores de este tutorial) advierten que docker system prune --volumes también elimina los volúmenes de bases de datos que están «temporalmente sin uso» después de ejecutar docker compose down. Prueba realizada con Docker 29:
$ docker system prune --volumes -f
Deleted Containers:
871f1c408d23dd413804105498b5520385dfafc9e558c02447ed940684bbc483
Deleted Volumes:
e5d0caa972c5323d5a64e9baf5fcb21d66ce7fbb4879bdcc7aa068a14fdbbf76
Total reclaimed space: 8.192kB
$ docker volume ls
DRIVER VOLUME NAME
local cleanup-demo_pgdata
--volumes solo eliminó un volumen anónimo. El volumen con nombre de la base de datos de Compose, cleanup-demo_pgdata, sigue ahí. Desde Docker 23, volume prune y system prune --volumes solo procesan de forma predeterminada los volúmenes anónimos.
El comando que realmente elimina los volúmenes con nombre es docker volume prune -a:
$ docker volume prune -a -f
Deleted Volumes:
cleanup-demo_pgdata
Total reclaimed space: 40.61MB
$ docker volume ls
DRIVER VOLUME NAME
Esta vez se eliminó cleanup-demo_pgdata, y los 40.61 MB de archivos de la base de datos que contenía también desaparecieron y no se pueden recuperar.
Usa
docker volume prune -asolo cuando estés seguro de que no necesitas ninguno de los datos. Para eliminar un volumen específico, es más seguro usardocker volume rm nombre; en un proyecto Compose, usadocker compose down -v, que solo elimina los volúmenes de ese proyecto. Si usas Docker 20.10 o una versión anterior,--volumestodavía elimina los volúmenes con nombre.
Eliminar todas las imágenes que no se estén usando
$ docker image prune -a -f | grep -E "^untagged|^Total"
untagged: nginx:1.30
untagged: node:24-alpine
untagged: postgres:18
untagged: python:3.14-slim
untagged: myapp:latest
untagged: mysql:8.4
untagged: redis:8-alpine
untagged: registry:3
untagged: ubuntu:26.04
untagged: adminer:latest
untagged: alpine:3.23
untagged: hello-node:latest
Total reclaimed space: 2.665GB
$ docker images
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
nginx:1.30-alpine 0985e772fb9f 93.7MB 27MB U
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 1 1 93.66MB 0B (0%)
Containers 1 1 81.92kB 0B (0%)
Local Volumes 0 0 0B 0B
Build Cache 26 0 599.6MB 506.9MB
- Se eliminaron las otras 12 imágenes, excepto
nginx:1.30-alpine, que está usando el contenedorweb; se recuperaron 2.665 GB. - El último comando
docker system dfmuestra que solo quedan 93.66 MB de imágenes.
La próxima vez que ejecutes docker run o construyas una imagen, estas imágenes se descargarán automáticamente de nuevo. Si la red es lenta o la imagen es muy grande (por ejemplo, las imágenes relacionadas con modelos de IA pueden ocupar varios GB), considera usar --filter para eliminar solo las antiguas:
docker image prune -a --filter "until=168h" # Elimina solo las creadas hace más de 7 días
Ten en cuenta que until compara la fecha de creación de la imagen (cuándo la creó su autor), no cuándo la descargaste.
Los registros de los contenedores también ocupan espacio
De forma predeterminada, los registros json-file no tienen límite de tamaño. Prueba con un contenedor que genera salida continuamente (el comando yes produce mucho texto cada segundo):
$ docker run -d --name noisy alpine:3.23 sh -c "timeout 3 yes hello-docker-log; sleep 600"
863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6
$ docker inspect --format "{{.LogPath}}" noisy
/var/lib/docker/containers/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6-json.log
$ du -h $(docker inspect --format "{{.LogPath}}" noisy)
69.3M /var/lib/docker/containers/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6-json.log
$ docker rm -f noisy
noisy
Con solo 3 segundos de salida, el archivo de registro ya ocupa 69.3 MB. En los contenedores que se ejecutan durante mucho tiempo y generan muchos registros, estos archivos pueden alcanzar decenas de GB y no se eliminan automáticamente hasta que se borra el contenedor. Los archivos de registro están en /var/lib/docker/containers/ID_DEL_CONTENEDOR/. En un host Linux, puedes encontrar los archivos de registro más grandes así:
sudo du -h /var/lib/docker/containers/*/*-json.log | sort -h | tail
Configurar límites para un solo contenedor
$ docker run -d --name noisy --log-opt max-size=10m --log-opt max-file=3 alpine:3.23 sh -c "timeout 3 yes hello-docker-log; sleep 600"
fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161
$ ls -lh $(dirname $(docker inspect --format "{{.LogPath}}" noisy)) | grep json
-rw------- 1 root root 3.2K Oct 13 01:07 config.v2.json
-rw-r----- 1 root root 7.2M Oct 13 01:07 fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161-json.log
-rw-r----- 1 root root 9.5M Oct 13 01:07 fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161-json.log.1
-rw-r----- 1 root root 9.5M Oct 13 01:07 fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161-json.log.2
-rw------- 1 root root 1.5K Oct 13 01:07 hostconfig.json
$ docker inspect --format '{{json .HostConfig.LogConfig}}' noisy
{"Type":"json-file","Config":{"max-file":"3","max-size":"10m"}}
$ docker rm -f noisy
noisy
max-size=10m indica un máximo de 10 MB por archivo, y max-file=3 indica que se conservan como máximo 3 archivos. Los antiguos rotan a .1, .2. Con la misma cantidad de salida, los registros ocupan unos 26 MB en total y no seguirán creciendo.
En Compose se escribe así:
services:
app:
image: myapp
logging:
options:
max-size: "10m"
max-file: "3"
Configurar límites globales para los registros
Para aplicar límites a todos los contenedores nuevos: en Linux, edita /etc/docker/daemon.json; en Docker Desktop, edita el mismo JSON en Settings → Docker Engine:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
En Linux, ejecuta sudo systemctl restart docker después de modificar el archivo. En Docker Desktop, pulsa Apply & restart. Solo se aplica a los contenedores que se creen a partir de entonces. Para los contenedores existentes, elimínalos y vuelve a crearlos (en Compose, usa docker compose up -d --force-recreate).
Docker Desktop: el espacio en disco no aumenta después de limpiar
En Windows y macOS, todos los datos de Docker se almacenan en un archivo de disco virtual. Al eliminar imágenes, se libera espacio dentro del disco virtual, pero es posible que el archivo no reduzca su tamaño de inmediato.
- Docker Desktop: en Settings → Resources → Advanced puedes consultar y ajustar el límite del disco virtual. Troubleshoot → Clean / Purge data borra todos los datos de Docker (elimina imágenes, contenedores y Volumes). Úsalo solo como último recurso.
- Windows (WSL 2): si el archivo
.vhdxsigue ocupando mucho espacio, primero ejecutawsl --shutdowny luego comprime el archivo.vhdxcorrespondiente concompact vdiskdediskpart.
Limpieza periódica recomendada
En un servidor, puedes usar cron para ejecutarla una vez por semana:
docker container prune -f --filter "until=168h"
docker image prune -af --filter "until=168h"
docker builder prune -af --filter "until=168h"
Estos comandos no afectan a ningún Volume, así que los datos de la base de datos están seguros. Si además configuras límites globales para los registros, evitarás que el espacio en disco se descontrole.
Resumen
- Primero consulta
docker system dfy luego decide qué limpiar. image prune -aelimina todas las imágenes que no se estén usando;builder prunelimpia la caché de compilación.volume prunesolo elimina Volumes anónimos;-atambién incluye los que tienen nombre.- Configura los límites de registros
max-sizeymax-file.
Ejercicios
Ejercicio 1: Escribe un conjunto de comandos para cron que no afecte a ningún Volume y elimine solo las imágenes y la caché de compilación con más de 7 días.
Respuesta
docker image prune -af --filter "until=168h"
docker builder prune -af --filter "until=168h"
Preguntas frecuentes
¿Es seguro docker system prune?
Sin --volumes, no toca ningún volumen. Desde Docker 23, incluso con --volumes, solo elimina volúmenes anónimos. El comando realmente peligroso es docker volume prune -a.
¿Por qué no hay más espacio en disco en Windows después de limpiar?
Docker Desktop almacena los datos en un archivo de disco virtual. Al eliminar imágenes, el archivo no siempre se reduce de inmediato. Consulta la última sección de este capítulo.
¿Puedo borrar toda la caché de compilación?
Sí. No afecta a ninguna imagen ni contenedor, aunque la próxima compilación será más lenta.
Actualizado 14 de octubre de 2026