Docker File vs Docker Compose: What's the Difference?

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 RUN, ADD, COPY, ENTRYPOINT, etc.

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 docker swarm.

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.

Compose file support is going to be part of the default docker client which is written in Go, as a command-line argument, "docker compose". Notice the missing hyphen there. It's still experimental, so in production using the Python version, i.e. docker-compose is still recommended.

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

docker-compose up

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.yml or 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.

Essential Docker Compose Commands and Their Usage
Here’s an overview of the Docker Compose file components and various commands you can use to manage them.

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 ....

Cloud Engineer IT Professional Program

Become a certified cloud engineer, one of the 15 highest paying IT jobs, in as little as six months.

Check it out

Wrapping up

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.

Docker Run vs Start vs Create: Difference Explained
For a docker beginner, terms like docker start, docker run and docker create could be confusing. This article explains the difference with examples.

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.