While developing a web application, a common method of calling the application from a local machine is through 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 to call an application and the benefits of using it. http://localhost:x Reverse Proxy Why do we need Reverse Proxy? The most prominent reason of using is to avoid changing ports everytime you try to access different modules of the application through the same URL. Through we can reach Frontend, Backend or other services without changing port through a single domain. Other important reasons of using Reverse Proxy is to mask services behind a proxy and avoid dealing with CORS issues. Reverse Proxy Reverse Proxy # Without Reverse # Domain Name: http: # Mysql wordpress: http: # Angular app: http: # Backend: https: Proxy //mydomain.com //mydomain.com:10088 //mydomain.com:7787 //mydomain:9876 # With Reverse # Domain Name: http: # Mysql wordpress: http: # Angular app: http: # Backend: https: Proxy //mydomain.com //mydomain.com/db //mydomain.com/ang //mydomain/wp Prerequisites Docker Compose on Linux should be enabled. iptables Note that Docker uses to access incoming connections. iptables Building docker-compose.yml For the reference of this article, let us create a server with in one service. Start by creating the docker container, along with defining ports, base image, container name and service names. Wordpress-MySQL Nginx version: services: whilefly_wp: container_name: production_wp image: nginx:latest volumes: - - - - user: root restart: always ports: - environment: MYSQL_ROOT_PASSWORD: MYSQL_DATABASE: MYSQL_USER: MYSQL_PASSWORD: nginx: image: nginx:latest container_name: production_nginx volumes: - xx/Desktop/cust/xx/Docker/nginx/reverse_proxy.conf: nginx/conf.d/ .conf - xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.pem: nginx/cert/star_xx_com.pem - xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.key: nginx/cert/star_xx_com.key - xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.crt: nginx/cert/star_xx_com.crt ports: - : - : links: - whilefly_wp volumes: xx_db_data: '2' "/home/xx/Desktop/cust/xx/html:/var/www/html" "/home/xx/Desktop/cust/xx/Docker/logs:/logs" "/home/xx/Desktop/cust/xx/Docker/database:/docker-entrypoint-initdb.d" "xx_db_data:/var/lib/mysql" "8081:80" 'xxxxx' 'production_db' 'production_admin' 'xxxxxx' /home/ /etc/ default /home/ /etc/ /home/ /etc/ /home/ /etc/ 8080 8080 443 443 Let's explain the setup in steps. 1. command defines the service you will build in Docker. services version: services: running_wp: nginx: '2' 2. As shown below, the service uses 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 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 host to port for container. running_wp nginx:latest production_wp 8081 80 version: services: running_wp: container_name: production_wp image: boraozkan/nginx:latest volumes: - - - - user: root restart: always ports: - environment: MYSQL_ROOT_PASSWORD: MYSQL_DATABASE: MYSQL_USER: MYSQL_PASSWORD: '2' "/home/xx/Desktop/cust/xx/html:/var/www/html" "/home/xx/Desktop/cust/xx/Docker/logs:/logs" "/home/xx/Desktop/cust/xx/Docker/database:/docker-entrypoint-initdb.d" "xx_db_data:/var/lib/mysql" "8081:80" 'xxxxx' 'production_db' 'production_admin' 'xxxxxx' 3. Assign necessary access credentials with command. environment environment: MYSQL_ROOT_PASSWORD: MYSQL_DATABASE: MYSQL_USER: MYSQL_PASSWORD: 'xxxxx' 'production_db' 'production_admin' 'xxxxxx' 4. Assign the base image and container name. Base image will create Nginx on the first run. You can also add encrypted SSL files through , it is free. https://letsencrypt.org/ version: nginx: image: nginx:latest container_name: production_nginx volumes: - xx/Desktop/cust/xx/Docker/nginx/reverse_proxy.conf: nginx/conf.d/ .conf - xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.pem: nginx/cert/star_xx_com.pem - xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.key: nginx/cert/star_xx_com.key - xx/Desktop/cust/xx/Docker/nginx/cert/star_xx_com.crt: nginx/cert/star_xx_com.crt ports: - : - : links: - running_wp volumes: xx_db_data: '2' /home/ /etc/ default /home/ /etc/ /home/ /etc/ /home/ /etc/ 8080 8080 443 443 5. Add Nginx configuration file under path - this is the default directory for virtual host descriptions. conf.d /home/xx/Desktop/cust/xx/Docker/nginx/reverse_proxy.conf: nginx/conf.d/ .conf /etc/ default 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 ( and ). Secondly, the forward traffic would be directed to port - this is the port of production container for reaching. 8080 443 8081 # re-route everything to production_wp server { listen ; server_name production_wp; error_page http: ssl on; ssl_certificate /etc/nginx/cert/star_xx_com.crt; ssl_certificate_key /etc/nginx/cert/star_xx_com.key; location /wp { proxy_pass http: rewrite /wp(.*) /origin-d$ proxy_pass http: proxy_redirect / href= 8080 497 //$host:80$request_uri; //localhost:8081/wp; 1 //localhost:8081; /wp; sub_filter 'href="/ ' ' "/wp' } } # wordpress container via production_wp server { listen 443; server_name production_wp; error_page 497 http://$host:80$request_uri; 7. Enable secure HTTP with the command. ssl on ssl on; ssl_certificate /etc/nginx/cert/star_xx_com.crt; ssl_certificate_key /etc/nginx/cert/star_xx_com.key; 8. To prefix headers for proxy connections, we can use the directive which helps in redefining or appending fields to the request header passed through the proxied server. proxy_set_header proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; 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 conf. Let us say it is using e.g, to which is asymmetric path. http://localhost/wp http://localhost:8081 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 while starting containers. docker-compose.yaml docker-compose up -d 11. The command is a shorthand form of and . docker-compose up docker-compose build docker-compose run #docker-compose up -d Pulling nginx (nginx:latest)... : Pulling nginx:latest b8f262c62ec6: Pulling fs layer a98660e7def6: Pulling fs layer d75689ceb37: Pulling fs layer eb0368afa: Waiting e9c: Waiting d44b3ce98: Waiting beb665ea0e0e: Pulling fs layer c98a22d85c62: Waiting bf70d116f1d7: Waiting f2d71621e0: Waiting ea02a46a87c8: Waiting fff17c3a50: Waiting 2.1 from 4 639 99e337926 431 97 78 12. When complete, we should have two containers deployed, one of which we cannot access directly: $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c327bb01a85 nginx:latest minutes ago Up minutes : -> /tcp, : -> /tcp production_nginx ce1f25d8 boraozkan/nginx:latest minutes ago Up minutes /tcp, : -> /tcp production_wp 9 "nginx -g 'daemon of…" 8 8 0.0 .0 .0 8080 8080 0.0 .0 .0 443 443 3823 "/usr/bin/supervisord" 8 8 3306 0.0 .0 .0 8081 80 13. We can check our applications (one with Nginx and the other one with Apache). Navigate to , and this will hit which will in turn will load the Nginx web application: http://localhost:8080 Nginx Reverse Proxy 14. Also check with navigating to or , through the Nginx Reverse Proxy and the Apache web application will be loaded: http://localhost:8081 http://localhost/wp asymmetric path Troubleshooting Once the services are up, try to connect your web application to the localhost link. If it is not answered, check your table for correctness. iptables 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 masquerading rule on the host machine that the Docker server creates when it starts: iptables $ sudo iptables -t nat -L -n ... Chain POSTROUTING (policy ACCEPT) target prot opt source destination 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 configuration on containers. Using this will give you additional flexibility during deployment of a web application. Reverse Proxy I hope you liked this post! More to come soon. Till then, here are some more Kubernetes and Docker best practices for managing and deploying containers.