Trending keywords: security, cloud, container,

What is Docker CLI (Command Line Interface)?


Docker CLI tool is a command line application used to interact with the dockerd daemon. The dockerd daemon is the process that manages containers and handles all the commands sent from the CLI by exposing an API endpoint. So both dockerd and Docker CLI pieces are needed for docker to work. The following illustration depicts the overall Docker architecture:

Docker Architecture (Source:

In this entry you will go through the basics of the Docker CLI tool used to interface with Docker Engine, its key features, how to install and operate it, how to configure it, and how it relates to Docker Compose and Docker APIs.

Docker CLI features

The Docker CLI includes several useful features. It handles standard UNIX-style arguments, and in many cases, it offers both short and long forms.

For example, the flags -H, --host are both for specifying the host to connect. It accepts environment variables (which we’ll explain in detail later on), and it can also accept configuration from a file (config.json) so that admins can limit the passing of flags explicitly.

The –help flag is nice, but it could be better (I would have liked to see more comprehensive documentation similar to that offered by the Git toolset). Most of the reference material can be found on the official documentation site.

There is an option to run the tool with experimental features for testing purposes by exporting the following env variable:

export DOCKER_CLI_EXPERIMENTAL=enabledCode language: JavaScript (javascript)

Finally, it also allows the tool to be extended using plugins. You will need to follow specific instructions to set up out-of-process extensions that the CLI tool can use (such as registering new commands).

You can check this gist code of a sample plugin example for adding a new command to the CLI that displays the Docker changelog for the installed version and know more about using plugins.

Installation and configuration

As with all software, you have to install it before you can use it. Docker CLI is written in the Go programming language, so it’s quite portable as a tool.

The dockerd daemon, which is responsible for handling the CLI requests, can run on most popular platforms (including Windows, Linux, and Mac with ARM/x86_64 /amd64 CPUs). You can find a list of platforms that support Docker on this page.


The Docker CLI can be installed as a desktop application (called Docker Desktop) or by using the command line. Note that commercial use of Docker Desktop in larger enterprises requires a paid subscription.

The Get Docker page provides instructions for installing Docker Desktop on your computer. Meanwhile, installing the Docker CLI requires you to run a bunch of commands. If you use Ubuntu, for example, you first need to ensure that your apt repository packages are up to date with the latest ca-certificates and gnupg:

$ sudo apt update
$ sudo apt install ca-certificates curl gnupg lsb-release

Note that you can use either curl or wget to download the gpg keys:

$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpgCode language: JavaScript (javascript)

The following command updates the /etc/apt/sources.list.d/docker.list, adding a new repository for the Docker distribution and using the lsb_release tool for printing the right Linux distribution name:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] 
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Code language: PHP (php)

Now that the sources are configured, these last two commands are used to install the Docker CLI, dockerd, and docker-compose tools:

$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli docker-buildx-plugin docker-compose-plugin

You can also install Docker using the installation script, which requires fewer steps. Just make sure that you make it executable before running it:

$ sudo apt update
$ sudo apt install ca-certificates curl gnupg lsb-release
$ curl -fsSL -o
$ sudo chmod +x
$ sudo sh ./ --dry-runCode language: JavaScript (javascript)

When all of these steps are done, you can check to see if everything is alright by printing the docker version:

$ docker version
 Cloud integration: v1.0.22
 Version:           20.10.13
 API version:       1.41
 Go version:        go1.16.15
 Git commit:        a224086

Basic Interactivity

You can use the docker <command> to issue commands and get information about the available list of options.

For example, to get the list of options for the docker image command, run:

$ docker image
Usage:  docker image COMMAND
Manage images
  build       Build an image from a Dockerfile
  history     Show the history of an image
…Code language: JavaScript (javascript)

Use docker <command> <subcommand> –help to get a detailed list of available options for a subcommand. For example:

$ docker image build --help
Usage:  docker image build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
…Code language: JavaScript (javascript)

Running erroneous commands will stop the execution of the task and print an associated error:

$ docker image build -t
flag needs an argument: 't' in -t
See 'docker image build --help'.Code language: JavaScript (javascript)

When you first install Docker, you may need to log into a registry to push or pull images. You can do that with the docker login command:

