For the last few months, I have been working with Docker extensively. In this article and the one that follows, I want to share the most used Docker commands that every Docker user must know.

Originally, the intent was to have a single list of all the commands. However, I felt like each command must have a basic description and I must talk about the most common uses of each command. So, I will split the post into two parts.

Let’s get started.

1. docker info

The very first thing anyone generally does after installing any application is to check its version. Docker provides two commands in that respect: docker version and docker info.

docker version gives you details like the Docker API version, operating system, underlying architecture and a few more. However, docker info gives you a lot more system-wide information regarding the Docker installation. Here is a sample output of the docker info command:

$ docker info
Containers: 6
 Running: 4
 Paused: 0
 Stopped: 2
Images: 9
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
 Volume: local
 Network: bridge host ipvlan macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version:  (expected: 468a545b9edcd5932818eb9de8e72413e616e86e)
runc version: N/A (expected: 69663f0bd4b60df09991c08812a60108003fa340)
init version: v0.18.0 (expected: fec3683b971d9c3ef73f284f176672c44b448662)
Security Options:
  Profile: default
Kernel Version: 4.15.0-43-generic
Operating System: Ubuntu 16.04.4 LTS
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 15.53GiB
Name: server-04
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: quickdevnotes
Experimental: true
Insecure Registries:
Live Restore Enabled: false

You get details like the storage driver, containers, your registries and registry mirrors and lot more. While this is great, sometimes it can be overwhelming.

docker info allows you to format the output as you want, by accepting the --format or -f option. Here are a few examples to apply the format option:

// get the response in json format
$ docker info --format '{{json .}}'

// get the response in json format and parse it through 'jq'
$ docker info --format '{{json .}}' | jq

// get a particular part of the information
$ docker info -f '{{.Plugins}}'
$ docker info -f '{{.Plugins.Network}}'

2. docker search

I must admit! I’m a bit lazy when it comes to switching between application windows, especially for simple things. If you’re someone like me, I’m sure you will like docker search.

Generally, we switch to a web browser, go to DockerHub and then search for an image. Instead of doing all that, docker search allows you to search DockerHub for images using a simple command, from your terminal.

Here is an example:

$ docker search nginx --format "table {{.Name}} \t {{.StarCount}} \t {{.IsOfficial}} \t {{.IsAutomated}}"
NAME                                STARS               OFFICIAL            AUTOMATED
nginx                               11727               [OK]
jwilder/nginx-proxy                 1628                                    [OK]
linuxserver/nginx                   70
bitnami/nginx                       69                                      [OK]
tiangolo/nginx-rtmp                 49                                      [OK]
nginx/nginx-ingress                 20
nginxdemos/hello                    18                                      [OK]
blacklabelops/nginx                 12                                      [OK]
webdevops/nginx                     8                                       [OK]
1science/nginx                      4                                       [OK]
mailu/nginx                         3                                       [OK]
travix/nginx                        2                                       [OK]
wodby/nginx                         0                                       [OK]

In the above example, I’m using the --format flag. Please feel free to remove the formatting and do a search.

3. docker login/logout

As you continue to work with Docker, the time will come when you want to secure your Docker images in a Docker registry. To pull or push an image from a private registry, the Docker engine requires credentials for authentication.

You can log in using the following command:

$ docker login
Username: quickdevnotes
Login Succeeded

Once the login is successful, the auth credentials are stored in the ~/.docker/config.json file in encrypted form.

