So you need to deploy containers. Where do you begin? You could certainly do this from the command line, deploying each container via a long string of command options, every time. Or you could make use of a tool that allows you to carefully construct the deployment within a configuration file, and then deploy the container with a simple command.
But which configuration file do you use? Which method of deployment do you use? You can go with docker-compose or docker. Your choice could all hinge on the complexity of the application/service you plan on deploying. And that all boils down to using either a Dockerfile or a docker-compose.yml or both.
You see? It gets complicated because you can use docker-compose.yml in such a way that it will call upon a Dockerfile to allow you to create even more complex container rollouts.
Let’s see how these two are used in conjunction.
So let’s say we want to create a Dockerfile that will use the latest NGINX image, but install php and php-fpm. The file is named Dockerfile and we’ll house it in a new directory called dockerbuild. Create that new directory with the command:
Within ~/dockerbuild, create the Dockerfile with the command:
In that file, paste the following:
FROM nginx:latest MAINTAINER NAME EMAIL RUN apt-get -y update && apt-get -y upgrade && apt-get install -y php-fpm
Where NAME is the name to be used as the maintainer and EMAIL is the maintainer’s email address.
This Dockerfile will pull the latest version of the official NGINX image and then build a new image based on it, and also upgrade the platform and install the php-fpm package and its dependencies (which includes PHP). It’s an incredibly simple example, but one that’s easy to follow.
You could then run the docker build command with that Dockerfile, like so:
docker build -t "webdev:Dockerfile" .
But we want to integrate that file into docker-compose.yml.
The docker-compose.yml file
Now let’s craft a docker-compose.yml file which uses that Dockerfile, but also adds a database to the stack. This docker-compose.yml file might look like:
version: '3' services: web: build: . ports: - "8080:80" db: image: mysql ports: - "3306:3306" environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_USER=user - MYSQL_PASSWORD=password - MYSQL_DATABASE=demodb
The important section here is web:. It is in the web section that we instruct the docker-compose command to use the Dockerfile in the same directory (the . indicates to run the build command in the current working directory). If we wanted to house our Dockerfile in a completely separate directory, it would be declared here. Say, for example, the docker-compose.yml file is in ~/dockerbuild and the Dockercompose file is in ~/nginxbuild, you could declare that with the line:
Save and close the file. You could then deploy the new container with the command (run from within the directory housing the docker-compose.yml file):
The command would first build the NGINX container from the Dockerfile and then deploy the db container as defined in the db: section.
Of course, you could also define everything within the docker-compose.yml file, but making use of both Dockerfile and docker-compose.yml makes for a much more flexible and efficient system. Why? Say you’ve defined a very complex Dockerfile for an NGINX container and you want to reuse that in a container deployment within a complete stack. Why go through all the trouble of re-defining the NGINX container within docker-compose.yml when you can simply repurpose the Dockerfile.
Write once, use often
With this system, you can write once and use often. So craft a Dockerfile for a part of the stack and re-use it for multiple stacks, by way of docker-compose.yml. Remember, docker-compose.yml files are used for defining and running multi-container Docker applications, whereas Dockerfiles are simple text files that contain the commands to assemble an image that will be used to deploy containers.
So the workflow looks like this:
- Create Dockerfiles to build images.
- Define complex stacks (comprising of individual containers) based on those Dockerfile images from within docker-compose.yml.
- Deploy the entire stack with the docker compose command.
And that is the fundamental difference between Dockerfile and docker-compse.yml files.