How to: Nginx with Docker Compose
In this article, we will guide you through the essential steps of setting up Nginx with Docker Compose. This is a simple setup that by itself doesn’t do much, but it is a foundation to more complex Docker Compose environments.
Docker Compose is a tool for defining and running multi-container applications, in this article we will use it to create a local development environment, so we can spin up a Nginx container and test few configurations.
The following instructions are done on a Mac but it should be very similar to most other operational systems. I will assume that you already have Docker and Docker Compose installed on your computer.
The default path for a Compose file is compose.yaml
(preferred) or compose.yml
that is placed in the working directory. Compose also supports docker-compose.yaml
and docker-compose.yml
for backwards compatibility of earlier versions. If both files exist, Compose prefers the canonical compose.yaml
.
In order to start let’s create a folder called TTB in our home directory, and we will from now on only work inside the TTB folder.
Let’s create a file called compose.yaml
and add the below content:
version: '3'
services:
nginx:
image: nginx:1.11
ports:
- "8080:80"
Once we have the file saved, you can run below command:
$ docker compose up
That will start the containers, notice that if you don’t have the image of nginx:1.11 on your machine it will be downloaded, after that if everything goes will the terminal will hang, that means that the Nginx container is running, you should see something similar to the below entries.
$ docker compose up
[+] Running 5/5
✔ nginx 4 layers [⣿⣿⣿⣿] 0B/0B Pulled. 7.7s
✔ 6d827a3ef358 Pull complete 3.9s
✔ f8f2e0556751 Pull complete 0.7s
✔ 5c9972dca3fd Pull complete 4.7s
✔ 451b9524cb06 Pull complete 1.8s
[+] Running 3/2
✔ Network ttb_default Created 0.0s
✔ Container ttb-nginx-1 Created 0.2s
Now if you open your browser at 127.0.0.1:8080 you will see the Nginx welcome page.
That means we are all good, notice that on the compose.yaml
we set the ports to be 8080:80, that means that port 8080 on our machine will forward the traffic to port 80 on the container, this is very handy.
Also, notice that on the terminal that you run the docker compose command you will see the nginx logs, you should see something similar to below entries.
nginx-1 | 192.168.65.1 - - [12/Mar/2024:10:41:29 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" "-"
What we did was very basic, lets change that welcome page to something else, let’s create a folder called html
and inside that folder a file called index.html
and add the below content to it
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Tech Breeze</title>
</head>
<body>
<p>Welcome to The Tech Breeze</p>
</body>
</html>
Lets save the file, our file structure should be like this:
├── compose.yaml
└── html
└── index.html
Now lets change the compose.yaml
file and add our custom index.html
file inside the Nginx container.
version: '3'
services:
nginx:
image: nginx:1.11
volumes:
- ./html/index.html:/usr/share/nginx/html/index.html
ports:
- "8080:80"
Notice that we have added the volumes
keys, added the following values ./html/index.html:/usr/share/nginx/html/index.html
, notice that there is a :
between the files, that means the first files file is ./html/index.html
and the second is /usr/share/nginx/html/index.html
, the first file is the one we created, the one in our local machine, the second file is where we want to store the first file inside the container, here we are replacing the current index.html
of the Nginx container.
Remember that we still have the docker compose running, so you can go back to the terminal and hit ctrl + C
to stop the docker compose. If you don’t want the terminal to be hanging while the docker is running you can add the -d
to set the detached mode, so the containers run in the background, we will use this now.
Now, lets run the new docker compose configuration using the -d
as you can see below
$ docker compose up -d
Now the container should start and the terminal will appear like after any other command. In order to check if the container is up and running you can browse 127.0.0.1:8080 again, and this time you should see our modified index.html
.
This looks simple, but it is very powerful, now if you change the content of the file index.html
on your local machine and refresh the page, you will notice that the page also change, without having to restart the container. That is because we are using the volumes
key in the compose.yaml
and any change we make on that file will be reflected on the file that is inside the container because we are sharing it with the container.
Given that we are running the docker compose command with the -d
in order to see the logs of the container we need to run the following command:
$ docker compose logs nginx
The nginx in the above command is the name of the service, if you go back to the compose.yaml
file you will see that we declare a service called nginx, so we want to see the logs of this service, or another way of saying this is, we want to see the logs of the container that correspond to the service nginx.
Another nice command you can use is to check if the containers are really running, and there are 2 ways you can do that, the first way is using the docker compose command, but you MUST run this command inside the folder where the compose.yaml
file is located, the second command uses docker and that will list any container running on your machine and you can do that from any folder.
Docker Compose example:
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
ttb-nginx-1 nginx:1.11 "nginx -g 'daemon of…" nginx 9 minutes ago Up 9 minutes 443/tcp, 0.0.0.0:8080->80/tcp
Docker example:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9efa3f145091 nginx:1.11 "nginx -g 'daemon of…" 11 minutes ago Up 11 minutes 443/tcp, 0.0.0.0:8080->80/tcp ttb-nginx-1
Now you have learned how to share a volume with the container and the benefits this bring to you and you have learned how to check if the containers are running, there are two more things I want to show you.
The first thing, how to bring all this down, and that is simple you need to run the below command, if not the containers will be running on the background of your computer, and depending on how your computer is configured every time you restart your computer the containers will be running as well, so this is important.
Stop all the Docker Compose services
$ docker compose down
[+] Running 2/1
✔ Container ttb-nginx-1 Removed 0.1s
✔ Network ttb_default Removed 0.0s
As with any docker compose command, you MUST run it inside the folder that has the compose.yaml
file.
You might be thinking, how do I know that the index.html file is located on the /usr/share/nginx/html/index.html
, I know that because I looked inside the container, and that is the second thing I want to show you how to do it, and as you could have imagined there are 2 ways of doing that, using the docker compose command and using the docker command.
If we use the docker compose command we will refer to the container we want to access by its service name.
Accessing the container using Docker Compose:
$ docker compose exec nginx bash
root@94108ec9004a:/#
From the above command, you can see that we used the docker compose exec
command and pointed the command at the nginx
service and we also mentioned that we want to run the bash
command inside the container, as as you can see on the following line we are inside the container as root.
Accessing the container using Docker:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
94108ec9004a nginx:1.11 "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes 443/tcp, 0.0.0.0:8080->80/tcp ttb-nginx-1
$ docker exec -ti 94108ec9004a bash
root@94108ec9004a:/#
From the above command you can see that if we want to access the container using the docker command we need to find what is the container ID first, and that we can get by running the docker ps
command, once we have the ID we can exec into the container by running docker exec -ti <container ID> <command>
the -ti means that we want a interactive terminal on the container.
Now that you can jump inside the container, you can investigate all the files and configuration inside of it, and you can see exactly what you want to change and where.
If you liked this how to, and you are interested in docker and docker compose I recommend you to check our the following book
Docker Up & Running from Sean P. Kane (Author) and Karl Matthias (Author)
I read this book and it is very nice and complete.