A Tour of Docker CLI Commands — Part I

Photo by Steve Johnson on Unsplash

Introduction

I put together this quick, introductory tutorial workflow to help you to familiarize yourself with the Docker CLI.

It doesn’t cover everything. There are several out-of-scope topics which will be covered in a follow-up Part II tutorial.

Terminology

Throughout this article you’ll hear about

  • Docker
  • Docker Hub
  • images
  • containers

Docker Hub is a container image directory where images are stored and available to be pulled for developers to build containers for services or web apps.

It is a public registry maintained by Docker, an open-source project with PaaS services that distribute software using OS-level virtualization

A Docker image has the deployment and execution configuration, and dependencies needed by a container runtime. It is a static representation of the app or service and its configuration and dependencies.

A developer builds an application or service using Docker and bundles it together with any dependencies into a container, which is an instance of a Docker image and can be run anywhere (on-premises, in the cloud etc).

The developer runs a Docker host the development computer (Windows, Linux, macOS), which is the machine that Docker Engine is installed and where Docker images are deployed.

Setup

Check here to get started for free with Docker.

Once you’ve completed all the installation steps, run the following command on your Terminal to check that Docker was installed successfully:

docker versionClient:
Cloud integration: v1.0.24
Version: 20.10.17
API version: 1.41
[...]

Pulling Images and Creating Containers

Let’s pull the Docker image Postgres.

Use the following command to pull the Postgres image from the Docker Hub registry:

docker pull postgres

We can confirm we’ve got the Docker image using the following command, and using the — q flag to display the image id only:

docker imagesREPOSITORY   TAG       IMAGE ID       CREATED       SIZE
postgres latest 1133a9cdc367 2 weeks ago 376MB
docker images -q1133a9cdc367

We can then create a container from an image, without specifying a name for the container:

docker create postgres3fa3bc56a56f7a0bf4bb9a34ad94941f2066643cc476d3a3e2c3223784333ee0

This command shows details of the running containers (which we have none at the moment):

docker psCONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

We can run the following commands to show all containers irrespective of whether they are running or not, as well as the those image Ids only.

This time, we can see the one container created from the Postgres image.

docker ps -aCONTAINER ID   IMAGE      COMMAND                  CREATED              STATUS    PORTS     NAMES3fa3bc56a56f   postgres   "docker-entrypoint.s…"   About a minute ago   Created             strange_easleydocker ps -aq3fa3bc56a56f

Let’s pull a second image from Docker Hub, this time MySQL:

docker pull mysql

Check to see we’ve now got two images now:

docker imagesREPOSITORY   TAG       IMAGE ID       CREATED        SIZE
mysql latest 38643ad93215 17 hours ago 446MB
postgres latest 1133a9cdc367 2 weeks ago 376MB

Let’s create a container for the MySQL image, this time specifying a container name “mysql-container”:

docker create --name mysql-container mysql
2e5afd84fd493a35a00d6e83a848415e0eac52382e1f088af6725198ab09e3cb

The create command creates a new container from a docker image, but again the container doesn’t run immediately (same as the container we created from the Postgres image).

Now check we’ve got two containers (irrespective of status):

docker ps -aCONTAINER ID   IMAGE      COMMAND                  CREATED              STATUS    PORTS     NAMES2e5afd84fd49   mysql      "docker-entrypoint.s…"   About a minute ago   Created             mysql-container3fa3bc56a56f   postgres   "docker-entrypoint.s…"   15 minutes ago       Created             strange_easley

Searching for Containers

Let’s do that again, but this time filtering the results to show only containers named “my” (again, irrespective of status):

docker ps -a -f name=myCONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS    PORTS     NAMES2e5afd84fd49   mysql     "docker-entrypoint.s…"   4 minutes ago   Created             mysql-container

We can also show we don’t have any running containers by filtering on status “running”:

docker ps -a -f status=runningCONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Running Containers

The start command will start any stopped container.

Let’s start the “mysql_container” and check for running containers:

docker start mysql-containermysql-containerdocker psCONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Wait a minute!? Shouldn’t there be a running container?

Let’s check the logs on that container as follows:

docker container logs mysql_container2022-07-27 16:32:47+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specifiedYou need to specify one of the following:- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD

