DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Containerize Gradle Apps and Deploy to Kubernetes With JKube Kubernetes Gradle Plugin
  • KubeMQ: A Modern Alternative to Kafka
  • 7 Microservices Best Practices for Developers
  • Rapidly Develop Java Microservices on Kubernetes With Telepresence

Trending

  • DZone's Article Submission Guidelines
  • Medallion Architecture: Why You Need It and How To Implement It With ClickHouse
  • Top Book Picks for Site Reliability Engineers
  • Event-Driven Architectures: Designing Scalable and Resilient Cloud Solutions
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. How to NGINX Reverse Proxy with Docker Compose

How to NGINX Reverse Proxy with Docker Compose

Take a look at how to use NGINX reverse proxy with Docker Compose to expose multiple services without changing ports.

By 
Sudip Sengupta user avatar
Sudip Sengupta
DZone Core CORE ·
Apr. 30, 20 · Tutorial
Likes (11)
Comment
Save
Tweet
Share
152.6K Views

Join the DZone community and get the full member experience.

Join For Free

While developing a web application, a common method of calling the application from a local machine is through http://localhost:x ports, which essentially means that we are required to expose several ports to access different modules of the application. In the article below, we will go through the method of using Reverse Proxy to call an application and the benefits of using it.

Why Do We Need Reverse Proxy?

The most obvious reason for using Reverse Proxy is to avoid changing ports every time you try to access different modules of the application through the same URL. Through Reverse Proxy we can reach frontend, backend, or other services without changing port through a single domain. Another important reason for using Reverse Proxy is to mask services behind a proxy and avoid dealing with CORS issues.

Plain Text
 




xxxxxxxxxx
1


 
1
# Without Reverse Proxy 
2
# Domain Name: http://mydomain.com 
3
# Mysql wordpress: http://mydomain.com:10088 
4
# Angular app: http://mydomain.com:7787 
5
# Backend: https://mydomain:9876


Plain Text
 




xxxxxxxxxx
1


 
1
# With Reverse Proxy 
2
# Domain Name: http://mydomain.com 
3
# Mysql wordpress: http://mydomain.com/db 
4
# Angular app: http://mydomain.com/ang 
5
# Backend: https://mydomain/wp


Prerequisites

  • Docker Compose on Linux
  • iptables should be enabled. Note that Docker uses iptables to access incoming connections.

Building docker-compose.yml

For reference for this article, let us create a Wordpress-MySQL server with NGINX in one service. Start by creating the Docker container, along with defining ports, base image, container name, and service names.

Shell
 




xxxxxxxxxx
1
37


 
1
version: '2'
2

          
3
services:
4
  whilefly_wp:
5
    container_name: production_wp
6
    image: nginx:latest
7
    volumes:
8
      - "/home/xx/Desktop/cust/xx/html:/var/www/html"
9
      - "/home/xx/Desktop/cust/xx/Docker/logs:/logs"
10
      - "/home/xx/Desktop/cust/xx/Docker/database:/docker-entrypoint-initdb.d"
11
      - "xx_db_data:/var/lib/mysql"
12
    user: root
13
    restart: always
14
    ports:
15
      - "8081:80"
16
    environment:
17
      MYSQL_ROOT_PASSWORD: 'xxxxx'
18
      MYSQL_DATABASE: 'production_db'
19
      MYSQL_USER: 'production_admin'
20
      MYSQL_PASSWORD: 'xxxxxx'
21
      
22
  nginx:
23
    image: nginx:latest
24
    container_name: production_nginx
25
    volumes:
26
      - /home/xx/Desktop/cust/xx/Docker/nginx/reverse_proxy.conf:/etc/nginx/conf.d/default.conf
27
      - /home/xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.pem:/etc/nginx/cert/star_xx_com.pem
28
      - /home/xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.key:/etc/nginx/cert/star_xx_com.key
29
      - /home/xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.crt:/etc/nginx/cert/star_xx_com.crt
30
    ports:
31
      - 8080:8080
32
      - 443:443
33
    links:
34
     - whilefly_wp
35

          
36
volumes:
37
  xx_db_data:



Let's explain the setup in steps.

  1. services command defines the service you will build in Docker.
Shell
 




xxxxxxxxxx
1


 
1
version: '2'
2

          
3
services:
4
  running_wp:   
