Docker General Tips for Linux
A grab-bag of Docker tips for Linux that save time, disk space and sanity: running Docker without sudo, clearing out cache, controlling image pulls in Compose, reading logs, and a handful of everyd...
A grab-bag of Docker tips for Linux that save time, disk space and sanity: running Docker without sudo, clearing out cache, controlling image pulls in Compose, reading logs, and a handful of everyday commands worth keeping close.
Run Docker without sudo
Add your user to the docker group and you never have to type sudo in front of a Docker command again, which saves your sanity just a little bit.
# Add the docker group. It probably already exists and will throw an error, but hey, live dangerously...
sudo groupadd docker
# Add your logged-in user to the docker group
sudo gpasswd -a $USER docker
# Switch your current shell to the docker group (or log out and back in, but ain't nobody got time for that)
newgrp docker
# Quick test - should list containers with no permission error
docker ps -a
A few things worth knowing:
newgrp dockeronly applies to the current terminal. Other open terminals and your desktop session pick it up after a log out/in or reboot.- Check it worked with
groupsorid -nG-dockershould be in the list. - Still getting
permission denied ... /var/run/docker.sock? Make sure the daemon is running withsudo systemctl enable --now docker. - Security caveat: the
dockergroup is effectively root on that machine, because anyone in it can mount the host filesystem into a container. Only add users you would trust withsudo. On shared or production servers, consider rootless mode instead.
Clear Docker cache and reclaim disk space
Use the narrowest prune command that removes what you no longer need. Docker keeps build cache, containers, images and volumes on disk, and over time they eat a lot of space, locally and in CI.
Start by seeing what is actually using the space:
docker system df # summary by type
docker system df -v # detailed, per image/container/volume
Then pick a command:
| Goal | Command | What it removes |
|---|---|---|
| Clear the selected builder's unused build cache | docker buildx prune | Unused build-cache records for the selected builder |
| Clear unused Docker data | docker system prune | Stopped containers, unused networks, dangling images and unused build cache |
| Clear all unused data, including images and anonymous volumes | docker system prune -a --volumes | Everything above, plus all unused images and anonymous volumes not used by a container |
Or target one type at a time:
docker container prune # stopped containers
docker image prune # dangling (untagged) images
docker image prune -a # every image not used by a container
docker volume prune # unused anonymous volumes (add -a for named ones too)
docker network prune # unused networks
docker builder prune -a # all build cache
Handy extras:
- Skip the confirmation prompt with
-f, e.g.docker system prune -f- useful in cron jobs and CI. - Only prune old stuff:
docker image prune -a --filter "until=168h"keeps anything from the last 7 days. - Volumes hold your data (databases!). Run
docker volume lsand think twice before--volumesordocker volume prune -a.
Control image pulls with pull_policy in Compose
Set pull_policy on a service to decide when Compose pulls its image; it has been part of the Compose spec since 2020-05-07.
services:
my-service:
image: someimage/somewhere
pull_policy: always
| Value | Behaviour |
|---|---|
always | Always pull the image, even if it is cached |
never | Never pull; fails if the image is not already local |
missing | Pull only if the image is not cached (the default) |
build | Always build or rebuild the image from build: |
Newer Compose versions also accept daily, weekly and every_<duration> (e.g. every_12h) to re-check for updates on a schedule. See the Compose spec for details.
To update a stack by hand without touching the file:
docker compose pull && docker compose up -d
Read container logs
Grep logs by redirecting stderr into stdout first (2>&1), because many containers write their logs to stderr and a plain pipe misses them.
# Search an nginx container's logs for requests from 127.x addresses
docker logs nginx 2>&1 | grep "127."
# Show the last 10 lines and keep streaming new ones (Ctrl+C to stop)
docker logs nginx --tail=10 --follow
More useful flags:
docker logs nginx --since 30m # only the last 30 minutes
docker logs nginx --since 2026-10-23T08:00:00 --until 2026-10-23T09:00:00
docker logs nginx -t # prefix every line with a timestamp
docker compose logs -f --tail=50 web # follow one service in a Compose stack
docker compose logs -f # follow every service, colour-coded
Logs grow forever by default with the json-file driver. Cap them per service in Compose:
services:
web:
image: nginx
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
Or set it globally in /etc/docker/daemon.json, then sudo systemctl restart docker (applies to newly created containers only):
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
Other handy tricks
These cover the day-to-day jobs that come up on almost every Docker box.
Get a shell inside a running container
docker exec -it nginx bash # use sh if bash isn't installed (Alpine images)
docker exec -it -u root nginx sh # as root
See what's running and what it's costing you
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" # tidy ps output
docker stats # live CPU / RAM / network per container
docker top nginx # processes inside a container
Inspect a container
docker inspect nginx # everything, as JSON
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx # just the IP
docker inspect -f '{{.State.Health.Status}}' nginx # health check status
Copy files in and out
docker cp nginx:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./nginx.conf nginx:/etc/nginx/nginx.conf
Make containers survive reboots
docker run -d --restart unless-stopped --name nginx nginx
docker update --restart unless-stopped nginx # change an existing container
unless-stopped restarts after a crash or reboot, but stays down if you stopped it yourself. In Compose, add restart: unless-stopped to the service.
Compose everyday commands
docker compose up -d # start in the background
docker compose down # stop and remove containers + network (volumes kept)
docker compose ps # status of the stack
docker compose restart web # restart one service
docker compose exec web sh # shell into a service
docker compose config # validate and print the merged config
Quality-of-life bits
- Use
docker compose(with a space, Compose v2 plugin), not the olddocker-composePython tool, which is end-of-life. - Stop everything at once:
docker stop $(docker ps -q). - Add a
.dockerignore(e.g..git,node_modules,*.log) so builds are faster and images smaller. - Pin image tags (
postgres:16) instead oflatest, so an update never surprises you mid-week.
Quick reference
| I want to... | Command |
|---|---|
| Use Docker without sudo | sudo gpasswd -a $USER docker && newgrp docker |
| See what's using disk space | docker system df |
| Clean up safely | docker system prune |
| Clean up everything unused | docker system prune -a --volumes |
| Always pull the latest image in Compose | pull_policy: always |
| Grep a container's logs | docker logs <name> 2>&1 | grep "text" |
| Tail and follow logs | docker logs <name> --tail=10 --follow |
| Get a shell in a container | docker exec -it <name> sh |
| Watch resource usage | docker stats |
| Restart after reboots | docker update --restart unless-stopped <name> |
| Update a Compose stack | docker compose pull && docker compose up -d |
- #Docker
- #Linux