Efficient Docker image and container management is fundamental to maintaining a healthy container environment. Docker images accumulate on hosts — old base images, build cache layers, and unused intermediate images can consume tens of gigabytes of disk space if not managed regularly. Understanding the Docker image layer model is key: images consist of read-only layers stacked on each other, and each RUN, COPY, and ADD instruction in a Dockerfile creates a new layer. Containers add a thin writable layer on top of the image layers. This guide covers the essential Docker image and container management commands on RHEL 9: listing, inspecting, tagging, pushing/pulling images, managing container lifecycle, and cleaning up disk space.
Prerequisites
- Docker Engine installed on RHEL 9
Step 1 — Image Management
# List all local images
docker images
docker images --format "table {{.Repository}}t{{.Tag}}t{{.Size}}"
# Pull an image
docker pull nginx:1.27-alpine
# Tag an image for a registry
docker tag nginx:1.27-alpine registry.example.com/myteam/nginx:1.27-alpine
# Push to registry
docker push registry.example.com/myteam/nginx:1.27-alpine
# Inspect image metadata and layers
docker inspect nginx:alpine
docker history nginx:alpine # Show each layer and its size
# Search Docker Hub
docker search postgres
Step 2 — Container Lifecycle Management
# Create (without starting)
docker create --name mycontainer nginx:alpine
# Start/stop/restart
docker start mycontainer
docker stop mycontainer
docker restart mycontainer
# Run one-off command in a new container (removed after exit)
docker run --rm alpine echo "Hello from container"
# Interactive container for debugging
docker run -it --rm alpine /bin/sh
# List containers (running and stopped)
docker ps # Running only
docker ps -a # All containers
docker ps -a --format "table {{.Names}}t{{.Status}}t{{.Image}}"
Step 3 — Container Inspection and Debugging
# View container logs
docker logs mycontainer
docker logs -f mycontainer # Follow
docker logs --tail 100 mycontainer
# Execute a command inside a running container
docker exec -it mycontainer /bin/sh
docker exec mycontainer cat /etc/nginx/nginx.conf
# Copy files to/from containers
docker cp mycontainer:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./config.conf mycontainer:/etc/nginx/nginx.conf
# View resource usage
docker stats # Real-time CPU/memory/network stats
docker stats --no-stream # One-time snapshot
Step 4 — Clean Up Disk Space
# Check Docker disk usage
docker system df
# Remove stopped containers
docker container prune -f
# Remove unused images (not referenced by any container)
docker image prune -f
# Remove all unused images (including tagged ones with no running containers)
docker image prune -a -f
# Remove unused volumes
docker volume prune -f
# Remove everything unused at once (containers, networks, images, build cache)
docker system prune -f
docker system prune -a -f # Also removes all unused images (more aggressive)
Step 5 — Set Resource Limits on Containers
# Limit CPU and memory (prevent a single container from consuming all resources)
docker run -d
--name myapp
--memory="512m" # Maximum memory
--memory-swap="512m" # Disable swap (same as memory = swap disabled)
--cpus="1.5" # Use at most 1.5 CPU cores
myapp:latest
# Verify limits
docker inspect myapp | grep -E "Memory|Cpu"
Conclusion
Regular Docker image and container cleanup on RHEL 9 prevents disk exhaustion, which is a common operational issue on long-running Docker hosts. Implement a scheduled docker system prune -f in cron (weekly is typical) to remove stopped containers and dangling images automatically. Setting memory limits on all containers is equally important — without limits, a memory leak in any container can consume all available RAM and cause the kernel’s OOM killer to terminate other containers or system processes.
Next steps: How to Build Docker Images on RHEL 9, How to Set Up a Private Docker Registry on RHEL 9, and How to Configure Docker Networking on RHEL 9.