Getting started with Docker and Docker networking can present some challenges. One of the initial hurdles is understanding the concepts of container networking, which operates differently from traditional networking. You need to familiarize yourself with concepts like bridges, overlays, network modes, and DNS resolution within Docker. This understanding is crucial to grasp how containers communicate with each other and with the host system.
Another challenge lies in choosing the appropriate networking option. Docker offers various networking options such as bridge networks, host networking, overlay networks, and macvlan networks. Selecting the right option for a specific use case can be challenging, particularly for beginners who are not yet acquainted with the characteristics and implications of each option.
Configuring networking for containers is another area that can pose difficulties. It involves creating and managing Docker networks, assigning IP addresses, defining ports, and linking containers together. Users may struggle with setting up networking configurations correctly, especially when dealing with complex multi-container setups or external connectivity requirements.
BunkerWeb is a web server that is built on the NGINX server software and is specifically focused on enhancing security. Familiar to many, NGINX is a web server and reverse proxy server with a reputation for high performance, scalability, and flexibility. It is commonly used to serve web content, handle load balancing, and act as a reverse proxy to distribute incoming requests to backend servers. By building BunkerWeb on top of NGINX, it likely leverages NGINX’s robust features and capabilities while adding security enhancements and focusing on secure web server configurations.
BunkerWeb provides several features, among them are:
- Easy Integration into Existing Environments: BunkerWeb seamlessly integrates with Linux, Docker, Swarm, and Kubernetes, making it simple to incorporate into your existing infrastructure and workflow.
- Highly Customizable: With BunkerWeb, you have the flexibility to customize and fine-tune its features to meet your specific use case. You can easily enable, disable, and configure different functionalities according to your requirements.
- Secure by Default: BunkerWeb prioritizes security by providing out-of-the-box and hassle-free minimal security measures for your web services. It is designed to ensure your applications and data are protected without requiring extensive configuration efforts.
- Free as in “Freedom”: BunkerWeb is licensed under the free AGPLv3 license, offering you the freedom to use, modify, and distribute the software. This license promotes openness and community collaboration.
- Security features such as:
- HTTPS Support with Let’s Encrypt Automation: BunkerWeb seamlessly integrates with Let’s Encrypt to automate the process of obtaining and renewing SSL/TLS certificates, ensuring secure communication with HTTPS.
- State-of-the-Art Web Security Measures: BunkerWeb implements various advanced web security measures, including HTTP security headers to enhance protection, prevention of information leaks, and robust TLS hardening configurations.
- Integrated ModSecurity WAF with OWASP Core Rule Set: BunkerWeb includes an integrated ModSecurity Web Application Firewall (WAF) that leverages the OWASP Core Rule Set, providing an additional layer of defence against web-based attacks and vulnerabilities.
- Automatic Behavior-Based Ban: BunkerWeb monitors and detects unusual behaviour from clients and automatically blocks them based on HTTP status codes, helping prevent malicious activities.
- Connections and Requests Limit: BunkerWeb allows you to set limits on client connections and requests, helping to mitigate potential abuse or resource exhaustion.
- Bot Blocking with Challenge Response: BunkerWeb offers the ability to block bots by presenting them with challenges to solve, such as cookies, JavaScript execution, captchas, hCaptcha, or reCAPTCHA, effectively filtering out automated malicious activities.
- Blacklisting Known Bad IPs with External Blacklists and DNSBL: BunkerWeb enables the use of external blacklists and DNS-based blackhole lists (DNSBL) to automatically block connections from known malicious IP addresses.
Now let’s learn how to run Nginx Web Server in Docker Container using BunkerWeb.
#1. Install Docker and Docker Compose
This guide requires you to have Docker Engine and Docker Compose installed. To install Docker, follow the below guide:
After the installation, ensure that docker has been started and enabled:
sudo systemctl enable --now docker
You also need to add your system user to the docker group:
sudo usermod -aG docker $USER
newgrp docker
Verify the docker installation.
$ docker version
Client: Docker Engine - Community
Version: 23.0.6
API version: 1.42
Go version: go1.19.9
Git commit: ef23cbc
Built: Fri May 5 21:18:22 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 23.0.6
API version: 1.42 (minimum version 1.12)
Go version: go1.19.9
Git commit: 9dbdbd4
Built: Fri May 5 21:18:22 2023
OS/Arch: linux/amd64
......
You can also install docker-compose using the guide:
Once installed, verify with the command:
$ docker-compose version
Docker Compose version v2.18.0
#2. Provision BunkerWeb Container
When dealing with BunkerWeb, there are several concepts we need to be aware of. These concepts include:
- Integrations
The primary focus is on seamlessly integrating BunkerWeb into the target environment. The term “integration” is preferred over “installation” since BunkerWeb aims to harmoniously become a part of existing environments. The supported integrations are Docker, Docker autoconf, Swarm, Kubernetes, Linux and Ansible.
- Settings
Once BunkerWeb is seamlessly integrated into your environment, the next step involves configuring it to effectively serve and safeguard your web applications.
Configuration of BunkerWeb revolves around the utilization of “settings” or “variables.” Each setting is associated with a specific name, such as AUTO_LETS_ENCRYPT or USE_ANTIBOT, for instance. By assigning values to these settings, you can tailor BunkerWeb to meet your specific configuration requirements.
- Multisite mode
When utilizing BunkerWeb, understanding the concept of multisite mode becomes essential. The primary objective of safeguarding web applications naturally incorporates the notion of “virtual host” or “vhost” (further information available here). This concept enables the seamless hosting of multiple web applications from a single instance or a cluster. By employing multisite mode, BunkerWeb empowers you to efficiently serve and protect multiple web applications simultaneously.
When running BunkerWeb in docker containers, we observe the below architecture:
The utilization and configuration of the BunkerWeb container revolve around the following components:
- Environment Variables: BunkerWeb allows you to configure and customize its behaviour using environment variables. These variables provide a flexible way to adapt BunkerWeb to your specific use cases and requirements.
- Volume: BunkerWeb utilizes volumes to cache critical data and facilitate the mounting of custom configuration files. This enables you to persist important information and easily incorporate your own tailored configuration files into the BunkerWeb container.
- Networks: BunkerWeb employs networks to expose ports, allowing clients to access the web services served by BunkerWeb. Additionally, networks enable seamless connectivity to upstream web services, ensuring smooth communication between BunkerWeb and other components of your environment.
Now we will begin by creating a network for BunkerWeb:
docker network create bw-net
We also need to create a volume for BunkerWeb. Begin by creating a path on your host:
sudo mkdir /bw-datastore
sudo chmod 775 -R /bw-datastore
sudo chown -R $USER:docker /bw-datastore
For Rhel-based systems, configure SELinux as shown:
sudo chcon -R -t svirt_sandbox_file_t /bw-datastore
Now create a docker volume:
docker volume create --driver local \
--opt type=none \
--opt device= /bw-datastore \
--opt o=bind bw-data
View the volume;
$ docker volume ls
DRIVER VOLUME NAME
local bw-data
#3. Run BunkerWeb Docker Container
Now to run and verify that BunkerWeb is working perfectly, we need to deploy and application for the test. For this demo, we can use a sample app then create reverse proxy using Bunkerweb.
Now we will proceed and run the BunkerWeb Docker container. This can be done in two ways:
- Uisng Docker CLI
- Using Docker Compose
Option 1: Run BunkerWeb Using Docker CLI
Begin by spinning the demon app with the command:
docker run -d \
--name myapp \
--network bw-net \
nginxdemos/hello:plain-text
Then spin the BunkerWeb container with the command bearing the below syntax:
docker run -d \
--name mybunker \
--network bw-net \
-p 80:8080 \
-p 443:8443 \
-v bw-data:/data \
-e SERVER_NAME=web.geeksforgeeks.org \
-e USE_REVERSE_PROXY=yes \
-e REVERSE_PROXY_URL=/ \
-e REVERSE_PROXY_HOST=http://myapp \
bunkerity/bunkerweb:1.4.8
In the above command, we have set reverse proxy for the app we deployed earlier on the URL http://myapp.
View if the containers are running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a4dbded0a42 bunkerity/bunkerweb:1.4.8 "/opt/bunkerweb/help…" 3 seconds ago Up 2 seconds (health: starting) 80/tcp, 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp mybunker
b669d3fa1eb4 nginxdemos/hello:plain-text "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 80/tcp myapp
Option 2: Run BunkerWeb Using Docker Compose
It is also possible to run the BunkerWeb and the test app containers using a single Docker Compose file. First, create the file:
vim docker-compose.yml
In the file, add the lines below, replacing where required:
version: '3'
services:
mybunker:
container_name: mybunker
image: bunkerity/bunkerweb:1.4.8
ports:
- 80:8080
- 443:8443
volumes:
- bw-data:/data
environment:
- SERVER_NAME=web.geeksforgeeks.org
- USE_REVERSE_PROXY=yes
- REVERSE_PROXY_URL=/
- REVERSE_PROXY_HOST=http://myapp
networks:
- bw-net
myapp:
container_name: myapp
image: nginxdemos/hello:plain-text
networks:
- bw-net
volumes:
bw-data:
networks:
bw-net:
name: bw-net
Save the file and run the containers with the command:
docker-compose up -d
View if the containers are running:
$ docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
thor-myapp-1 nginxdemos/hello:plain-text "/docker-entrypoint.…" myapp 22 seconds ago Up 21 seconds 80/tcp
thor-mybunker-1 bunkerity/bunkerweb:1.4.8 "/opt/bunkerweb/help…" mybunker 22 seconds ago Up 21 seconds (healthy) 80/tcp, 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp
Test Access to Appication
If the containers are running, we can test if BunkerWeb is handling the requests as desired. We can use cURL as shown:
curl web.geeksforgeeks.org
Sample Output:
You can also load the page on your browser using the URL //web.geeksforgeeks.org
#4. Run BunkerWeb Containers With Multiple Applications
There are scenarios where you have several applications that need a reverse proxy. BunkerWeb is capable of handling the traffic and proxy the requests as required.
- For Docker CLI
Begin by spinning the apps:
##APP1
docker run -d \
--name myapp1 \
--network bw-net \
nginxdemos/hello:plain-text
##APP2
docker run -d \
--name myapp2 \
--network bw-net \
nginxdemos/hello:plain-text
##APP3
docker run -d \
--name myapp3 \
--network bw-net \
nginxdemos/hello:plain-text
Proceed and spin BunkerWeb:
docker run -d \
--name mybunker \
--network bw-net \
-p 80:8080 \
-p 443:8443 \
-v bw-data:/data \
-e MULTISITE=yes \
-e "SERVER_NAME=myapp1.geeksforgeeks.org myapp2.geeksforgeeks.org myapp3.geeksforgeeks.org" \
-e USE_REVERSE_PROXY=yes \
-e REVERSE_PROXY_URL=/ \
-e myapp1.geeksforgeeks.org_REVERSE_PROXY_HOST=http://myapp1 \
-e myapp2.geeksforgeeks.org_REVERSE_PROXY_HOST=http://myapp2 \
-e myapp3.geeksforgeeks.org_REVERSE_PROXY_HOST=http://myapp3 \
bunkerity/bunkerweb:1.4.8
View if the containers are running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
56cb582c7d5e bunkerity/bunkerweb:1.4.8 "/opt/bunkerweb/help…" 5 seconds ago Up 4 seconds (health: starting) 80/tcp, 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp mybunker
42d995f8acb6 nginxdemos/hello:plain-text "/docker-entrypoint.…" 20 seconds ago Up 19 seconds 80/tcp myapp3
6ab7df943bf2 nginxdemos/hello:plain-text "/docker-entrypoint.…" 24 seconds ago Up 23 seconds 80/tcp myapp2
4e84d030f8c9 nginxdemos/hello:plain-text "/docker-entrypoint.…" 28 seconds ago Up 27 seconds 80/tcp myapp1
- Using Docker Compose
You can spin all your apps and BunkerWeb with a single file:
vim docker-compose.yml
Add the lines below to it:
version: '3'
services:
mybunker:
container_name: mybunker
image: bunkerity/bunkerweb:1.4.8
ports:
- 80:8080
- 443:8443
volumes:
- bw-data:/data
environment:
- MULTISITE=yes
- SERVER_NAME=myapp1.geeksforgeeks.org myapp2.geeksforgeeks.org myapp3.geeksforgeeks.org
- USE_REVERSE_PROXY=yes
- REVERSE_PROXY_URL=/
- myapp1.geeksforgeeks.org_REVERSE_PROXY_HOST=http://myapp1
- myapp2.geeksforgeeks.org_REVERSE_PROXY_HOST=http://myapp2
- myapp3.geeksforgeeks.org_REVERSE_PROXY_HOST=http://myapp3
networks:
- bw-net
myapp1:
container_name: myapp1
image: nginxdemos/hello:plain-text
networks:
- bw-net
myapp2:
container_name: myapp2
image: nginxdemos/hello:plain-text
networks:
- bw-net
myapp3:
container_name: myapp3
image: nginxdemos/hello:plain-text
networks:
- bw-net
volumes:
bw-data:
networks:
bw-net:
name: bw-net
Run the containers:
docker-compose up -d
View if the containers are up:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
385de3ddfa7b nginxdemos/hello:plain-text "/docker-entrypoint.…" 21 seconds ago Up 19 seconds 80/tcp myapp1
0e3f8980f23b nginxdemos/hello:plain-text "/docker-entrypoint.…" 21 seconds ago Up 19 seconds 80/tcp myapp3
25dd1f4be099 nginxdemos/hello:plain-text "/docker-entrypoint.…" 21 seconds ago Up 19 seconds 80/tcp myapp2
4c3fdf996b05 bunkerity/bunkerweb:1.4.8 "/opt/bunkerweb/help…" 21 seconds ago Up 19 seconds (healthy) 80/tcp, 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp mybunker
Test Access to the Applications
To test if you are able to access the sites, first, modify your /etc/hosts file:
$ sudo vim /etc.hosts
192.168.200.51 myapp1.geeksforgeeks.org myapp2.geeksforgeeks.org myapp3.geeksforgeeks.org
Now you can use cURL as shown below to verify if BunkerWeb is working:
curl myapp1.geeksforgeeks.org
curl myapp2.geeksforgeeks.org
curl myapp3.geeksforgeeks.org
Sample Output:
You can also use a web browser with the required URL for example:
APP1:
APP2
APP3
#5. Configure HTTPS on BunkerWeb
It is also important to secure traffic using HTTPS. BunkerWeb allows you to use Let’s Encrypt, Custom certificate and Self-signed certs when protecting your traffic.
To enable HTTPS, you can use the below environment variables:
Setting | Default | Description |
---|---|---|
REDIRECT_HTTP_TO_HTTPS | no | If set to yes , will redirect every HTTP request to HTTPS even if BunkerWeb is not configured with HTTPS. |
AUTO_REDIRECT_HTTP_TO_HTTPS | yes | If set to yes , will redirect every HTTP request to HTTPS only if BunkerWeb is configured with HTTPS. |
HTTPS_PROTOCOLS | TLSv1.2 TLSv1.3 | This is the list of supported SSL/TLS protocols when HTTPS is enabled. |
HTTP2 | yes | If set to yes , will enable HTTP2 protocol support when using HTTPS. |
LISTEN_HTTP | yes | If set to no , BunkerWeb will not listen for HTTP requests. Useful if you want HTTPS only for example. |
To use a desired certificate, you need to declare it in your configuration as an environment variable. This can be done as shown:
- Let’s Encrypt
BunkerWeb has an automatic Let’s Encrypt certificate generation and renewal. It makes it so easy to get HTTPS working out of the box for public-facing web applications. For this to work, you need to have an FQDN. Below is a list of the environment variables involved:
Setting | Default | Description |
---|---|---|
AUTO_LETS_ENCRYPT | no | if set to yes , HTTPS will be enabled with automatic certificate generation and renewal from Let’s Encrypt. |
EMAIL_LETS_ENCRYPT | contact@{FIRST_SERVER} | This is the email address to be used when generating certificates. Let’s Encrypt will send notifications to that email such as certificate expiration. |
USE_LETS_ENCRYPT_STAGING | no | If set to yes , the staging server of Let’s Encrypt will be used instead of the production one. Useful when doing development tests to avoid being “blocked” due to limits. |
- Custom certificate
This option applies to those who want to use their own certificates. The environment variables used here are:
Setting | Default | Description |
---|---|---|
USE_CUSTOM_HTTPS | no | If set to yes , HTTPS will be enabled with custom certificates. BunkerWeb will also check every day if the custom certificate specified in CUSTOM_HTTPS_CERT is modified and reload NGINX for that case. |
CUSTOM_HTTPS_CERT | The full path to the certificate. If you have one or more intermediate certificate(s) in your chain of trust, you will need to provide the bundle (more info here). | |
CUSTOM_HTTPS_KEY | The full path to the private key. |
- Self-signed
If you do not have a Fully Qualified Domain name, you can still protect your traffic on BunkerWeb. The related settings are:
Setting | Default | Description |
---|---|---|
GENERATE_SELF_SIGNED_SSL | no | If set to yes , HTTPS will be enabled with automatic self-signed certificate generation and renewal from Let’s Encrypt. |
SELF_SIGNED_SSL_EXPIRY | 365 | This is the number of days for the certificate expiration (-days value used with openssl). |
SELF_SIGNED_SSL_SUBJ | /CN=myapp.geeksforgeeks.org/ | This is the certificate subject to use (-subj value used with openssl). |
To test if this works, we can modify our docker-compose file and add the lines in the environment section for BunkerWeb:
$ vim docker-compose.yml
version: '3'
services:
mybunker:
container_name: mybunker
image: bunkerity/bunkerweb:1.4.8
ports:
- 80:8080
- 443:8443
volumes:
- bw-data:/data
environment:
- SERVER_NAME=web.geeksforgeeks.org
- USE_REVERSE_PROXY=yes
- REVERSE_PROXY_URL=/
- REVERSE_PROXY_HOST=http://myapp
- AUTO_REDIRECT_HTTP_TO_HTTPS=yes
- GENERATE_SELF_SIGNED_SSL=yes
- SELF_SIGNED_SSL_EXPIRY=365
- SELF_SIGNED_SSL_SUBJ=/CN=web.geeksforgeeks.org/
........
Apply the changes:
docker-compose up -d
Now verify if you are able to access the app using HTTPS:
Conclusion
That marks the end of this detailed guide on how to run Nginx Web Server in Docker Container using BunkerWeb. This will help solve the networking complexity involved when dealing with complex multi-container setups or external connectivity requirements. I hope this was informative.
See more: