Introduction
We 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.
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 version Client: 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 images REPOSITORY TAG IMAGE ID CREATED SIZE postgres latest 1133a9cdc367 2 weeks ago 376MB docker images -q 1133a9cdc367
We can then create a container from an image, without specifying a name for the container:
docker create postgres 3fa3bc56a56f7a0bf4bb9a34ad94941f2066643cc476d3a3e2c3223784333ee0
This command shows details of the running containers (which we have none at the moment):
docker ps CONTAINER 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 -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3fa3bc56a56f postgres "docker-entrypoint.s…" About a minute ago Created strange_easley docker ps -aq 3fa3bc56a56f
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 images REPOSITORY 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 -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2e5afd84fd49 mysql "docker-entrypoint.s…" About a minute ago Created mysql-container 3fa3bc56a56f 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=my CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2e5afd84fd49 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=running CONTAINER 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-container mysql-container docker ps CONTAINER 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_container 2022-07-27 16:32:47+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified You 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 mysql 23aa7eb5bb5d0e6266f649c5d3cb9f92bcb09bcd5dcd8f8d3c9aa4286ab664dd
Now we can see the one mysql container is running called “some-mysql”:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 23aa7eb5bb5d 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-mysql some-mysql docker ps CONTAINER 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-mysql some-mysql docker ps CONTAINER 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-mysql UID PID PPID C STIME TTY TIME CMD 999 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-mysql some-mysql docker stop some-mysql some-mysql docker ps CONTAINER 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 prune WARNING! 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 -a CONTAINER 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-mysql Error 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
Author: George Marklow.