15 Docker Hacks & Tips!

Docker is one of the amazing tools I like the most. It's by far the sparkling unicorn of containerization happening in the world of software development and the amazing tool that simplified the configuration of our projects tenfold.

In this post I'll share with you some cool docker hacks and tips. Most of you are probably familiar with many of this commands, but I hope that you find one or two little nuggets from this post;


nice docker ps output

Just pipe docker ps output to less -S so that the table rows are not wrapped:

docker ps -a | less -S

follow the logs

docker logs won't watch the logs by default unless use the -f flag:

docker logs <containerid> -f

Pretty Json from docker inspect

docker inspect spits out a lots of JSON by default. You can just use jq to extract the desired values:

# list IP addresses for all containers connected to 'bridge' network
docker network inspect bridge -f '{{json .Containers}}' | jq '.[] | {cont: .Name, ip: .IPv4Address}

Or you can use the builtin go templating in docker inspect like below:

# is the last run container still running?
docker inspect --format '{{.State.Running}}' $(docker ps -lq)

Docker Command Completion

The Docker CLI syntax is very rich and constantly growing: adding new commands and new options. It’s hard to remember every possible command and option, so having a nice command completion for a terminal is a must have.

The command completion is a kind of terminal plugin, that lets you auto-complete or auto-suggest what to type in next by hitting the tab key. Docker command completion works for commands and options. The Docker team prepared command completion for the docker, docker-machine and docker-compose commands, for both Bash and Zsh shell.

read the official Docker documentation for install instructions: docker engine, docker-compose and docker-machine.

Cleaning Up

After working with Docker for some time, you start accumulating development junk: unused volumes, networks, exited containers and unused images.

Prune: Run them all

prune is a very useful command (also works for volume and network sub-commands), but it is only available for Docker 1.13. So if you’re using older Docker versions, the following commands can help you to replace the prune command.

docker system prune

Remove Dangling Volumes

dangling volumes are volumes not in use by any container. To remove them, combine two commands: first, list volume IDs for dangling volumes and then remove them.

docker volume rm $(docker volume ls -q -f "dangling=true")

Remove Exited Containers

The same principle works here too. First, list the containers (only IDs) you want to remove (with filter) and then remove them (consider rm -f to force remove).

docker rm $(docker ps -q -f "status=exited")

Remove Dangling Images

dangling images are untagged images, that are the leaves of the images tree (not intermediary layers).

docker rmi $(docker images -q -f "dangling=true")


Docker has an internal pool of IPs which it uses for container IP addresses. These are invisible to the outside by default and accessible via a bridge interface.

looking up port mappings

docker run accepts explicit port mappings as parameters or you can specify -P to map all ports automatically. The latter has the advantage of preventing conflicts and looking up the assigned ports can be done as follows:

docker port <containerId> <portNumber>
# or
docker inspect --format '{{.NetworkSettings.Ports}}' <containerId>

container IPs

Each container has it's IP in a private subnet (which is by default). The IP can change with restart but can be looked up should you need it:

docker inspect --format '{{.NetworkSettings.IPAddress}}' <containerId>

docker tries to detect conflicts and will use a different subnet if needed.

taking over the hosts network stack

docker run --net=host allows reusing the network stack of the host. Don't do this :)

Use Another Container’s Network Stack

$ docker run --net=container:<name|id> ...

The new container will attach to the same network interfaces as the other container. The target container can be specified by id or name.

Attachable Overlay Network

Using Docker Engine running in swarm mode, you can create a multi-host overlay network on a manager node. When you create a new swarm service, you can attach it to the previously created overlay network.

Sometimes you need to attach a new Docker container (filled with different networking tools), to an existing overlay network, in order to inspect the network configuration or debug network issues. You can use the docker run command for this, eliminating the need to create a completely new debug service.

Docker 1.13 brings a new option to the docker network create command: attachable. The attachable option enables manual container attachment.

# create an attachable overlay network
 docker network create --driver overlay --attachable mynet
# create net-tools container and attach it to mynet overlay network
docker run -it --rm --net=mynet net-tools sh

Start Containers Automatically

When running a process inside a Docker container, a failure may occur due to multiple reasons. In some cases, you can fix it by re-running the failed container. If you are using a Docker orchestration engine, like Swarm or Kubernetes, the failed service will be restarted automatically.
If not, then you might want to restart the container based on the exit code of the container’s main process, or always restart (regardless the exit code). Docker 1.12 introduced the docker run command: restart for this use case.

Restart Always

Restart the container with a restart policy of always so that if the container exits, Docker will restart it.

docker run --restart=always my_image 

Restart Container on Failure

Restart the container with a restart policy of on-failure and a maximum restart count of 10.

docker run --restart=on-failure:10 my_image 

That's it folks. I hope you learned a thing or two ;)