Lab 1: The “Junk Generator” (Visualize the problem)
- Check Space:
docker system df(Note the numbers). - Create Junk:
- Run a container:
docker run -d --name junk-app alpine sleep 1000 - Stop it:
docker stop junk-app - Pull an image:
docker pull busybox
- Run a container:
- Check Space Again:
docker system df(Reclaimable space increased). - Clean Up:
docker system prune -f - Verify:
docker ps -a(The stopped container is gone).docker images(Busybox is still there! Why? Because it is not “dangling”, just unused). - Deep Clean:
docker system prune -a -f - Verify:
docker images(Busybox is gone).
Lab 2: The “Orphan Volume” Hunt
- Create Volume:
docker volume create orphan-vol - Check List:
docker volume ls - Prune:
docker volume prune -f - Check List:
docker volume ls(It’s gone).
Lab 1: The “Time Machine” Clean (Using Filters)
Goal: Automate cleanup safely by only deleting old junk.
- Create “Old” and “New” Junk:
- We can’t actually fake time easily, so we will use the logic.
- Pull an image:
docker pull hello-world(This is “New”).
- The Command:
docker system prune -a --filter "until=24h"- Explanation: This command looks for junk created more than 24 hours ago.
- Result: Since you just pulled
hello-world, it is preserved.
- The Comparison:
- Now run:
docker system prune -a(Without filter). - Result:
hello-worldgets deleted because it is not currently running. - Lesson: Use
until=24hin your cron jobs (automated scripts) to avoid deleting images you just built but haven’t started yet.
- Now run:
Lab 2: The “Dependency Hell” (Why can’t I delete this?)
Goal: Understand image layers and why Docker sometimes refuses to delete.
- Create Base Image:
- Create file
Dockerfile.base:FROM alpine - Build:
docker build -t my-base:v1 -f Dockerfile.base .
- Create file
- Create Child Image:
- Create file
Dockerfile.child:FROM my-base:v1 - Build:
docker build -t my-child:v1 -f Dockerfile.child .
- Create file
- Attempt Deletion:
docker rmi my-base:v1
- Result:
- Error:
image is being used by ... - Why? Docker protects you. If you delete the base, the child breaks.
- Error:
- Fix:
- Delete the child first:
docker rmi my-child:v1 - Now delete the base:
docker rmi my-base:v1 - Success!
- Delete the child first:
Lab 3: The “Silent Disk Killer” (Log Explosion)
Goal: Simulate a container filling the disk with logs and fix it without restarting.
- Create the Problem:
- Run a container that spams logs endlessly.
docker run -d --name spammer alpine sh -c "while true; do echo 'CRITICAL ERROR: Disk is filling up fast...'; sleep 0.01; done"
- Observe the Growth:
- Let it run for 30 seconds.
- Find the log file:
LOG_PATH=$(docker inspect --format='{{.LogPath}}' spammer) - Check size:
ls -lh $LOG_PATH(It will grow by MBs every second).
- Attempt Prune (Fail):
- Run
docker system prune. - Result: Does nothing. The container is running, so logs are “active.”
- Run
- The Architect Fix (Truncate):
- You cannot delete the file while open, but you can empty it.
truncate -s 0 $LOG_PATH- Check size again:
ls -lh $LOG_PATH(It is now 0 bytes!).
- The Permanent Fix (Log Rotation):
- Stop the spammer:
docker rm -f spammer - Run with limits:
docker run -d --log-opt max-size=1m --log-opt max-file=3 alpine ... - Result: Docker will now automatically delete old logs when they reach 1MB.
- Stop the spammer: