Running an NGINX reverse proxy with Docker and Let's Encrypt on Compute Engine  |  Google Cloud Platform Community

Ask questions Research chat →

https://cloud.google.com/community/tutorials/nginx-reverse-proxy-docker · scraped

deploy

Attachments

Scraped Content

— 1332 words · 2026-02-14 17:41:39 UTC ·

Excerpt

## Objectives - Create a Compute Engine instance. - Run an NGINX reverse proxy. - Run multiple web applications in Docker. - Install SSL/TLS certificates with Let's Encrypt. ## Setting up the virtual machine Create a new Compute Engine instance using the CoreOS stable image. CoreOS comes with Docker pre-installed and supports automatic system updates. 1. Open the Cloud Console. 2. Create a new Compute Engine instance. 3. Select the desired Zone, such as "us-central1-f". 4. Select the desired Machine type, such as "micro" (f1-micro). 5. Change the Boot disk to "CoreOS stable". 6. Check the boxes to allow HTTP and HTTPS traffic in the Firewall section. 7. Expand the Management, disk, networking section. 8. Click the Networking tab. 9. Select New static IP address under External IP. 10. Give the IP address a name, such as "reverse-proxy". 11. Click the Create button to create the Compute Engine instance. ## Set up some domains for your instance Create multiple A type DNS records for v
## Objectives - Create a Compute Engine instance. - Run an NGINX reverse proxy. - Run multiple web applications in Docker. - Install SSL/TLS certificates with Let's Encrypt. ## Setting up the virtual machine Create a new Compute Engine instance using the CoreOS stable image. CoreOS comes with Docker pre-installed and supports automatic system updates. 1. Open the Cloud Console. 2. Create a new Compute Engine instance. 3. Select the desired Zone, such as "us-central1-f". 4. Select the desired Machine type, such as "micro" (f1-micro). 5. Change the Boot disk to "CoreOS stable". 6. Check the boxes to allow HTTP and HTTPS traffic in the Firewall section. 7. Expand the Management, disk, networking section. 8. Click the Networking tab. 9. Select New static IP address under External IP. 10. Give the IP address a name, such as "reverse-proxy". 11. Click the Create button to create the Compute Engine instance. ## Set up some domains for your instance Create multiple A type DNS records for various domains/subdomains on your DNS provider pointing at the external IP address for your new instance. For example, in Google Domains, open DNS for your domain, scroll to Custom resource records and add an A type record. The name "@" corresponds to the root of your domain or you can change it to a subdomain, such as "a" and "b". This tutorial assumes that you have two subdomains with A records: - a.example.com - b.example.com ## Setting up the reverse proxy To have the separate websites respond only to their respective hosts, you use a reverse proxy. This tutorial uses the nginx-proxy Docker container to automatically configure NGINX to forward requests to the corresponding website. As an example, this tutorial shows a plain NGINX server running as site A and a plain Apache server running as site B. 1. Run the reverse proxy. ```plain text docker run -d \     --name nginx-proxy \     -p 80:80 \     -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy ``` 2. Start the container for site A, specifying the domain name in the VIRTUAL_HOST variable. ```plain text docker run -d --name site-a -e VIRTUAL_HOST=a.example.com nginx ``` 3. Check out your website at http://a.example.com. 4. With site A still running, start the container for site B. ```plain text docker run -d --name site-b -e VIRTUAL_HOST=b.example.com httpd ``` 5. Check out site B at http://b.example.com. Congratulations, you are running multiple apps on the same host using Docker and an nginx reverse proxy. Note: If you do not wish to set up HTTPS for your websites using Let's Encrypt, you can skip reading the rest of this tutorial. ## Setting up HTTPS with Let's Encrypt Plain HTTP is not secure. It is not encrypted and is vulnerable to man-in-the-middle attacks. In this step, you'll add support for the HTTPS protocol. 1. Stop the containers. ```plain text docker stop site-a docker stop site-b docker stop nginx-proxy ``` 2. Remove the containers. ```plain text docker rm site-a docker rm site-b docker rm nginx-proxy ``` To enable HTTPS via TLS/SSL, your reverse proxy requires cryptographic certificates. Use Let's Encrypt via the Docker Let's Encrypt nginx-proxy companion to automatically issue and use signed certificates. 1. Create a directory to hold the certificates. 2. Run the proxy, but this time declaring volumes so that the Let's Encrypt companion can populate them with certificates. ```plain text docker run -d -p 80:80 -p 443:443 \     --name nginx-proxy \     -v $HOME/certs:/etc/nginx/certs:ro \     -v /etc/nginx/vhost.d \     -v /usr/share/nginx/html \     -v /var/run/docker.sock:/tmp/docker.sock:ro \     --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true \     jwilder/nginx-proxy ``` 3. Run the Let's Encrypt companion container. ```plain text docker run -d \     --name nginx-letsencrypt \     --volumes-from nginx-proxy \     -v $HOME/certs:/etc/nginx/certs:rw \     -v /var/run/docker.sock:/var/run/docker.sock:ro \     jrcs/letsencrypt-nginx-proxy-companion ``` 4. Run site A. In addition to VIRTUAL_HOST, specify LETSENCRYPT_HOST to declare the host name to use for the HTTPS certificate. Specify the LETSENCRYPT_EMAIL so that Let's Encrypt can email you about certificate expirations. ```plain text docker run -d \     --name site-a \     -e 'LETSENCRYPT_EMAIL=webmaster@example.com' \     -e 'LETSENCRYPT_HOST=a.example.com' \     -e 'VIRTUAL_HOST=a.example.com' nginx ``` 5. You can watch the companion creator request new certificates by watching the logs. You should eventually see a log which says Saving cert.pem. 6. After the certificate is issued, check out your website at https://a.example.com. 7. Run site B. ```plain text docker run -d \     --name site-b \     -e 'LETSENCRYPT_EMAIL=webmaster@example.com' \     -e 'LETSENCRYPT_HOST=b.example.com' \     -e 'VIRTUAL_HOST=b.example.com' httpd ``` 8. You can watch the companion creator request new certificates by watching the logs. You should eventually see a log which says Saving cert.pem. 9. After the certificate is issued, check out your website at https://b.example.com. Congratulations, your web apps are now running behind an HTTPS reverse proxy. ## Proxying composed web apps In order to proxy the nginx-proxy container and the web app container must be on the same Docker network. When you run a multi-container web app with docker-compose, Docker attaches the containers to a default network. The default network is different from the bridge network that containers run with the docker run command attach to. If you run the docker-compose and have specified a VIRTUAL_HOST environment variable in the docker-compose.yml configuration file, you'll see this error message in the docker logs nginx-proxy output: ```plain text no servers are inside upstream ``` The proxy will also stop working. To resolve this, 1. Create a new Docker network. ```plain text docker network create --driver bridge reverse-proxy ``` 2. Stop and remove your web application containers, the nginx-proxy container, and the nginx-letsencrypt container. ```plain text docker stop my-container docker rm my-container docker stop nginx-proxy docker rm nginx-proxy docker stop nginx-letsencrypt docker rm nginx-letsencrypt ``` 3. Run the proxy and other containers, specifying the network with the -net reverse-proxy command-line parameter. Run the proxy container. ```plain text docker run -d -p 80:80 -p 443:443 \     --name nginx-proxy \     --net reverse-proxy \     -v $HOME/certs:/etc/nginx/certs:ro \     -v /etc/nginx/vhost.d \     -v /usr/share/nginx/html \     -v /var/run/docker.sock:/tmp/docker.sock:ro \     --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true \     jwilder/nginx-proxy ``` Run the Let's Encrypt helper container. ```plain text docker run -d \     --name nginx-letsencrypt \     --net reverse-proxy \     --volumes-from nginx-proxy \     -v $HOME/certs:/etc/nginx/certs:rw \     -v /var/run/docker.sock:/var/run/docker.sock:ro \     jrcs/letsencrypt-nginx-proxy-companion ``` Run your website containers. ```plain text docker run -d \     --name site-a \     --net reverse-proxy \     -e 'LETSENCRYPT_EMAIL=webmaster@example.com' \     -e 'LETSENCRYPT_HOST=a.example.com' \     -e 'VIRTUAL_HOST=a.example.com' nginx ``` 4. Modify the docker-compose.yml file to include the network you created in the networks definition. ```plain text networks:   reverse-proxy:     external:       name: reverse-proxy   back:     driver: bridge ``` In the container definitions, specify the appropriate networks. Only the web server needs to be on the reverse-proxy network. The other containers can stay on their own network. The final docker-compose.yml file will look something like this: ```plain text version: '2' services:   db:     restart: always     image: my_database     networks:       - back   web:     restart: always     image: my_webserver     networks:       - reverse-proxy       - back     environment:       - VIRTUAL_PORT=1234       - VIRTUAL_HOST=c.example.com       - LETSENCRYPT_HOST=c.example.com       - LETSENCRYPT_EMAIL=webmaster@example.com networks:   reverse-proxy:     external:       name: reverse-proxy   back:     driver: bridge ``` 5. Run the docker-compose up -d command to run your composed containers with the new configuration. ## Surviving reboots When your Compute Engine instance restarts, the Docker containers will not automatically restart. Use the --restart flag for the docker run command to specify a Docker restart policy. I suggest always or unless-stopped so that Docker restarts the containers on reboot.

Visibility

Visible to everyone

Reading Status

Related Bookmarks

My Note


Saved!

Annotations

Export as Markdown
+ Annotate selection

Add Annotation