$ docker login
Authenticating with existing credentials...
Login SucceededCode language: JavaScript (javascript)

There are a lot of available commands in Docker with further subcommands and flags. Most of the time, though, you will be using just a few of them. We will explore those in detail later in this tutorial.

Environment Variables

The Docker CLI runs on an execution context and can be configured with environment variables. These variables are used to configure connection parameters and access credentials. There aren’t many of them, but it’s important to know what they do. Here are some of the most important ones:

DOCKER_HOST: This is used to change the host that the CLI tool connects to. It needs to be a valid connection string. The different types of connection strings can be located in this section of the code. For example, tcp:// and unix:///path are valid connection strings.

DOCKER_CONTEXT: This is used to specify the default Docker context to use. You can use Docker contexts to easily switch back to different hosts. For example, here is a list of available contexts:

$ docker context list
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT                                        KUBERNETES ENDPOINT                 ORCHESTRATOR
default *           moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                   (default)   swarmCode language: PHP (php)
<code>desktop-linux       moby                                                          unix:///Users/theo.despoudis/.docker/run/docker.sock</code>Code language: HTML, XML (xml)

DOCKER_TLS_VERIFY: Set this to true or 1 if you don’t want to skip SSL certificate verification between your CLI tool and the dockerd daemon. This means that any certificate you use needs to be valid or the operation will fail.

DOCKER_CONFIG: This is the location of the Docker configuration files. By default, it is set to .docker inside the user’s home directory.

Config Files

The DOCKER_CONFIG env variable specifies the folder that the CLI tool will use to configure it using a special config.json. If you want to use a different config.json for a particular command, you need to use the --config <config_folder> instead.

Using config files allows the user to provide overrides and common options for Docker commands. For example, to assign a default format output for different kinds of listing options like images, containers, or secrets, you can use:

// config.json
"imagesFormat": "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"
Code language: JSON / JSON with Comments (json)

This is equivalent to using the following command:

$ docker image list --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"Code language: PHP (php)

You can also specify custom HTTP headers using the HttpHeaders field and certain build time arguments for --build-arg. The available config options are documented here.

It is recommended that you store these files in a configuration management tool so that they can be updated automatically when you need to change certain values using a version control system.

Useful Commands

Now, we’ll explore some of the most useful and practical commands to know when using the Docker CLI tool. Many of these commands accept arguments in a specific place, so you need to make sure you pass them in the correct order. You might want to review the list of available commands in the reference docs section.

Docker Create

The create (or container create) command creates a new container out of an existing base image without starting it. You can name the container and attach volumes, environment variables, and other configurations. For example:

$ docker container create -it --name example busybox

This creates a container named example out of the BusyBox image with a status of CREATED. Then you can use the start command to change its status to RUNNING.

Docker Build

This builds an image out of a Dockerfile. You need to provide a path or the location of the Dockerfile, specify a URL, or use STDIN instructions to build the image. For example, given that there is a Dockerfile in the current folder, you just need to run:

$ docker build .

This will create a new image based on the instructions you provided. You also have the option to override some of the build parameters using arguments.

Docker Pull

The pull command downloads the specified image from the registry into the local Docker filesystem. Once the image is downloaded, you will be able to list it using the docker image ls command:

$ docker pull alpine:latest
$ docker image ls
REPOSITORY                  TAG                IMAGE ID       CREATED        SIZE
alpine                      latest             b2aa39c304c2   10 seconds ago   7.05MB

Docker Run

The docker run command combines multiple commands for creating or pulling a container and running it with the provided options. If an image does not exist in the local host, for example, it will first pull it from the default registry, then create and run it all in the same command. The following example shows what this flow looks like:

$ docker run --name redis -p 6379:6379 -d redis:latest
Unable to find image 'redis:latest' locally
latest: Pulling from library/redis

$ docker ps
CONTAINER ID   IMAGE                      COMMAND                  CREATED         STATUS                         PORTS                    NAMES
3665d49a6c75   redis:latest               "docker-entrypoint.s…"   5 seconds ago   Up 4 seconds         >6379/tcp   redisCode language: JavaScript (javascript)

There are multiple configuration options you can use with run. You can learn more about them in the docs.

Docker Start/Stop

