By Bobby Iliev
Hi all!
Recently I had to setup a few small Docker containers for a couple of small websites.
As the sites were really small I didn’t want to run each one on a separate Droplet, so instead, I used Nginx with separate Nginx server blocks for each site and a reverse proxy for each Docker container.
Here’s how I set that up:
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Accepted Answer
Before you start, make sure to have Docker and Nginx installed, here’s how to do that:
https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04
Once you have both installed, you can continue with the steps:
For the same of simplicity, I will run a simple and I’ll run 2 small httpd
containers.
8080
on your host:docker run -dit --name container-1 -p 8080:80 httpd:2.4
Now if you visit http://your-dropets-ip:8080, you should be able to see a message saying It Works!
.
Just so that we could differentiate the two containers, let’s update the It works!
message with Container 1
for example:
docker ps
Then run the following sed
command to update the message:
docker exec CONTAINER_ID sed -i 's/It works!/Container 1/' /usr/local/apache2/htdocs/index.html
This would basically run a search and replace for the It works!
string and update it with Container 1
in the default index.html
file in the container itself.
If you visit your Droplet’s IP again in your browser the message should change from It works!
to Container 1
.
Let’s do the same thing for container 2, but map it to port 8081
instead:
docker run -dit --name container-2 -p 8081:80 httpd:2.4
Then agian get your container ID
docker ps
Then run the sed
command again to update the It works!
message to Container 2
:
docker exec CONTAINER_ID sed -i 's/It works!/Container 2/' /usr/local/apache2/htdocs/index.html
Now if you visit http://your-dropets-ip:8081, you should be able to see a message saying Container 2
.
Now that we have our containers up and running we can go ahead and configure our Nginx server blocks, I will go ahead and use the following two subdomain names for this example:
To keep things as simple as possible, I will create 2 server blocks with the following content:
Create a new file called container1.bobbyiliev.com.conf
in the /etc/nginx/sites-available/
directory and add the following content:
server {
listen 80;
server_name container1.bobbyiliev.com;
location / {
proxy_pass http://localhost:8080;
}
}
Create a new file called container2.bobbyiliev.com.conf
in the /etc/nginx/sites-available/
directory and add the following content:
server {
listen 80;
server_name container2.bobbyiliev.com;
location / {
proxy_pass http://localhost:8081;
}
}
Then once you have the two config files ready cd
to the /etc/nginx/sites-enabled
directory, and run the following commands:
ln -s ../sites-available/container1.bobbyiliev.com.conf .
ln -s ../sites-available/container2.bobbyiliev.com.conf .
Run a config test to make sure that there are no errors:
nginx -t
And if you get Syntax OK
message, restart Nginx:
systemctl restart nginx
Note, for more information about Nginx server blocks, I would recommend taking a look at this tutorial here:
That is pretty much it, now if I visit container1.bobbyiliev.com I should be able to see the Container 1
message and the same for container2.bobbyiliev.com.
To test that I could run a simple curl
request:
- curl container1.bobbyiliev.com
You should see the following output
<h1>Container 1</h1>
Then run the same request for container2.bobbyiliev.com:
- curl container2.bobbyiliev.com
And agian you should see the following output
<h1>Container 2</h1>
Here’s a quick video demo on how to do the above:
Now you have 2 different containers on the same Droplet being served from different domain names! Of course, this is just a very basic example, you could go a lot further by expanding your Nginx config a lot more, for example adding more headers to your Nginx proxy pass and even installing a Let’s Encrypt SSL.
Hope that this helps! Let me know if you have any questions! Regards, Bobby
Hi @bobbyiliev !
Thank you for your swift reply, this sorted things out. I created a ’ docker-compose.yml-file for all 3 containers, kept the nginx-proxy.conf :
version: '3.7'
services:
proxy:
image: jwilder/nginx-proxy:0.7.0
container_name: proxy-test
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx-proxy.conf:/etc/nginx/conf.d/nginx-proxy.conf:ro
container1:
image: httpd:2.4
container_name: container-1
environment:
VIRTUAL_HOST: container1.bobbyiliev.com
ports:
- 8080:80
container2:
image: httpd:2.4
container_name: container-2
environment:
VIRTUAL_HOST: container2.bobbyiliev.com
ports:
- 8081:80
And nginx-proxy.conf according to your instructions
server {
listen 80;
server_name container1.bobbyiliev.com;
location / {
proxy_pass http://container-1;
}
}
server {
listen 80;
server_name container2.bobbyiliev.com;
location / {
proxy_pass http://container-2;
}
}
> curl localhost:8081
<html><body><h1>Container 2</h1></body></html>
> curl localhost:8080
<html><body><h1>Container 1</h1></body></html>
> curl container1.bobbyiliev.com
<html><body><h1>Container 1</h1></body></html>
> curl container2.bobbyiliev.com
<html><body><h1>Container 2</h1></body></html>
Thanks for that clarification, it really helped!
Another way that works the same way ? Still, if I leave the out the nginx-proxy.conf-file then the following attributes ‘VIRTUAL_HOST’ and ‘ports’ in the docker-compose.yml-file will map the domain correctly. <p> What is the benefits of using an nginx-proxy.conf in that case ?
And this , follow-up question goes a bit beyond your post, that would be putting an Matomo-ID (wrapped in a javascript) in the nginx-configuration file instead of cluttering up my different services with the Matomo-ID
Best, Inkimar
Hi Bobby, Thank you very much for your tutorial,
What I want to achieve seems quite straightforward but I’ve been battling it for days now
I have a container for my frontend react app pulled in and running, same for my node-typescript app.
I mapped the frontend to port 3000 and the backend to 8000
I then set up Nginx to route the root requests to 3000 and then the request to the IP:8000 to /api
The frontend works fine but for some reason, I can’t seem to get the backend to work the way I want it.
When I visit the http://myIP:8000 it works from postman but when I use my https://server_address/api, the request comes back as bad gateway, tried a couple of solutions online but to no avail yet.
I will look forward to your response
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.