DEV Community

max
max

Posted on

Docker Commands You Keep Googling (A Cheatsheet for the Rest of Us)

I have mass-deployed Kubernetes clusters. I have written multi-stage Dockerfiles that would make a build engineer weep with joy. And yet, at least once a week, I open a browser tab and type "docker remove all stopped containers" like it is the first time I have ever touched a terminal.

You do it too. We all do it. Docker's CLI is powerful, but it was clearly designed by someone who thought consistency was optional. Some commands use container, some use ps, some have flags that mean entirely different things depending on context.

So here is the article I wish existed three years ago: the Docker commands that experienced developers actually forget, organized by the real-world situations where you need them.


Situation 1: "Something Is Eating All My Disk Space"

You get a disk space alert, or your laptop starts wheezing. Nine times out of ten, Docker is hoarding old images, stopped containers, and orphaned volumes like a digital packrat.

See how much space Docker is consuming:

docker system df
Enter fullscreen mode Exit fullscreen mode

This gives you a breakdown by images, containers, volumes, and build cache. The output will probably horrify you.

The nuclear option -- reclaim everything:

docker system prune -a --volumes
Enter fullscreen mode Exit fullscreen mode

This removes all stopped containers, all networks not used by at least one container, all images without at least one container associated to them, and all volumes not used by at least one container. It is the rm -rf of Docker. Use it on your dev machine, not in production. Obviously.

The surgical approach -- clean up one category at a time:

# Remove stopped containers only
docker container prune

# Remove dangling images (untagged layers)
docker image prune

# Remove ALL unused images, not just dangling ones
docker image prune -a

# Remove unused volumes (careful -- this includes data)
docker volume prune
Enter fullscreen mode Exit fullscreen mode

I run docker system df every Monday morning. It is a surprisingly effective habit for keeping your dev environment from bloating to 50GB of stale Alpine images.


Situation 2: "What Is Actually Running Right Now?"

You are trying to start a service and port 3000 is already taken. Or something is chewing CPU. Time to investigate.

# What containers are running?
docker ps

# What containers exist, including stopped ones?
docker ps -a

# Just give me the IDs (useful for scripting)
docker ps -q

# Real-time resource usage for all running containers
docker stats

# Resource usage for a specific container
docker stats my-container-name
Enter fullscreen mode Exit fullscreen mode

The docker stats command is underrated. It gives you a live-updating table with CPU percentage, memory usage, network I/O, and disk I/O for every running container. It is basically htop for Docker and it is built in. No extra tools needed.

Finding which container grabbed your port:

docker ps --format "table {{.Names}}\t{{.Ports}}" | grep 3000
Enter fullscreen mode Exit fullscreen mode

That --format flag with Go templates is one of Docker's best-kept secrets. You can customize the output of almost any list command instead of parsing walls of text.


Situation 3: "The Container Crashed and I Need to Know Why"

The container started, ran for 3 seconds, and died. The classic.

# View logs for a stopped or running container
docker logs my-container

# Follow logs in real-time (like tail -f)
docker logs -f my-container

# Show only the last 50 lines
docker logs --tail 50 my-container

# Show logs with timestamps
docker logs -t my-container

# Show logs since a specific time
docker logs --since 2h my-container
Enter fullscreen mode Exit fullscreen mode

The --since flag accepts human-readable durations like 2h, 30m, or 10s. That alone saves me from scrolling through 10,000 lines of health check output to find the one error that matters.

If logs are not enough, inspect the container's state:

# See exit code, error message, environment, mounts, everything
docker inspect my-container

# Just the exit code
docker inspect --format='{{.State.ExitCode}}' my-container

# Just the error message
docker inspect --format='{{.State.Error}}' my-container
Enter fullscreen mode Exit fullscreen mode

Exit code 137 means it was killed (usually OOM). Exit code 1 means your application crashed. Exit code 0 means it exited normally, and if that was not intentional, your entrypoint script is probably finishing without starting a long-running process.


