A container is a standard unit of software that packages an application with all of its dependencies and libraries. This makes it easy to deploy applications within containers regardless of hardware configuration or operating system. Unlike virtual machines, containers use the host OS rather than bundling an OS with the application.
Docker is a container platform. It provides a complete ecosystem of tools to build container images, pull these images from known registries, deploy containers, and manage or orchestrate running containers across a cluster of machines. Docker has popularized container adoption. Even the phrase "dockerize my app" has become common.
The word "Docker" usually refers to its engine. The commercial offering is called Docker Enterprise. There's also the free community edition that's simply called Docker Engine. Docker was initially available on Linux but later become available on MacOS and Windows as well.
What are the benefits of using Docker?
Docker provides a consistent runtime across all phases of a product cycle: development, testing, and deployment. For example, if development team has upgraded one dependency, other teams must also do the same. If they don't, app may work during development but fail in deployment or work with unexpected side effects. Docker overcomes this complexity by providing a consistent environment for your app. Hence, it's become essential for DevOps practice.
Docker is open source. There's freedom of choice since any type of application (legacy, cloud native, monolithic, 12-factor) can run in a Docker container. Security is built into the Docker Engine by default. It's powered by some of the best components such as the containerd. There's also powerful CLI and API to manage containers. Via certified plugins, we can extend the capabilities of the Docker Engine.
What do you mean by the term "Docker image"?
A Docker image is a read-only template from which containers are created. Here's a useful analogy: just as objects are instantiated from classes in object-oriented languages, Docker containers are instantiated from Docker images.
For example, your application may require an OS and runtimes such as Apache, Java or ElasticSearch. All these can be bundled into a Docker image. Thus, your app can have this exact runtime environment wherever it runs.
An image is built in multiple read-only layers. At the bottom, we might have bootfs and OS base image such as Debian. Higher layers could have custom software or libraries such as Emacs or Apache. This layering mechanism makes it easy to build new images on top of existing images. When an image gets instantiated into a running container, a thin writable layer is added on top, called Container Layer. This means that all changes go into the topmost layer. In fact, the underlying file system doesn't make a copy of the lower layers since they are read-only. This helps us bring up containers quickly.
How do developers share Docker images?
A remote location where Docker images are stored is called the Docker Registry. Images are pulled from and new images are pushed to the registry. Without registries, it would be difficult to share and reuse images across projects. There are many registries online and Docker Hub is the default one. Just as developers share code via GitHub, Docker images are shared via Docker Hub.
Besides Docker Hub, here are some other registries: Gitlab, Quay, Harbor, and Portus. Registries from cloud providers include Amazon Elastic Container Registry, Azure Container Registry, and Google Container Registry.
A collection of images with the same name but different tags is called Docker Repository. A tag is an identifier for an image. For example, "Python" is name of the repository but when we pull the image "Python:3.7-slim", we refer to the image tagged with "3.7-slim". In fact, it's possible to pull by mentioning only the repository name. A default tag (such as "latest") will be used and only that image will be pulled. Thus, these two commands are equivalent:
docker pull rhel7or
docker pull registry.access.redhat.com/rhel7:latest.
Which are the essential components of the Docker ecosystem?
The Docker Engine is a client-server app of two parts: the Docker Client and the Docker Daemon. Docker commands are invoked using the client on the user's local machine. These commands are sent to daemon, which is typically running on a remote host machine. The daemon acts on these commands to manage images, containers and volumes.
Using Docker Networking we can connect Docker containers even if they're running on different machines. What if your app involves multiple containers? This is where Docker Compose is useful. This can start, stop or monitor all services of the app. What if you need to orchestrate containers across many host machines? Docker Swarm allows us to do this, basically manage a cluster of Docker Engines.
Which are the command-line interfaces (CLIs) that Docker provides?
- Docker CLI: This is the basic CLI used by Docker clients. For example,
docker pullis part of this CLI with "pull" being the child command. These commands are invoked by user using the Docker Client. Commands are translated to Docker API calls that are sent to the Docker Daemon.
- Docker Daemon CLI: The Docker Daemon has its own CLI, which is invoked using the
dockerdcommand. For example, the command
$ sudo dockerd -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock &asks the daemon to listen on both TCP and a Unix socket.
- Docker Machine CLI: This is invoked with the command
- Docker Compose CLI: This is invoked with the command
docker-compose. This uses Docker CLI under the hood.
- DTR CLI: Invoked with
docker/dtr, this is the CLI for Docker Trusted Registry (DTR).
- UCP CLI: Invoked with
docker/dtr, this is the CLI for installing and managing Docker Universal Control Plane (UCP) on a Docker Engine.
- Docker CLI: This is the basic CLI used by Docker clients. For example,
What are Volumes in Docker and where are they useful?
Containers are meant to be temporary. Any changes made to it at runtime are usually not saved. Sometimes we may save the changes into a new image. Otherwise, changes are discarded. However, there's merit in saving data or state so that other containers can use them. Volumes are therefore used for persistent storage.
A volume is a directory mounted inside a container. It points to a filesystem outside the container. We can therefore exit containers without losing app data. Newer containers that come up can access the same data using volumes. The important thing is to implement locks or something equivalent for concurrent write access. Volumes can be created via Dockerfile or Docker CLI tool.
Apart from sharing data or state across containers, volumes are useful for sharing data (such as code) between containers and host machines. They're also useful for handling large files (logs or databases) because writing to volumes is faster than writing to Docker's Union File System (UFS) that uses IO expensive copy-on-write (CoW).
What's the purpose of a Dockerfile?
Dockerfile is nothing more than a text file containing instructions to build a Docker image. Each instruction creates one read-only layer of the image. When the container runs, a new writable layer is created on top to capture runtime changes.
Let's take the example of a Node.js application. The instruction
FROM node:9.3.0-alpinespecifies the base image of Node.js version 9.3.0 running on Alpine Linux.
ADDinstruction can be used to add files.
RUNcan be used for framework installation or application build. To expose ports from the container, use
EXPOSE. To finally launch the app within the container, use the
What are some basic Docker commands that a beginner should know?
We describe some Docker commands listed in the official Docker documentation:
To build a new image from a Dockerfile use the
buildcommand. We can then push this to a registry using
pullcan be used to find and download an image from registry to our local system. To create a new image from a running container's changes, we can use
commit. To list images, use
images. A downloaded image can be removed using
Once we have an image, we can create and start a container using
start. Containers can be stopped using
kill. A running container can be restarted using
restart. We can use
rmto remove containers. The command
pswill list all running containers. To list stopped containers as well, use "-all" option.
- Chanezon, Patrick. 2017. "Docker Leads OCI Release of v1.0 Runtime and Image Format Specifications." Blog, Docker, July 19. Accessed 2019-08-06.
- Chaturvedi, Vineet. 2019. "What Is Docker & Docker Container? A Deep Dive Into Docker!" Blog, Edureka, May 22. Accessed 2019-06-05.
- Docker. 2019a. "The Industry-Leading Container Runtime." Accessed 2019-08-06.
- Docker. 2019b. "Docker Desktop." Accessed 2019-08-06.
- Docker Core Engineering. 2016. "Docker 1.12: Now with Built-in Orchestration!" Blog, Docker, June 20. Accessed 2019-08-06.
- Docker Core Engineering. 2017. "Introducing Docker 1.13" Blog, Docker, January 19. Accessed 2019-08-06.
- Docker Docs. 2019a. "docker (base command)." Command-Line Interfaces (CLIs), Docker v19.03, August 02. Accessed 2019-08-06.
- Docker Docs. 2019b. "docker ps." Command-Line Interfaces (CLIs), Docker v19.03, August 02. Accessed 2019-08-06.
- Docker Docs. 2019c. "Best practices for writing Dockerfiles." Command-Line Interfaces (CLIs), Docker v19.03, August 02. Accessed 2019-08-06.
- Docker Docs. 2019d. "dockerd." Command-Line Interfaces (CLIs), Docker v19.03, August 02. Accessed 2019-08-06.
- Docker Docs. 2019e. "Overview of Docker Compose." Docker v19.03, August 02. Accessed 2019-08-06.
- Docker Docs. 2019f. "Docker Machine Overview." Docker v19.03, August 02. Accessed 2019-08-06.
- Docker Saigon. 2016. "Docker Internals." Docker Saigon, February 29. Accessed 2019-08-06.
- El Amri, Aymen. 2018. "An Overall View On Docker Ecosystem — Containers, Moby, Swarm, Linuxkit, containerd, Kubernetes .." Medium, January 11. Accessed 2019-08-06.
- Friis, Michael. 2017. "Announcing Docker Enterprise Edition." Blog, Docker, March 20. Accessed 2019-08-06.
- Gienow, Michelle. 2017. "Docker Basics: Diving into the Essential Concepts, Tools, and Terminology." The New Stack, August 04. Accessed 2019-08-06.
- Grace, Nolan. 2017. "Docker Series — Creating your first Dockerfile." Pintail.ai, via Medium, December 18. Accessed 2019-08-06.
- Hale, Jeff. 2019. "Learn Enough Docker to be Useful. Part 2: A Delicious Dozen Docker Terms You Need to Know." Towards Data Science, January 16. Accessed 2019-08-06.
- Hykes, Solomon. 2015. "Introducing runC: a lightweight universal container runtime." Blog, Docker, June 22. Accessed 2019-08-06.
- Janetakis, Nick. 2017. "Get to Know Docker's Ecosystem." Blog, June 27. Accessed 2019-08-06.
- Jernigan, Tiffany. 2016. "Docker 1.11 et plus: Engine is now built on runC and containerd." Medium, May 17. Accessed 2019-08-06.
- Kasireddy, Preethi. 2016. "A Beginner-Friendly Introduction to Containers, VMs and Docker." freeCodeCamp, March 04. Accessed 2019-08-06.
- Ledenev, Alexei. 2016. "Deploy Docker Compose (v3) to Swarm (mode) Cluster." Codefresh, December 22. Accessed 2019-08-06.
- Mavungu, Eddy. 2017. "Docker Storage: An Introduction." Blog, Codeship, May 05. Accessed 2019-08-04.
- McCarty, Scott. 2018. "A Practical Introduction to Container Terminology." Blog, RedHat Developer, February 22. Accessed 2019-08-06.
- Messina, David. 2018. "5 years later, Docker has come a long way." Blog, Docker, March 20. Accessed 2019-08-06.
- OCI. 2019. "About." Open Container Initiative. Accessed 2019-08-06.
- Opensource. 2019. "What is Docker?" Opensource, Red Hat. Accessed 2019-08-06.
- ShapeBlock. 2019. "Docker registries: a roundup." ShapeBlock, March 22. Accessed 2019-08-06.
- van der Mersch, Vassili. 2016. "API-Driven DevOps: Spotlight on Docker." Nordic APIs, March 15. Accessed 2019-08-06.
- Wikipedia. 2019. "Docker (software)." Wikipedia, August 02. Accessed 2019-08-07.