Your first Docker Compose file
Imagine a scenario of wanting to run a static page on a server. For this task, an NGINX server is a good choice. We have a simple HTML file on the static-site/index.html
path:
<!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <p>Hi! This application should run on docker-compose</p> </body> </html>
By using Docker, we will run an NGINX server using the official image found at https://www.docker.com/blog/how-to-use-the-official-nginx-docker-image/:
$ docker run --rm -p 8080:80 --name nginx-compose nginx
Let’s break this down a little bit:
- Docker Engine will run a Docker NGINX image.
- The default port on the image is
80
, so we shall map it locally to8080
to avoid using a privileged port. - The name we assign will be constant in order to make interactions with the container easier.
- By using the
—rm
argument, we ensure that once we are done with our task and stop the container, the container will be deleted.
Our container is up and running. In a different Terminal session, we should access the default NGINX page:
$ curl 127.0.0.1:8080 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
Since we have successfully run NGINX, we need to adapt our command in order to use the customized HTML page. A simple and fast way to do this is to mount the file at the path of a container. Let’s exit the previous command using Ctrl + C and then refine the previous command:
docker run --rm -p 8080:80 --name nginx-compose -v $(pwd)/static-site:/usr/share/nginx/html nginx
As expected, the page changes to the one we have specified:
$ curl localhost:8080/index.html <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <p>Hi! This application should run on docker-compose</p> </body> </html> $
Now we have everything needed to migrate this application to Compose. We will create a Compose file for the default NGINX installation:
services: nginx: image: nginx ports: - 8080:80
Let’s break down what we just did:
- The name of the service will be NGINX.
- The image is the same NGINX image.
- The ports are the same ports used previously.
The content shall be saved to a file named docker-compose.yaml
.
Next, we will execute the Compose command on the Terminal:
$ docker compose up [+] Running 2/0 Network chapter1_default Created 0.0s Container chapter1-nginx-1 Created 0.0s Attaching to chapter1-nginx-1 chapter1-nginx-1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration chapter1-nginx-1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ … $
As expected, the result from the HTTP request is the same as the one that we experienced by just running the Docker container.
The naming of the file is important. We did execute the Compose command to spin up the Compose file, but we did not specify the file to be used. As it happens with docker build
and Dockerfile, by running docker compose
in a directory, Compose will search for a file named docker-compose.yaml
. If the file exists, it’ll be picked up as the default Compose file. Be aware that we are not limited to just one filename; we can use a different filename for our Compose applications. In the following chapters, there are cases where we can use a different name for the Compose files and run the application using the –f
option.
Next, we shall mount the custom HTML page through the Compose configuration:
services: nginx: image: nginx ports: - 8080:80 volumes: - ./static-site:/usr/share/nginx/html
As simple as our previous Docker command seemed to be, behind the scenes, it created a Docker volume pointing to a path of our filesystem and then it was attached to the container. The same applies to Compose. We specify a volume that points to our filesystem. Then, based on our location, it is mounted to a directory of the container:
$ curl localhost:8080/index.html <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <p>Hi! This application should run on docker-compose</p> </body> </html>
As expected, the result is the same one with the result of the Docker example.
To review this section, we ran an NGINX instance using Docker CLI and made the transition to Compose by adding the corresponding YAML sections for the Docker command parameters that were used. Now, we are ready to move on to the next stage of this chapter’s journey, where we’ll build and run a Docker image on Docker Compose.