1. Introduction
As more and more applications move to cloud computing, the terminology can sometimes become confusing.
In this article, we’ll talk about the difference between Docker, Dockerfile, and Docker Compose.
2. Docker
Let’s start by looking at Docker, one of the core components of any cloud computing platform. Docker is a container engine that allows us to efficiently and securely separate our applications from the infrastructure they run on.
What does this mean exactly? Docker allows us to run any application in a virtualized environment, using just about any hardware or Operating System we want. This means we can use the same environment for our applications in development, testing, and production.
There are a few key components that make up Docker:
- Daemon: The Docker daemon listens for Docker API requests and manages objects such as images and containers.
- Client: The Docker client is the main interface for issuing commands to the daemon.
- Desktop: Docker desktop is a specialized version of Docker for Mac and Windows that simplifies interacting with the daemon.
Additionally, there are several Docker objects that we should be familiar with:
- Image: An image is a self-contained file that includes all necessary files for running an application (including Operating System and application code). Images have layers, and each layer contributes one or more sets of files and directories.
- Container: A container is a runnable instance of an image. Containers are typically isolated from each other, although volumes and networks can allow them to interact.
- Registry: A registry stores images. It can be private or public and optionally require authentication.
- Volume: A volume is a filesystem that can be made available to one or more containers. Volumes can be persistent or ephemeral (lasting only as long as a container is active).
- Networks: Networks allow containers to communicate using standard network protocols (TCP/IP).
Now that we understand the basic concepts of Docker itself, we can look at two other technologies that are directly related.
3. Dockerfile
A Dockerfile is a plain text file that contains instructions for building Docker images. There’s a Dockerfile standard they follow, and the Docker daemon is ultimately responsible for executing the Dockerfile and generating the image.
A typical Dockerfile usually starts by including another image. For example, it might build on a specific operating system or Java distribution.
From there, a Dockerfile can perform various operations to build an image:
- Copy files from the host system into the container. For example, we might want to copy a JAR file that contains our application code.
- Run arbitrary commands relative to the image. For example, we might want to run typical Unix commands to change file permissions or install new packages using a package manager.
- Define the command that should be executed when a container is created. For example, a java command that loads our JAR file and starts the desired main method.
Let’s look at an example Dockerfile:
FROM openjdk:17-alpine
ARG JAR_FILE=target/my-app.jar
COPY ${JAR_FILE} my-app.jar
ENTRYPOINT ["java","-jar","/my-app.jar"]
This example creates a Docker image based on the existing OpenJDK 17 Alpine image. It then copies a compiled JAR file into the image and defines the startup command as the java command with the -jar option along with our compiled JAR file.
It’s worth noting that a Dockerfile is just one way to create Docker images. Other tooling, such as Buildpacks, can help automate the process of compiling our code into Docker images without using Dockerfiles.
4. Docker Compose
Docker Compose is a tool for defining and running multi-container Docker applications. Using a YAML configuration file, Docker Compose allows us to configure multiple containers in one place. We can then start and stop all of those containers at once using a single command.
Additionally, Docker Compose allows us to define common objects shared by containers. For example, we can define a volume once and mount it inside every container, so that they share a common file system. Or, we can define the network used by one or more containers to communicate.
Let’s write a simple Docker Compose file:
version: "3.9"
services:
database:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
web:
image: my-application:latest
ports:
- "80:5000"
volumes:
db_data: {}
This will start two containers: a MySQL database server and a web application. It defines one volume that is used by the database container. Additionally, it defines which ports should be exposed for each container so network traffic can reach them.
Dockerfiles and Docker Compose are not mutually exclusive. In fact, they work quite well together. Docker Compose provides a build directive that we can use to build our Dockerfiles prior to starting a container.
Finally, keep in mind that Docker Compose is just one tool for orchestrating multiple containers. Other options include Kubernetes, Openshift, and Apache Mesos.
5. Conclusion
In this article, we’ve discussed the differences between Docker, Dockerfile, and Docker Compose. While all of these technologies are related, they each refer to distinct pieces of a larger technology ecosystem.
Understanding each of these pieces and the roles they play can help us make more informed decisions when working on cloud computing platforms.