$ cat ~/.docker/config.json
    "auths": {
        "": {}

You may also pass the username and password within the command using the flags -u and -p respectively. However, it is not recommended.

You can log out using the docker logout command that also removes the user credentials from the config file.

4. docker build

Any application can be run as a container if it has a Docker image. A Docker image is the building block for containers. To build an image, we write a Dockerfile. At the highest level, a Dockerfile is a set of commands that are executed to build a Docker image.

The Dockerfile is passed to docker build command as an argument. The engine reads through the file and builds an image, as each command contributes a layer. Here is a sample Dockerfile and the command used to build an image out of it:

FROM busybox
COPY data.txt .
CMD cat data.txt

$ docker build -t web-app .

The . in the end, is very important. It is the context that is passed to the Docker engine concerning the Dockerfile.

However, you can pass the context to the docker build command, as the need may arise. In the following example, we are executing the build command from a directory that does not contain the Dockerfile:

$ docker build -t web-app -f ../var/Dockerfile ../var

Here we provide the path to Dockerfile and the context, which is its directory. And yes, you can name your Dockerfile anything you want. It’s not a mandate to name it as Dockerfile. However, you will then have to use the -f option while building an image.

5. docker tag

Tags are life saviors. Applying the right tags to your Docker images is very essential. The default tag for an image is latest. You can add as many tags as you want.

To tag an image use the docker tag command, as shown below:

$ docker tag busybox busybox:v1
$ docker tag busybox quickdevnotes/busybox-custom

I highly recommend that all your Docker images must have tags other than latest at any point in time. This will make your rollouts and rollbacks much faster and efficient.

6. docker images

It’s always good to keep a check of all the Docker images available at your local machine. It is helpful when you want to free some space.
docker images provides you a list of docker images available locally. Here is an example:

$ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
confluentinc/cp-kafka       latest              aa982a32e7c4        5 months ago        569MB
confluentinc/cp-zookeeper   latest              16ce4511d84e        5 months ago        569MB
wurstmeister/zookeeper      latest              3f43f72cb283        6 months ago        510MB
wurstmeister/kafka          2.11-2.0.0          568143d73a6b        9 months ago        339MB
sheepkiller/kafka-manager   latest              4e4a8c5dabab        15 months ago       463MB

You may also use the --format option to get rid of unwanted information. Here is an example:

$ docker images --format "table {{.Repository}} \t {{.Tag}} \t {{.Size}}"
REPOSITORY                    TAG                 SIZE
confluentinc/cp-kafka         latest              569MB
confluentinc/cp-zookeeper     latest              569MB
wurstmeister/zookeeper        latest              510MB
wurstmeister/kafka            2.11-2.0.0          339MB
sheepkiller/kafka-manager     latest              463MB

In addition to --format, there are a few other options as well. You can get them by using the docker images --help command.

7. docker inspect

As the name suggests, docker inspect provides detailed information on resources or constructs controlled by Docker. By default, the command returns the results in a JSON array.

Here is an example:

$ docker inspect busybox
        "Id": "sha256:db8ee88ad75f6bdc74663f4992a185e2722fa29573abcc1a19186cc5ec09dceb",
        "RepoTags": [
        "RepoDigests": [
        "Parent": "",
        "Comment": "",
        "Created": "2019-07-18T21:20:21.810680491Z",
        "Container": "d6bc4fd488f31e0e72c06b4f268e475ff54ca7c17bc3a867da366aa581576057",
        "ContainerConfig": {
            "Hostname": "d6bc4fd488f3",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
            "Cmd": [
                "#(nop) ",
                "CMD [\"sh\"]"
            "ArgsEscaped": true,
            "Image": "sha256:94660471d35df73633987b367900b00d5eeda0ffdd3a096db092926bb6de3ba4",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        "DockerVersion": "18.06.1-ce",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
            "Cmd": [
            "ArgsEscaped": true,
            "Image": "sha256:94660471d35df73633987b367900b00d5eeda0ffdd3a096db092926bb6de3ba4",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 1223894,
        "VirtualSize": 1223894,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/30d975af37c6654d4fe99d938c5dc62a06c9930c75d16ebd0f8423448101d9ca/merged",
                "UpperDir": "/var/lib/docker/overlay2/30d975af37c6654d4fe99d938c5dc62a06c9930c75d16ebd0f8423448101d9ca/diff",
                "WorkDir": "/var/lib/docker/overlay2/30d975af37c6654d4fe99d938c5dc62a06c9930c75d16ebd0f8423448101d9ca/work"
            "Name": "overlay2"
        "RootFS": {
            "Type": "layers",
            "Layers": [
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"

Besides, the JSON format makes it easier to get the value of a field quite easy. Here is an example from the Docker Docs:

$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' ec734

The Docker Docs have some other useful examples, which I appreciate you looking at.

8. docker pull

docker pull is used to pull a Docker image from the repository. The repository can be at the Docker Hub or another publicly hosted registry. In fact, it can be a private Docker registry hosted in your local environment. Though it requires some configuration for your Docker daemon to use a private registry.

I wrote an article about hosting a private registry, a few months ago. You may refer the same for more details.

Here are a few examples of docker pull in action:

// pulls the 'latest' tag when no tag is specified
docker pull busybox 

// pulls the specified tag 
docker pull busybox:glibc

// pulls all the available tags
docker pull busybox --all-tags

Each time we need an image, the Docker engine first checks if the image is available locally. If not, it pulls the image by resolving the namespace concerning the available registries.

9. docker push

I believe this is one of the most straightforward commands available for use. docker push pushes or uploads an image to its respective repository. Let’s consider a few examples:

$ docker push busybox:some-tag

In the above command, notice that the image name does not include a namespace. This is because the busybox image lies in the default namespace in Docker Hub.

Here is another example of an image from my repository:

$ docker push quickdevnotes/webapp:latest

Since my repositories are not officially recognized by Docker, they lie in a separate namespace. Therefore, each time I want to pull or push an image it is mandatory to specify the namespace before the image name.

It is also important to note that you need to first login to your Docker Hub account before you try to pull or push an image from a private registry. Else you get a permission denied error.

10. docker run

If you are using Docker, it is but obvious that you want to run some containers. That’s exactly what docker run is for. Each time we execute the docker run command, a process starts on the host machine which we call as a Docker container.

According to Docker documentation:

When an operator executes docker run, the container process that runs is isolated in that it has its own file system, its own networking, and its own isolated process tree separate from the host.

The basic form of docker run looks like the following:


It is a must to specify an image to run a container, as it defines the base for a container. I am going to keep it simple. Talking about each option for this command is like rewriting the whole documentation all over. So, here are a few examples that you generally see:

// starts an Ubuntu container and open an interactive TTY connection
$ docker run -it ubuntu:16.04 /bin/bash

// starts a busybox container and shows the output of top command
$ docker run -it busybox top

// starts a container in detached mode
$ docker run -d alpine sleep 1d

// starts a container in detached mode 
// maps port 5000 of host to port 80 of the container
$ docker run -d -p 5000:80 quickdevnotes/webapp

// starts a container in detached mode 
// maps the port and sets the environment variable in container
$ docker run -d -p 5000:80 -e ASPNETCORE_ENVIRONMENT=Testing quickdevnotes/webapp

// starts a container in detached mode 
// maps the port, sets the environment variable
// mounts the configuration file from host to the path in container
$ docker run -d -p 5000:80 \
     $(pwd)/appsettings.json:/app/appsettings.json \

With the above examples, we have barely scratched the surface. There is a lot you can do with the docker run command. I insist, you check the amazing documentation for this command at Docker Docs.

If you want to experiment and explore by yourself, you can use the docker run --help command to get a list of available options.


In this article, we have covered ten of the twenty-five most used Docker commands. While there is a lot that you can do with these commands than what we have covered here. The idea was to keep it simple and jot down the most common and widely used scenarios.

If you think there is a command that should be a part of this list, please let me know in the comments section. Also, if there is an option that must be talked about for the listed commands, please let me know.

Categories: Docker