In this post, I’ve decided to share with you some useful commands and tools I frequently use when working with awesome Docker technology. There is no particular order or “coolness level” for every “hack.” I will simply present the use case and how the specific command or tool has helped me with my work. Read these great hacks and make sure to check out the great hack of all – Codefresh – the best CI for Docker out there.
Cleaning Up
After working with Docker for some time, you start accumulating development junk: unused volumes, networks, exited containers and unused images.
One Command to “Rule Them All”
$ docker system prune
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.
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")
Autoremove Interactive Containers
When you run a new interactive container and want to avoid typing rm
command after it exits, use --rm
option. Then when you exit from the created container, it will be automatically destroyed.
$ docker run -it --rm alpine sh
Inspect Docker Resources
jq – jq
is a lightweight and flexible command-line JSON
processor. It is like sed
for JSON data. You can use it to slice and filter, and map and transform structured data with the same ease that sed
, awk
, grep
and friends let you play with text.
docker info
and docker inspect
commands can produce output in JSON
format. Combine these commands with jq
processor.
Pretty JSON and jq Processing
# show whole Docker info $ docker info --format "{{json .}}" | jq . # show Plugins only $ docker info --format "{{json .Plugins}}" | jq . # list IP addresses for all containers connected to 'bridge' network $ docker network inspect bridge -f '{{json .Containers}}' | jq '.[] | {cont: .Name, ip: .IPv4Address}'
Watching Containers Lifecycle
Sometimes you want to see containers being activated and exited when you run certain docker commands or try different restart policies. Thewatch
command combined with docker ps
can be pretty useful here. I found that the docker stats
command (even with --format
option) is not useful for this because it doesn’t allow you to see the same information as you can with the docker ps
command.
Display a Table with ‘ID Image Status’ for Active Containers and Refresh it Every 2 Seconds
$ watch -n 2 'docker ps --format "table {{.ID}}t {{.Image}}t {{.Status}}"'
Enter into Host/Container Namespace
Sometimes you want to connect to the Docker host. The ssh
command is the default option, but this option may not be available, due to security settings, firewall rules or other undocumented issues (just try googling “how to ssh
into Docker for Mac VM” to see what I mean).
nsenter
, by Jérôme Petazzoni, is a small and very useful tool for this use cases. The nsenter
command allows you to enter
into n
ames
paces. I like to use the minimalistic (580 kB
) walkerlee/nsenter Docker image.
Enter into Docker Host
You can use --pid=host
to enter into Docker host namespaces.
# get a shell into Docker host $ docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n sh
Enter into ANY Container
It’s also possible to enter into any container with nsenter
and --pid=container:[id OR name]
. But in most cases, it’s better to use the standard docker exec
command. The main difference is that nsenter
doesn’t enter the cgroups, and therefore evades resource limitations (which can be useful for debugging).
# get a shell into 'redis' container namespace $ docker run --rm -it --privileged --pid=container:redis walkerlee/nsenter -t 1 -m -u -i -n sh
Heredoc Docker Container
Sometimes you want to get some tool as a Docker image, but you do not want to search for a suitable image or to create a new Dockerfile
(no need to keep it for future use, for example). Sometimes storing Docker image definition in a file looks like an overkill – you need to decide how you edit, store and share this Dockerfile. Sometimes it’s better to have a single line command, that you can copy, share, embed into a shell script or create special command alias.
So, when you want to create a new ad-hoc container with a single command, try a Heredoc approach.
Create Alpine Based Container with ‘htop’ Tool
$ docker build -t htop - << EOF FROM alpine RUN apk --no-cache add htop EOF
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.
If you are using Mac and Homebrew, then installing the Docker commands completion is pretty straight forward.
# Tap homebrew/completion to gain access to these $ brew tap homebrew/completions # Install completions for docker suite $ brew install docker-completion $ brew install docker-compose-completion $ brew install docker-machine-completion
If you’re not using Mac, read the official Docker documentation for install instructions: docker engine, docker-compose and docker-machine.
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 redis
container with a restart policy of always so that if the container exits, Docker will restart it.
$ docker run --restart=always redis
Restart Container on Failure
Restart the redis
container with a restart policy of on-failure and a maximum restart count of 10
.
$ docker run --restart=on-failure:10 redis
Network Tricks
There are times when you might want to create a new container and connect it to an existing network stack. This might be the Docker host network or another container’s network. This is helpful when debugging and auditing network issues.
The docker run --network/net
option allows you to do this.
Use the Docker Host Network Stack
$ docker run --net=host ...
The new container will attach to the same network interfaces as the Docker host.
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
I hope you find this post useful. If you have more tricks on your own, please leave them in the comments box!
Pssst, secret last hack, check out Codefresh for Docker native CI/CD, it’s designed specifically for Docker and can handle the entire container driven lifecycle.