5
  nginx:


2. As shown below, the running_wp service uses nginx:latest as the base image. You can also use your own custom image for MySQL and Wordpress. Next is to assign a container name, for instance currently production_wp is used below. Copy the local files under volume section to the given directory while building this docker image. It is important to assign Ports which are to be used for accessibility within or outside of the application. As shown below, we have mapped 8081 host to 80 port for container. 

Shell
 




xxxxxxxxxx
1
19


 
1
version: '2'
2
services:
3
  running_wp:
4
    container_name: production_wp
5
    image: boraozkan/nginx:latest
6
    volumes:
7
      - "/home/xx/Desktop/cust/xx/html:/var/www/html"
8
      - "/home/xx/Desktop/cust/xx/Docker/logs:/logs"
9
      - "/home/xx/Desktop/cust/xx/Docker/database:/docker-entrypoint-initdb.d"
10
      - "xx_db_data:/var/lib/mysql"
11
    user: root
12
    restart: always
13
    ports:
14
      - "8081:80"
15
    environment:
16
      MYSQL_ROOT_PASSWORD: 'xxxxx'
17
      MYSQL_DATABASE: 'production_db'
18
      MYSQL_USER: 'production_admin'
19
      MYSQL_PASSWORD: 'xxxxxx'


3. Assign necessary access credentials with the environment command. 

Shell
 




xxxxxxxxxx
1


 
1
environment:
2
      MYSQL_ROOT_PASSWORD: 'xxxxx'
3
      MYSQL_DATABASE: 'production_db'
4
      MYSQL_USER: 'production_admin'
5
      MYSQL_PASSWORD: 'xxxxxx'


4. Assign the base image and container name. The base image will create NGINX on the first run. You can also add encrypted SSL files through https://letsencrypt.org/; it is free.

Shell
 




xxxxxxxxxx
1
17


 
1
version: '2'
2
  nginx:
3
    image: nginx:latest
4
    container_name: production_nginx
5
    volumes:
6
      - /home/xx/Desktop/cust/xx/Docker/nginx/reverse_proxy.conf:/etc/nginx/conf.d/default.conf
7
      - /home/xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.pem:/etc/nginx/cert/star_xx_com.pem
8
      - /home/xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.key:/etc/nginx/cert/star_xx_com.key
9
      - /home/xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.crt:/etc/nginx/cert/star_xx_com.crt
10
    ports:
11
      - 8080:8080
12
      - 443:443
13
    links:
14
     - running_wp
15

          
16
volumes:
17
  xx_db_data:


5. Add NGINX configuration file under conf.d path - this is the default directory for virtual host descriptions.

Plain Text
 




xxxxxxxxxx
1


 
1
/home/xx/Desktop/cust/xx/Docker/nginx/reverse_proxy.conf:/etc/nginx/conf.d/default.conf


6. As shown below there are two parts of this config file. First one shows the server side defining which port will be listened by the NGINX Container (8080 and 443). Secondly, the forward traffic would be directed to port 8081 — this is the port of production container for reaching. 

Shell
 




