I've seen many people get confused between a Dockerfile and a Compose file. This is primarily because both are used to modify a Docker image in a way, though it's not technically correct.
It is easy to confuse the two terms, but it's also necessary to understand the difference when making a conversation with a colleague or your (potential) employer.
Dockerfile is what's used to create a container image, and a Compose file is what's used to deploy an instance of that image as a container.
Let me go in a bit of detail so that you properly understand the difference between Docker Compose and Dockerfile.
What is a Dockerfile?
I like to call Dockerfile the predecessor of a container image. You build an image from a Dockerfile. A typical Dockerfile contains special build instructions, commands like
Take the example below:
FROM alpine:latest RUN apk add --no-cache fortune ENTRYPOINT ["fortune"]
Each line starts with an instruction for the build component. These instructions don't necessarily have to be written in capital letters. The following is just as valid as the previous one.
from alpine:latest run apk add --no-cache fortune entrypoint ["fortune"]
From this Dockerfile, you can now build a container image (or a docker image). An image is simply a template for the running containers, consisting of multiple read-only layers. Since this isn't an article on container images, I'm going to refrain from over explaining that topic.
To build an image from this Dockerfile, using the docker CLI, run the following command
docker build -t fortune:alpine .
This will build an image tagged
fortune:alpine. I'm not going to create a container from this image yet, that's for the next section.
What is a Compose file?
Compose files are used in two types of deployments: in the non-cluster deployment with
docker-compose and a cluster deployment with
To distinguish the two types, I'm going to address the compose file responsible for cluster deployment as stack files. I'll talk about stack files in a moment.
Compose files are part of a tool called
docker-compose. It's a client application to the docker daemon server, kind of like the
docker CLI client, but instead of typing the whole
run commands every time, with
docker-compose you can re-use the same YAML file over and over again, and deploy the same container with the same configuration as you did in the first time.
It's more readable, more maintainable, more intuitive. A single compose file can contain multiple container deployment configurations.
Let's take the previous image, and deploy an instance of that using a compose file.
version: "3.3" services: fortune: image: "fortune:alpine"
Save the file as
docker-compose.yml. Now run in the same directory the following command
You don't have to save the file as
docker-compose.yml, you can save it however you like, but if it's not
docker-compose.yaml, make sure you use the
-f [FILENAME] option.
docker-compose -f docker-compose.yml up
Wait and see what happens.
To know what
fortune is, read this article about funny Linux commands.
What is a stack file?
Stack files are identical to compose files with similar syntax and most of the internal options, with some exceptions. Stack files are used to deploy stacks of services in a swarm cluster.
You can re-use the previous compose file directly as a stack file.
First, initialize the cluster.
docker swarm init
Then run a command similar to the following
docker stack deploy -c docker-compose.yml fortune
If deployed like this, you need to check the output by viewing the service logs using
docker service logs ....
Dockerfiles and Compose files serve a different purpose. If I could build a timeline, it'd look something like this
Dockerfile -> Docker Image -> Compose File -> Running Containers
There's another reason beginners get confused with these two files. A Dockerfile can be pointed to through the Compose file, and then you can use
docker-compose to build the image.
For example, you can rewrite the previous compose file so
version: "3.3" services: fortune: build: context: '.' dockerfile: "./Dockerfile" image: "fortune:alpine"
Now you can run
docker-compose build to build the image. Or you can also run
docker-compose up --build to build and run the container at once.
Here the Dockerfile is passed through the compose file, and from the first look, it can seem like it's the compose file that's responsible for building the image, but it's not.
I hope this article cleared what the difference is between a Dockerfile and a Compose file. If you have any questions, let me know in the comment section down below.