DevOps
Blog
DevOps7 min

Docker: How to Remove Images, Containers, and Volumes

Matthieu Robin25 mars 2022

Docker: How to Remove Images, Containers, and Volumes

Docker containers and images accumulate quickly. Your system fills with unused images, stopped containers, and orphaned volumes. Disk space gets eaten. Cleanup becomes necessary.

But cleanup can be tricky. Remove the wrong thing, and you break your pipeline. Delete an image someone depends on, and now your deployment fails.

This guide shows you exactly how to clean up Docker safely, from basic commands to production-grade strategies.

Understanding Docker Storage Layers

Before cleanup, understand what Docker stores:

Images : The templates. Each image is immutable and can be used to start multiple containers.

Containers : Running (or stopped) instances of images. Each container has a writable layer on top of the image.

Volumes : Persistent data storage. Separate from images and containers.

Build cache : Intermediate layers from docker build, used to speed up rebuilds.

Cleanup must respect dependencies. You can't delete an image if a container depends on it (even a stopped container).

Removing Docker Images

List Images

First, see what you have:

docker images

Output shows: REPOSITORY, TAG, IMAGE ID, SIZE, and creation date.

To list only dangling images (images with no tags, typically orphaned):

docker images -f "dangling=true"

Remove Specific Images

Remove a single image by name or ID:

docker rmi image_name:tag

Or by image ID:

docker rmi abc123def456

Remove multiple images at once:

docker rmi image1:tag1 image2:tag2 image3:tag3

If a container (even stopped) uses the image, you must stop and remove the container first:

docker rm container_id
docker rmi image_id

To force removal (aggressive, not recommended in production):

docker rmi -f image_id

Remove All Dangling Images

Dangling images are orphaned images left behind by failed builds or updates:

docker image prune

Confirm when prompted. This is safe: dangling images aren't used by anything.

To force without confirmation:

docker image prune -f

Remove all unused images (including those not referenced by any container):

docker image prune -a

This is more aggressive. Use it when you know you want to clean up thoroughly.

Removing Docker Containers

List Containers

View all containers (running and stopped):

docker ps -a

View only running containers:

docker ps

Remove Specific Containers

Remove a stopped container:

docker rm container_id

Remove by name:

docker rm container_name

If the container is still running, stop it first:

docker stop container_id
docker rm container_id

Or combine stop and remove:

docker rm -f container_id

Remove All Stopped Containers

docker container prune

This removes all stopped containers. Running containers are safe.

Confirm when prompted, or force with:

docker container prune -f

Removing Docker Volumes

Volumes persist independently. A volume can outlive the container that created it.

List Volumes

docker volume ls

Find dangling volumes (not in use by any container):

docker volume ls -f "dangling=true"

Remove Specific Volumes

docker volume rm volume_name

Remove by name:

docker volume rm my_app_data

Remove multiple volumes:

docker volume rm vol1 vol2 vol3

Remove All Dangling Volumes

docker volume prune

Confirm when prompted. This removes volumes not used by any container.

Force without confirmation:

docker volume prune -f

Complete Cleanup: Docker System Prune

The nuclear option (but safe for dangling objects):

docker system prune

This removes in one command:

  • All stopped containers
  • All dangling images
  • All dangling volumes
  • All unused networks

Force without confirmation:

docker system prune -f

To also remove all unused images (not just dangling):

docker system prune -a

To remove volumes as well:

docker system prune -a --volumes

This removes:

  • All stopped containers
  • All unused images
  • All unused volumes
  • All unused networks

Use this when you want a complete cleanup. It's safe as long as you have no stopped containers or images you plan to reuse.

Modern Docker Best Practices: Build Optimization

Cleanup becomes less necessary if you build smaller images in the first place.

Multi-Stage Builds

Multi-stage builds dramatically reduce final image size:

# Build stage
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

# Final stage - tiny runtime image
FROM alpine:latest
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]

The builder stage's dependencies (Go compiler, build tools) don't make it into the final image. Final size: often 10-50MB instead of 500MB+.

Dockerfile Best Practices

Order layers from least-changing to most-changing:

FROM ubuntu:22.04
# Base dependencies (rarely change)
RUN apt-get update && apt-get install -y curl jq

# Application dependencies (change occasionally)
COPY requirements.txt .
RUN pip install -r requirements.txt

# Source code (changes frequently)
COPY . .

