简介
想象一下,当您设置本地服务器并基于它创建前端应用程序时。要访问应用程序的 API,您可以输入 example.com:3000,对于应用程序,您可以输入类似 example.com:4040 的内容。一个应用程序可以有多个端口来访问不同的页面:主页、仪表板、联系人、表格等。现在想象一下记住多个应用程序的多个端口。
只做这样的事情来访问 API:example.com/api 和应用程序:example.com/app 并不是很好。您可以为多个容器建立路由,而不是输入愚蠢的端口,这些路由 URL 可以是任何东西。使用 docker 的反向代理更容易完成。
什么是代理?
让我试着用一个比喻来解释它。假设您走进您最喜欢的餐厅。你饿了。你想吃你最喜欢的食物。你给服务员点菜。服务员接过您的订单,然后去厨房。服务员要求厨师烹制您向服务员提出的所有要求。厨师烹制食物。服务员端来你的食物。简单的?
需要注意的关键事项:您要求服务员。服务员没有让你去厨房就满足了你的要求。厨师不知道那是给谁吃的。
在此示例中,服务员是代理,厨师是互联网。代理充当您和互联网之间的防火墙。代理提供安全、隐私和其他级别的功能。您可以在尼日利亚设置代理服务器。然后您可以在互联网上发出 HTTP 请求,该请求将首先发送到尼日利亚,然后以简单的语言发送到互联网上。
代理的另一个示例是一个公司或建筑物中的多台计算机。公司内部的所有计算机的IP地址都在公司的最高IP地址之下。所有互联网请求都是在一个 IP 地址下发出的,这使得追溯至个人计算机变得更加困难。
代理就是发出安全的外部请求。
[](https://res.cloudinary.com/practicaldev/image/fetch/s–BtG2msWx–/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/pof59a600nrxa1qaihzm.png)
什么是反向代理
如果我不在这里进行类比,那将是不公平的。这个比喻是老生常谈了。免责声明:不要评判我,我是一个精通技术的人。假设你早上醒来,你看到门上的邮递员。 Postman 为您提供多封信件、发票、明信片和其他形式的信件。所有这些信件都是从不同的地方发出的,但它们最终都会在正确的地方寄给你。
注意: 发件人不必与您直接联系。邮递员代表您从多个来源检索信件。
在这个例子中,邮递员是一个反向代理,源是客户端,你正在申请。客户端发出 HTTP 请求以与您的应用程序通信。客户端想要查看应用程序,因此客户端创建此请求:example.com。但在幕后反向代理将此请求转换为 example.com:8080。如果客户端或用户想要查看 API,则客户端创建此请求:example.com/api,但在后台,反向代理将其转换为 example.com:3000。反向代理位于 Web 服务器的前面,并将客户端请求转发到服务器。反向代理通常用于提高安全性、性能和可靠性。
反向代理可让您发出安全的内部请求。
[](https://res.cloudinary.com/practicaldev/image/fetch/s–_GSXASml–/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/divaqvxzhf3g940ea4oh.jpeg)
什么是 Docker?
Docker 是一种流行的企业 PAAS(平台即服务),用于使用容器创建、运行和部署应用程序。容器允许开发人员将应用程序与必要的模块、库、依赖项打包在一起,并将其部署为其中一个包。 Docker 位于现有的主机操作系统上,允许开发人员在虚拟机上制作轻量级容器来运行他们的应用程序。因此,开发人员可以在一个主机操作系统上创建多个容器并运行多个应用程序。企业不必花钱购买多个操作系统来部署单个应用程序。
[](https://res.cloudinary.com/practicaldev/image/fetch/s–lzqPKIQw–/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/8l2lztj2ws71trwt3qjb.png)
如何设置 NGINX Docker 反向代理
让我们建立一个使用 docker 设置 NGINX 反向代理的用例。在 docker 容器内,除非绑定到主机,否则无法访问私有端口和 IP 地址。我们可以使用反向代理通过单个端口 80 访问在多个容器上运行的多个 Web 应用程序。我们将设置 Nginx 容器,该容器将绑定到端口 80 到 docker 主机的端口 80,它将请求转发到运行的 Web 应用程序多个容器。
[](https://res.cloudinary.com/practicaldev/image/fetch/s–VU4lgdPv–/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/dfh0sjzmd8q7jwtr4ay0.png)
我们需要为 Web 服务或两个可以用任何语言编写的应用程序设置两个容器。但是为了教程的方便,让我们用一个简单的 index.html 页面创建两个 Web 服务。
我们的网络服务 1 的结构:
webservice1 ├── docker-compose.yml └── index.html
进入全屏模式 退出全屏模式
cd ~ mkdir webservice1 cd webservice1 vi docker-compose.yml
进入全屏模式 退出全屏模式
然后将此 YAML 代码粘贴到文件中:
version: '2' services: app: image: nginx:1.9 volumes: - .:/usr/share/nginx/html/ expose: - "80"
进入全屏模式 退出全屏模式
快速提示:确保所有 YAML 文件的缩进格式正确。您还可以使用 VS Code 正确格式化它们。
现在,让我们为 webservice1 创建一个简单的 HTML 页面:
vi index.html
进入全屏模式 退出全屏模式
<!DOCTYPE html> <html> <head> <title>Web service 1</title> </head> <body> <h1>Welcome to website 1</h1> </body> </html>
进入全屏模式 退出全屏模式
现在,使用 docker-compose 命令构建 webservice1
docker-compose build
进入全屏模式 退出全屏模式
启动容器
docker-compose up -d
进入全屏模式 退出全屏模式
列出所有容器
docker ps -a
进入全屏模式 退出全屏模式
您应该会看到带有名称的容器:
site2_app_1
进入全屏模式 退出全屏模式
同样,为 webservice2 创建第二个容器
cd ~ mkdir webservice2 cd webservice2 vi docker-compose.yml
进入全屏模式 退出全屏模式
YAML 文件的代码:
version: '2' services: app: image: nginx:1.9 volumes: - .:/usr/share/nginx/html/ expose: - "80"
进入全屏模式 退出全屏模式
创建索引文件
vi index.html
进入全屏模式 退出全屏模式
创建一个简单的 HTML 响应
<!DOCTYPE html> <html> <head> <title>Web service 2</title> </head> <body> <h1>Welcome to website 2</h1> </body> </html>
进入全屏模式 退出全屏模式
使用 docker-compose 命令构建 webservice2 容器
docker-compose build
进入全屏模式 退出全屏模式
启动容器
docker-compose up -d
进入全屏模式 退出全屏模式
伟大的!现在我们有了要绑定到代理的两个正在运行的 docker 容器。注意:这两个容器都应该在端口 80 上运行,因此我们必须设置一个代理来相应地引导请求。所以让我们设置代理。
这将是代理的文件结构:
proxy/ ├── backend-not-found.html ├── default.conf ├── docker-compose.yml ├── Dockerfile ├── includes │ ├── proxy.conf │ └── ssl.conf └── ssl ├── site1.crt ├── site1.key ├── site2.crt └── site2.key
进入全屏模式 退出全屏模式
让我们从创建所有必要的文件开始。
cd ~ mkdir proxy cd proxy touch Dockerfile touch backend-not-found.html touch default.conf touch docker-compose.yml mkdir includes mkdir ssl cd includes touch proxy.conf touch ssl.conf
进入全屏模式 退出全屏模式
创建 Dockerfile
vi Dockerfile
进入全屏模式 退出全屏模式
FROM nginx:1.9 COPY ./default.conf /etc/nginx/conf.d/default.conf COPY ./backend-not-found.html /var/www/html/backend-not-found.html COPY ./includes/ /etc/nginx/includes/ COPY ./ssl/ /etc/ssl/certs/nginx/
进入全屏模式 退出全屏模式
Dockerfiles 用于创建 docker 镜像。然后使用 docker 镜像来创建 docker 容器。在这个 Dockerfile 中,镜像会引用已有的 Nginx docker 镜像来创建一个自定义的 docker 镜像。然后,将通过将本地计算机上的现有文件复制到 docker 映像来构建映像。我们基本上是在添加一个配置文件、基本错误 HTML、更多代理配置文件以及我们稍后将生成的认证。
创建default.conf
vi default.conf
进入全屏模式 退出全屏模式
# web service1 config. server { listen 80; listen 443 ssl http2; server_name site1.test; # Path for SSL config/key/certificate ssl_certificate /etc/ssl/certs/nginx/site1.crt; ssl_certificate_key /etc/ssl/certs/nginx/site1.key; include /etc/nginx/includes/ssl.conf; location / { include /etc/nginx/includes/proxy.conf; proxy_pass http://site1_app_1; } access_log off; error_log /var/log/nginx/error.log error; } # web service2 config. server { listen 80; listen 443 ssl http2; server_name site2.test; # Path for SSL config/key/certificate ssl_certificate /etc/ssl/certs/nginx/site2.crt; ssl_certificate_key /etc/ssl/certs/nginx/site2.key; include /etc/nginx/includes/ssl.conf; location / { include /etc/nginx/includes/proxy.conf; proxy_pass http://site2_app_1; } access_log off; error_log /var/log/nginx/error.log error; } # Default server { listen 80 default_server; server_name _; root /var/www/html; charset UTF-8; error_page 404 /backend-not-found.html; location = /backend-not-found.html { allow all; } location / { return 404; } access_log off; log_not_found off; error_log /var/log/nginx/error.log error; }
进入全屏模式 退出全屏模式
在这个 Nginx 配置文件中,两个 Webservice 都有两个主要的服务器组件。这两个容器都将监听 Nginx 端口 80。要访问这两个容器,我们可以在它们定义的 server_name 上 curl 它们:HTTP://site1.test或HTTP://site2.test。这两个服务器组件都将帮助 Nginx 将请求指示到适当的 Web 服务容器。此配置还允许 Nginx 抛出自定义错误 HTML,而不是默认的 Nginx 错误页面。两个服务器组件都指示 Nginx 从适当的位置选择 SSL 证书。
创建 docker-compose.yml
vi docker-compose.yml
进入全屏模式 退出全屏模式
version: '2' services: proxy: build: ./ networks: - site1 - site2 ports: - 80:80 - 443:443 networks: site1: external: name: site1_default site2: external: name: site2_default
进入全屏模式 退出全屏模式
注意:将我的文件复制到终端时,请确保缩进正确。
这是我们实际实现代理的主要部分。 (从技术上讲,我们是在 default.conf 中完成的)这个 docker-compose.yml 文件将两个名为 site1 和 site2 的外部网络连接到代理。这个代理的80/443端口的绑定是在Docker主机的80/443端口上实现的。我们已经为 Webservice 创建了两个 docker 容器,并创建了两个名为 site1_default 和 site2_default 的外部 docker 网络。
创建证书和密钥
对于网络服务 1
cd ssl openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout site1.key -out site1.crt
进入全屏模式 退出全屏模式
对于网络服务 2
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout site2.key -out site2.crt
进入全屏模式 退出全屏模式
现在让我们为代理创建一个标准配置。
cd includes vi proxy.conf
进入全屏模式 退出全屏模式
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_request_buffering off; proxy_http_version 1.1; proxy_intercept_errors on;
进入全屏模式 退出全屏模式
创建标准 SSL 配置以解码 SSL 证书和密钥
vi ssl.conf
进入全屏模式 退出全屏模式
ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE- ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM- SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256- GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA- AES128-SHAECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256- SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256: DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA- DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256: AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES- CBC3-SHA:!DSS'; ssl_prefer_server_ciphers on;
进入全屏模式 退出全屏模式
此配置有助于使用密文解码 SSL 证书和密钥。
让我们添加主机名和 IP 地址
cd ~ vi /etc/hosts
进入全屏模式 退出全屏模式
172.31.30.78 site1.test 172.31.30.78 site2.test
进入全屏模式 退出全屏模式
这些是 docker 主机的私有 IP 地址。请求会到达 docker 主机的 80 端口,但会被重定向到 Nginx 容器的 80 端口。
最后,让我们构建一个代理容器
docker-compose build
进入全屏模式 退出全屏模式
我们有一个容器,现在运行容器
docker-compose up -d
进入全屏模式 退出全屏模式
现在,您应该看到三个正在运行的 docker 容器。两个用于 Web 服务,一个用于代理容器。
docker ps -a
进入全屏模式 退出全屏模式
让我们验证我们的反向代理是否正常工作
curl site1.test
进入全屏模式 退出全屏模式
您应该会看到以下响应:
<!DOCTYPE html> <html> <head> <title>Web service 1</title> </head> <body> <h1>Welcome to website 1</h1> </body> </html>
进入全屏模式 退出全屏模式
很好! ✨
容器化应用程序的好处之一是您可以轻松添加和部署应用程序。您可以通过将配置添加到 default.conf 并将外部网络添加到 docker-compose YAML 文件来添加任意数量的 Web 服务容器。这个例子说明了使用 docker 和 Nginx 设置反向代理是多么容易。想象一下,有多个应用程序在 docker 容器上运行,它们的所有请求都被 Nginx 容器重定向。您无需担心手动添加配置。您可以使用 Docker API 简单地自动化该过程,这是另一个博客讨论的好概念。
感谢您阅读该博客,我希望它可以帮助您理解这个非常独特的概念。
如果您有任何问题或疑虑,请给我留言。
原文链接:https://devpress.csdn.net/cloudnative/62f930767e6682346618c1a3.html