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