ENTRYPOINT ["python", "app.py"]

Docker caches layers. If you change source code, Docker only rebuilds from that layer onward. Expensive dependencies are already cached.

Use smaller base images:

Base Image Size
ubuntu:22.04 77 MB
debian:12-slim 28 MB
alpine:latest 7 MB
scratch 0 MB (for static binaries)

Alpine can create images 10x smaller than Ubuntu.

Build Cache Cleanup

The docker build system maintains cache layers. Prune stale build cache:

docker builder prune

Remove all build cache:

docker builder prune -a

Docker Cleanup in Production: Kubernetes/Hikube

If you run Docker in production via Kubernetes (like Hikube.cloud), container management is different.

Container Lifecycle in Kubernetes

Kubernetes automatically removes containers when pods are deleted. You don't manually remove containers.

However, old images accumulate on nodes. Kubernetes has built-in garbage collection:

# Images are collected when:
# - unused for more than 5 minutes (configurable)
# - AND node disk usage > threshold (usually 85%)

Image Cleanup Strategy for Kubernetes

1. Use specific image tags, not latest:

# Good: explicit version
image: myapp:v1.2.3

# Avoid: 'latest' tag masks old images
image: myapp:latest

Specific tags prevent accidental rollbacks to old versions and help with garbage collection.

2. Set appropriate imagePullPolicy:

# For images from your private registry
imagePullPolicy: IfNotPresent  # Use local copy if it exists

# For images you update frequently
imagePullPolicy: Always  # Always fetch fresh version

3. Use image lifecycle hooks for cleanup:

For self-hosted clusters, implement image pruning:

# On each node, periodically:
docker image prune -a --filter "until=72h" -f

This removes images unused for 3+ days.

4. Limit image retention in your registry:

In your container registry (Docker Hub, ECR, Harbor, etc.), set automatic cleanup policies:

# Example Harbor cleanup rule:
Pattern: "*"
Keep the recent: 10  # Keep only last 10 images per repository

Hikube Considerations

If you use Hikube (Hidora's managed Kubernetes):

  • Node storage is managed automatically
  • Garbage collection runs on all nodes
  • Image cleanup respects your deployment requirements
  • No manual intervention needed

Hikube handles image cleanup as part of the managed service, letting you focus on application deployments.

Cleanup Automation

Manual cleanup gets forgotten. Automate it:

Docker System Prune via Cron

Create a cleanup script:

#!/bin/bash
# /usr/local/bin/docker-cleanup.sh
docker system prune -a --volumes -f
echo "Docker cleanup completed at $(date)" >> /var/log/docker-cleanup.log

Make it executable:

chmod +x /usr/local/bin/docker-cleanup.sh

Add to crontab (run weekly):

crontab -e
# Add line:
0 2 * * 0 /usr/local/bin/docker-cleanup.sh

CI/CD Pipeline Cleanup

In your GitHub Actions or GitLab CI, add image cleanup:

# GitHub Actions example
- name: Clean up Docker images
  run: docker image prune -a -f --filter "until=720h"

This runs after deployments, keeping recent images but removing old ones.

Safe Cleanup Checklist

Before running cleanup commands:

  • Verify which images/containers/volumes will be removed
  • List them first (without -f flag)
  • Confirm no running containers depend on those resources
  • Check if any container is stopped but planned for restart
  • Verify volumes contain no important data
  • Have backups of stateful data if needed
  • Run on a non-critical system first
  • Document what you're cleaning up (for audit purposes)

The Bottom Line

Docker cleanup is straightforward once you understand the dependencies:

  1. Remove images you don't use : docker image prune
  2. Remove stopped containers : docker container prune
  3. Remove unused volumes : docker volume prune
  4. Or do everything at once : docker system prune

For production, prefer:

  • Multi-stage builds to keep images small
  • Specific tags instead of 'latest'
  • Kubernetes garbage collection (automatic)
  • Automated cleanup schedules

In managed Kubernetes environments like Hikube, image cleanup is handled automatically, letting your team focus on application development rather than infrastructure maintenance.

Related Reading


Running Docker in production? Hidora's Hikube platform manages image lifecycle, garbage collection, and infrastructure complexity: Managed Kubernetes (Hikube) · Technical Consultation

Does this article resonate?

Hidora can support you on this topic.

Need support?

Let's talk about your project. 30 minutes, no strings attached.