Situation 4: "I Need to Get Inside This Container"

Something is wrong and you need to poke around inside the running container.

# Open a bash shell in a running container
docker exec -it my-container bash

# If bash is not installed (common in Alpine images)
docker exec -it my-container sh

# Run a single command without opening a shell
docker exec my-container cat /etc/hosts

# Run as root (when the container runs as non-root)
docker exec -u root -it my-container bash
Enter fullscreen mode Exit fullscreen mode

The -u root trick is one I forget constantly. Many production images run as a non-root user for security, which means apt-get install and similar debugging commands will fail. Switching to root inside the container lets you install curl, netcat, or whatever else you need to debug with.

For containers that already crashed and will not start:

# Create a new container from the same image with a shell
docker run -it --entrypoint sh my-image:latest
Enter fullscreen mode Exit fullscreen mode

Overriding the entrypoint lets you poke around the filesystem even if the normal startup command fails immediately.


Situation 5: "Docker Compose Is Doing Something Weird"

Compose has its own set of commands that overlap with but are not identical to regular Docker commands. This is where my memory fails me most often.

# Start everything in the background
docker compose up -d

# Rebuild images AND start (when you changed a Dockerfile)
docker compose up -d --build

# Start only one specific service
docker compose up -d postgres

# Stop everything but keep volumes
docker compose down

# Stop everything AND destroy volumes (full reset)
docker compose down -v

# View logs for one service
docker compose logs -f api

# Run a one-off command in a service container
docker compose exec api python manage.py migrate

# Run a one-off command in a NEW container
docker compose run --rm api python manage.py shell
Enter fullscreen mode Exit fullscreen mode

The difference between exec and run in Compose trips people up. exec runs a command in an already-running container. run spins up a new container for the command. Use exec for quick commands against your running stack. Use run for tasks that might mess up the running container's state, like database migrations during development.


Situation 6: "I Need to Move an Image Without a Registry"

You are working offline, or you need to transfer an image to a machine that cannot reach your registry. This comes up more often than you would expect.

# Save an image to a tar file
docker save -o myapp.tar myapp:latest

# Load an image from a tar file
docker load -i myapp.tar
Enter fullscreen mode Exit fullscreen mode

Two commands. I Google them every single time. The asymmetry of save/load versus the export/import pair (which works on containers, not images) is exactly the kind of design choice that keeps Stack Overflow in business.


Situation 7: "Network Debugging Between Containers"

Containers cannot talk to each other. The dreaded connection refused or could not resolve host.

# List all Docker networks
docker network ls

# See which containers are on a network
docker network inspect bridge

# Create a custom network (containers can resolve each other by name)
docker network create my-network

# Connect a running container to a network
docker network connect my-network my-container

# Test connectivity from inside a container
docker exec -it my-container ping other-container
Enter fullscreen mode Exit fullscreen mode

Here is the thing that bites everyone at least once: containers on the default bridge network cannot resolve each other by container name. You need a custom network for that. Create one, attach your containers to it, and name resolution works automatically. I have seen senior engineers waste hours on this.


The Commands I Actually Have Memorized

After years of Docker usage, these are the only commands that live permanently in my muscle memory:

  • docker ps -- what is running?
  • docker logs -f -- what is it saying?
  • docker exec -it ... bash -- let me look inside
  • docker compose up -d -- start everything
  • docker compose down -- stop everything

That is five commands. Everything else, I look up. And honestly, that is fine. The goal is not to memorize every flag. The goal is to know what is possible and find the right command quickly when you need it.


Stop Googling the Same Commands

If you are tired of the browser-tab-per-Docker-question workflow, I put together a CLI Cheatsheet Bundle covering Docker, Git, and Linux commands in a single searchable reference. Every command includes the flags you actually use, organized by real-world scenario instead of alphabetical order. It is the kind of thing you keep open in a second monitor and wonder how you worked without it.

Top comments (0)