Starting and stopping a running container can be performed with the docker start and docker stop commands, respectively. A container can only be started if it’s available, and a container that has been started can only be stopped using the stop command once it completes its task or when stopping the dockerd process:

$ docker start nocontainer
Error response from daemon: No such container: nocontainer
Error: failed to start containers: nocontainer
$ docker start example
$ docker ps
CONTAINER ID   IMAGE                      COMMAND                  CREATED          STATUS                          PORTS                    NAMES
a883f7e9295b   busybox                    "sh"                     38 minutes ago   Up 6 seconds                                             example
$ docker stop exampleCode language: JavaScript (javascript)

Docker Exec

The exec command is used to execute a command in a running container. It is different from run in that it cannot be used to download images from a registry or perform other actions. For example, you cannot use exec on a container that is not present. The command is called from the default directory of the container or by the specified WORKDIR option:

$ docker exec -it redis redis-cli
Error: No such container: redis

$ docker run --name redis -p 6379:6379 -d redis:latest
$docker exec -it redis redis-cli> PING
PONG>Code language: PHP (php)

The exec command is useful for one-off tasks, testing connectivity, printing env variables, and for debugging purposes.

Docker Compose

Docker CLI is not the only tool that connects with the dockerd daemon. Since the dockerd process exposes an API, any compatible client can interface with it. Docker Compose, which is written in Python, is another tool that can act as a client to the Docker API.

Instead of using commands directly, you’ll need to specify a YAML definition of your stack. This will need to follow certain specifications. For example, the following specification defines a Redis server running on port 6379 and exposes the same port on the host machine. It then uses the docker-compose CLI to spin up the described service:

version: "3.9"
    image: "redis:alpine"
    container_name: redis
      - 6379:6379

$ docker-compose up -d
$ docker-compose ps
Name               Command               State           Ports         
redis redis ...   Up>6379/tcp

$ docker container ls
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                    NAMES
3d01944c30f8   redis:alpine   "docker-entrypoint.s…"   34 seconds ago   Up 33 seconds>6379/tcp   redisCode language: JavaScript (javascript)

This is equivalent to using the following Docker CLI commands:

$ docker network create --network=redis-net
$ docker run --name redis -p 6379:6379 --network=redis-net -d redis:latest

You can specify one or more services under the services field, and each one will have its own config. Docker Compose makes it easier to describe full-stack Docker applications in a single file and manage deployments using simple commands.

If you need to set up multiple networks, volumes, secrets, and other resources, Docker Compose is a scalable option. You can find the whole list of available commands for the docker-compose CLI with descriptions on this docs page.

Docker APIs

As we mentioned earlier, the Docker CLI interacts with Docker Engine using an API exposed in the dockerd service, and developers can create their own clients to interface with it.

This API (which is documented here) consists of various endpoints for managing Docker containers, secrets, and services. It uses the var/run/docker.sock for incoming HTTP and TCP requests:

The Docker API (Source:

Here is an example of using the socat tool to request the /version info endpoint:

echo -n "GET /info HTTP/1.0\n\n" | socat UNIX-CONNECT:/var/run/docker.sock - | grep -o '{.*}' | jq
  "Containers": 2,
  "ContainersRunning": 1,
  "ContainersPaused": 0,
  "ContainersStopped": 1,
  "Images": 4,
  "Driver": "overlay2",
  "DriverStatus": [
      "Backing Filesystem",
      "Supports d_type",
      "Native Overlay Diff",
  …Code language: PHP (php)

It sends a GET request to the /info endpoint using socat, which connects to the Docker socket. The last part of this expression extracts the JSON response and prettifies it in the command line.

In addition to the dockerd handlers, there are APIs for Docker Hub and Docker Registry that you can query as well. All of these exposed APIs deal with different management options and requests.


Docker is a platform for managing containers, and there are many tools and services in its ecosystem. Using the Docker CLI tool, users can issue commands to create and manage containers with ease and flexibility. This article explored the basics of the CLI tool, explained its most useful commands, and showed you how it works behind the scenes.

The goal of this article was to give you a good introduction to the Docker CLI. But when it comes to working with Docker and containers, you’ll do most of your learning in real-world scenarios like trying to deploy a WordPress stack consisting of WordPress, MySQL, and NGINX.