Lo que un contenedor escribe dentro de sí se va con él: al borrarlo (o al crearlo de nuevo con otra versión de la imagen), sus archivos desaparecen. Para los datos que importan, Docker tiene los volúmenes: directorios que viven aparte de los contenedores y que se montan dentro de ellos. Y para trabajar con archivos del propio servidor, se monta una carpeta de la máquina.
Los ejercicios pasan en el servidor de pruebas de la biblioteca municipal: el catálogo, los préstamos y la web, cada uno con sus datos.
Sin volumen, los datos se van
Un contenedor que escribe en /tmp/x lo escribe en su capa: docker rm y adiós. Por eso la
regla es sencilla: lo que tenga que sobrevivir al contenedor, en un volumen.
Volúmenes con nombre
tecnico@srv-pruebas:~$ docker volume create catalogo catalogo
tecnico@srv-pruebas:~$ docker volume ls DRIVER VOLUME NAME local catalogo
Con -v nombre:/ruta el volumen se monta en esa ruta del contenedor (y si no existe, se crea).
Lo que se escribe ahí queda en el volumen, aunque el contenedor sea de usar y tirar (--rm):
tecnico@srv-pruebas:~$ docker run --rm -v catalogo:/datos alpine sh -c 'echo "El Quijote" > /datos/libros.txt'
tecnico@srv-pruebas:~$ docker run --rm -v catalogo:/datos alpine cat /datos/libros.txt El Quijote
--mount type=volume,src=catalogo,dst=/datos hace lo mismo, con más letras y sin sorpresas: si
algo no cuadra, da error en lugar de crear lo que falta.
Ojo con el nombre: si está mal escrito, -v no da error, crea otro volumen (vacío) y monta ese. Y
los montajes se deciden al crear el contenedor: para añadirle o cambiarle uno, se borra y se crea
otra vez con su -v. Lo que hay en el volumen no se toca: no se va con el contenedor.
Ejercicio
Que no se pierdan
Las fichas de la biblioteca se perdían cada vez que alguien borraba su contenedor. Arranca el contenedor fichas (con alpine:3.20, haciendo sleep 3600) con un volumen llamado fichas montado en /datos, y escribe en él el archivo /datos/libro.txt.
Preparando la máquina…
¿Dónde están los datos?
Un volumen es un directorio de la máquina, dentro de /var/lib/docker (que solo ve root).
docker volume inspect lo dice en Mountpoint:
tecnico@srv-pruebas:~$ docker volume inspect catalogo [ { "CreatedAt": "2026-10-02T19:08:39Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/catalogo/_data", "Name": "catalogo", "Options": null, "Scope": "local" } ]
tecnico@srv-pruebas:~$ sudo ls -l /var/lib/docker/volumes/catalogo/_data total 4 -rw-r--r-- 1 root root 11 Oct 2 19:08 libros.txt
Ejercicio
¿Dónde están los datos?
Para la copia de seguridad del servidor hace falta saber dónde guarda Docker los datos del volumen catalogo. Averígualo y apunta esa ruta en ~/donde.txt.
Preparando la máquina…
Carpetas de la máquina
Con una ruta (que empiece por / o por ./) en lugar de un nombre, -v monta esa carpeta del
servidor. Lo que se cambie en ella se ve dentro al momento, sin reiniciar nada:
tecnico@srv-pruebas:~$ docker run -d --name web -p 8080:80 -v $HOME/web:/usr/share/nginx/html nginx:1.27-alpine
tecnico@srv-pruebas:~$ echo '<h1>Biblioteca municipal</h1>' > web/index.html
tecnico@srv-pruebas:~$ curl -s localhost:8080 <h1>Biblioteca municipal</h1>
Con :ro al final, el contenedor solo puede leerla:
tecnico@srv-pruebas:~$ docker run --rm -v $HOME/web:/w:ro alpine sh -c 'echo x > /w/y' sh: can't create /w/y: Read-only file system
Ejercicio
Lo de la carpeta, al momento
La web de la biblioteca se edita en /srv/biblioteca/web del servidor. Arranca el contenedor web (con nginx:1.27-alpine) publicando su 80 en el 8080 y con esa carpeta montada donde nginx tiene sus páginas (/usr/share/nginx/html), y pídela desde la máquina.
Preparando la máquina…
Copias y restauraciones
Para copiar un volumen no hace falta tocar /var/lib/docker: un contenedor de usar y tirar monta
el volumen y una carpeta de la máquina, y tar hace el resto.
tecnico@srv-pruebas:~$ docker run --rm -v catalogo:/datos -v $HOME:/copia alpine tar czf /copia/catalogo.tar.gz -C /datos .
tecnico@srv-pruebas:~$ tar tzf catalogo.tar.gz ./ ./libros.txt ./nuevo.txt
Restaurar es lo mismo al revés, en el volumen que toque:
tecnico@srv-pruebas:~$ docker run --rm -v catalogo-ayer:/datos -v $HOME:/copia alpine tar xzf /copia/catalogo.tar.gz -C /datos
Para un archivo suelto está docker cp, en los dos sentidos:
tecnico@srv-pruebas:~$ docker cp lector:/datos/libros.txt . Successfully copied 2.05kB to /home/tecnico/.
Ejercicio
La copia de la noche
Los préstamos están en el volumen prestamos. Haz una copia de lo que tiene en /srv/copias/prestamos.tar.gz, con un contenedor de usar y tirar (alpine:3.20 y tar).
Preparando la máquina…
Ejercicio
Volver a la de ayer
La copia de ayer del catálogo está en /srv/copias/catalogo-ayer.tar.gz. Pon lo que tiene en un volumen nuevo llamado catalogo, con un contenedor de usar y tirar.
Preparando la máquina…
Los que sobran
Algunas imágenes (postgres, por ejemplo) piden un volumen para sus datos (VOLUME en su
Dockerfile). Si no le das uno, Docker crea uno anónimo, con un nombre de 64 cifras, que se
queda ahí cuando borras el contenedor:
tecnico@srv-pruebas:~$ docker volume ls -f dangling=true DRIVER VOLUME NAME local catalogo-ayer local f20ac252ce6245e5ebb9f0a83e97d63639df338e26c7e22ad67030f5856bb47b local prestamos
dangling=true son los que no usa ningún contenedor (ni parado). docker volume prune borra los
anónimos que sobran; con -a, todos los que no se usan, también los que tienen nombre.
tecnico@srv-pruebas:~$ docker volume prune -f Deleted Volumes: f20ac252ce6245e5ebb9f0a83e97d63639df338e26c7e22ad67030f5856bb47b Total reclaimed space: 23.33MB
Un volumen que usa algún contenedor no se puede borrar (volume is in use): primero el
contenedor. Y docker rm -v borra, con el contenedor, sus volúmenes anónimos.
Ejercicio
Los que sobran
Las pruebas de la semana han dejado volúmenes anónimos que ya no usa nadie. Míralos y bórralos, sin tocar los que tienen nombre (fichas y prestamos son de verdad, aunque ahora no los use ningún contenedor).
Preparando la máquina…
Resumen
| Orden | Para qué |
|---|---|
docker volume create nombre |
un volumen con nombre |
docker run -v nombre:/ruta … |
montarlo (y crearlo si no está) |
docker run -v /carpeta:/ruta[:ro] … |
montar una carpeta de la máquina |
docker volume ls [-f dangling=true] |
los que hay (los que no usa nadie) |
docker volume inspect nombre |
dónde están sus datos (Mountpoint) |
docker run --rm -v vol:/datos -v $PWD:/copia alpine tar czf … |
copiar un volumen |
docker cp contenedor:/ruta . |
sacar (o meter) un archivo |
docker volume rm · docker volume prune [-a] |
borrar |