As expected, in order to start a MySQL server instance we’ve got to supply some arguments.

The MySQL page on Docker supplies the following template command, which I’ve just run without making any changes:

docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql23aa7eb5bb5d0e6266f649c5d3cb9f92bcb09bcd5dcd8f8d3c9aa4286ab664dd

Now we can see the one mysql container is running called “some-mysql”:

docker psCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                 NAMES23aa7eb5bb5d   mysql     "docker-entrypoint.s…"   28 seconds ago   Up 27 seconds   3306/tcp, 33060/tcp   some-mysql

What happened was the run command both created and started a totally new container called “some-mysql”.

Contrast that with the create command we used to create the “mysql-container”, which only creates a new container but doesn’t start it.

The part of the run command that specifies the name to use is as follows:

docker run --name some-mysql [...]

Pausing, Unpausing, Restarting and Stopping Containers

We can pause and unpause the running container “some-mysql” as shown below.

Notice that we’re using the ps command again after the pause command, which tells us whether the container is paused:

docker pause some-mysqlsome-mysqldocker psCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                   PORTS                 NAMES23aa7eb5bb5d   mysql     "docker-entrypoint.s…"   17 minutes ago   Up 21 seconds (Paused)   3306/tcp, 33060/tcp   some-mysql

Let’s now unpause it and check again:

docker unpause some-mysqlsome-mysqldocker psCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS              PORTS                 NAMES
23aa7eb5bb5d mysql "docker-entrypoint.s…" 18 minutes ago Up About a minute 3306/tcp, 33060/tcp some-mysql

We can list the processes running inside the container to see a particular PID using the top command:

docker container top some-mysqlUID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD999                 3503                3478                2                   16:55               ?                   00:00:07            mysqld

We can restart this running container as shown below.

We can also stop it, then confirm that no containers are running anymore:

docker restart some-mysqlsome-mysqldocker stop some-mysqlsome-mysqldocker psCONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

We can also filter the container logs for the text “SHUTDOWN” using grep command-line utility for searching plain-text (a further explaination of 2>&1 can be found here).

docker logs some-mysql 2>&1 | grep "SHUTDOWN"2022-07-27T16:38:44.799824Z 10 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.30).2022-07-27T16:43:34.052929Z 0 [System] [MY-013172] [Server] Received SHUTDOWN from user <via user signal>. Shutting down mysqld (Version: 8.0.30).

Removing Containers

We can remove all containers that are stopped using the prune command as shown below.

We have one container running and two others that aren’t, so we’d expect to see two deleted containers:

docker container pruneWARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
2e5afd84fd493a35a00d6e83a848415e0eac52382e1f088af6725198ab09e3cb
3fa3bc56a56f7a0bf4bb9a34ad94941f2066643cc476d3a3e2c3223784333ee0

To verify that we’ve only got one container left (the one still running) let’s run the command to list all containers (regardless of status):

docker ps -aCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS         PORTS                 NAMES
23aa7eb5bb5d mysql "docker-entrypoint.s…" 25 minutes ago Up 8 minutes 3306/tcp, 33060/tcp some-mysql

We can remove all containers regardless of status with the force flag.

Since we’ve only got one container left (currently running), we expect a single container to be removed:

docker rm -f $(docker ps -a -q)
23aa7eb5bb5d

We could also have deleted that container by name as shown below.

If you don’t stop the container, the CLI will complain that it’s trying to delete a running container:

docker rm some-mysqlError response from daemon: You cannot remove a running container 23aa7eb5bb5d0e6266f649c5d3cb9f92bcb09bcd5dcd8f8d3c9aa4286ab664dd. Stop the container before attempting removal or force remove

In this case either:

  • stop the container then remove it, or
  • remove it using the force flag.

Removing Images

Finally, let’s remove the Postgres and MySQL images using the rmi command:

docker rmi mysql
docker rmi postgres

It makes sense that this operation won’t work on an image if it’s being used by containers (try this yourself).

In order to force-remove an image you would use the force flag:

docker rmi -f mysql

Thanks for reading! Let me know what you think in the comments section below, and don’t forget to subscribe. 👍

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
George Marklow

George Marklow

George is a software engineer, author, blogger, and abstract artist who believes in helping others to make us happier and healthier.