xxxxxxxxxx
1
27


 
1
# re-route everything to production_wp
2
 server {
3
  listen 8080;
4
  server_name production_wp;
5
  
6
  error_page 497 http://$host:80$request_uri;
7

          
8
  ssl on;
9
  ssl_certificate /etc/nginx/cert/star_xx_com.crt;
10
  ssl_certificate_key /etc/nginx/cert/star_xx_com.key;
11

          
12
  location /wp {
13
    proxy_pass          http://localhost:8081/wp;
14
     rewrite /wp(.*) /origin-d$1
15
            proxy_pass http://localhost:8081;
16
            proxy_redirect / /wp;
17
            sub_filter 'href="/' 'href="/wp'
18
    
19
  }  
20
}
21

          
22
# wordpress container via production_wp
23
 server {
24
  listen 443;
25
  server_name production_wp;
26

          
27
  error_page 497 http://$host:80$request_uri;


7. Enable secure HTTP with the ssl on command. 

Shell
 




xxxxxxxxxx
1


 
1
ssl on;  
2
  ssl_certificate /etc/nginx/cert/star_xx_com.crt;  
3
  ssl_certificate_key /etc/nginx/cert/star_xx_com.key;


8. To prefix headers for proxy connections, we can use the proxy_set_header directive which helps in redefining or appending fields to the request header passed through the proxied server.

Shell
 




xxxxxxxxxx
1


 
1
proxy_set_header    X-Forwarded-Host   $host; 
2
proxy_set_header    X-Forwarded-Server $host; 
3
proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for; 
4
proxy_set_header    X-Forwarded-Proto  $scheme; 
5
proxy_set_header    X-Real-IP          $remote_addr; 
6
proxy_set_header    Host               $host;


9. For Reverse Proxy as mentioned in the beginning, we will give a path for the Wordpress container in NGINX configuration. Let us say it is using http://localhost/wp to http://localhost:8081, which is an asymmetric path. 

Shell
 




xxxxxxxxxx
1


 
1
location /wp {proxy_pass          http://localhost:8081/wp;rewrite /wp(.*) /origin-d$1proxy_pass http://localhost:8081;proxy_redirect / /wp;sub_filter 'href="/' 'href="/wp' }


10. Now we can start our containers with the command below. Remember to be in same path with docker-compose.yaml while starting containers. 

Shell
 




xxxxxxxxxx
1


 
1
docker-compose up -d 


11. The  docker-compose up  command is a shorthand form of  docker-compose build  and  docker-compose run . 

Shell
 




xxxxxxxxxx
1
15


 
1
#docker-compose up -d
2
Pulling nginx (nginx:latest)...
3
2.1: Pulling from nginx:latest
4
b8f262c62ec6: Pulling fs layer
5
a98660e7def6: Pulling fs layer
6
4d75689ceb37: Pulling fs layer
7
639eb0368afa: Waiting
8
99e337926e9c: Waiting
9
431d44b3ce98: Waiting
10
beb665ea0e0e: Pulling fs layer
11
c98a22d85c62: Waiting
12
bf70d116f1d7: Waiting
13
97f2d71621e0: Waiting
14
ea02a46a87c8: Waiting
15
78fff17c3a50: Waiting


12. When complete, we should have two containers deployed, one of which we cannot access directly:

Shell
 




xxxxxxxxxx
1


 
1
$ docker ps
2
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
3
9c327bb01a85       nginx:latest             "nginx -g 'daemon of…"   8 minutes ago       Up 8 minutes        0.0.0.0:8080->8080/tcp, 0.0.0.0:443->443/tcp   production_nginx
4
3823ce1f25d8        boraozkan/nginx:latest   "/usr/bin/supervisord"   8 minutes ago       Up 8 minutes        3306/tcp, 0.0.0.0:8081->80/tcp             production_wp


13. We can check our applications (one with NGINX and the other one with Apache).
Navigate to http://localhost:8080, and this will hit NGINX Reverse Proxy which will in turn will load the NGINX web application:

NGINX web application


14. Also check with navigating to http://localhost:8081 or http://localhost/wp, through the Nginx Reverse Proxy asymmetric path and the Apache web application will be loaded:

Apache web application 

Troubleshooting

Once the services are up, try to connect your web application to the localhost link. If it is not answered, check your iptables table for correctness.

By default Docker containers can make connections to the outside world, but the outside world cannot connect to containers. Each outgoing connection will appear to originate from one of the host machine’s own IP addresses thanks to an iptables masquerading rule on the host machine that the Docker server creates when it starts:

Shell
 




xxxxxxxxxx
1


 
1
$ sudo iptables -t nat -L -n
2

          
3
...
4
Chain POSTROUTING (policy ACCEPT)
5
target     prot opt source               destination
6
MASQUERADE  all  --  172.17.0.0/16       0.0.0.0/0


Conclusion

This article is aimed to show how you can use Nginx with docker-compose easily. It also shows setting of Reverse Proxy configuration on containers. Using this will give you additional flexibility during deployment of a web application.

I hope you liked this post! More to come soon.

Until then, here are some more Kubernetes and Docker best practices for managing and deploying containers.

Docker (software) Kubernetes application shell Web Service

Published at DZone with permission of Sudip Sengupta. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Containerize Gradle Apps and Deploy to Kubernetes With JKube Kubernetes Gradle Plugin
  • KubeMQ: A Modern Alternative to Kafka
  • 7 Microservices Best Practices for Developers
  • Rapidly Develop Java Microservices on Kubernetes With Telepresence

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!