通过 nginx-proxy 实现自动反向代理和 HTTPS
本章節代碼已經上傳至?https://github.com/siegrainwong/.NET-Core-with-Docker/tree/master/Part3
系列大綱
這次我們講第三篇:
用 docker-compose 啟動 WebApi 和 SQL Server
在容器中集成 Skywalking APM
通過 nginx-proxy 對 Portainer、Skywalking、WebApi 實現自動反向代理和 HTTPS
通過 Azure DevOps 進行 CI/CD 和藍綠發布
本章的東西很簡單,沒有特定的故障排除章節。
這里先糾正一個之前在大綱上的筆誤,之前本章的標題其實是通過 nginx-proxy 對 ES、Skywalking、WebApi 實現自動反向代理和 HTTPS,ES 是錯的,ES 沒啥好反代的因為它不需要外網訪問,這里是純筆誤,需要反代的是 Portainer。
經過我們第一章、第二章的學習,docker-compsoe的對外服務已經有了兩個,經過本章新加的 Portainer 后會達到三個,這時候就會有個問題,能不能用一個統一的服務器來管理這些外網入口,從而在負載均衡、安全性、隔離性等問題上都有所保證?
答案就是用 nginx 反向代理,但 nginx 配置寫起來也挺麻煩的,有沒有能根據 docker-compose 上的配置自動生成 nginx 配置的東西?答案就是 nginx-proxy 。
除此之外,nginx-proxy 還能自動幫你從 Let's Encrypt 上申請免費的 HTTPS 證書,簡直是不要太好用,不過因為申請證書要驗證網站所有權,你的服務器必須要被外網訪問到才行,所以這一章只能先配置好,效果是看不到的。
集成 Portainer
我們現在的容器經過這幾章后會“膨脹”到七個或者更多,每次都通過命令來查看容器的狀態太麻煩,效率也低,那么 Portainer 就成了解放雙手的好工具了。
我們先把上一章在 docker-compose.yml 中注釋掉的 webapi 放出來,因為本章不需要改 webapi 的代碼。
接下來,Portainer 的集成肥腸簡單,在 docker-compose.yml 中添加一個 service 多掛載個 volume 就行了:
# another services... portainer: image: portainer/portainer container_name: portainer command: -H unix:///var/run/docker.sock restart: always ports: - 9000:9000 volumes: - //var/run/docker.sock:/var/run/docker.sock - portainer_data:/datavolumes: # another volumes... portainer_data:然后,在項目根目錄執行docker-compose up -d
訪問localhost:9000,將出現如下的初始化界面:
進去之后,可以很方便的查看各個容器的情況、資源占用、日志、網絡等信息,大家就進去多點兩下就知道有多好使了。
集成 nginx-proxy
添加 docker-compose.prod.yml
看名字應該就知道,這是專門用于發布的 docker-compose 配置文件,因為我們開發階段是不需要用到這個反向代理的。
在 docker-compose.yml 相同目錄位置添加 docker-compose.prod.yml 文件
version: '3.3'services: coreapi: environment: VIRTUAL_HOST: coreapi.com VIRTUAL_PORT: 5000 sw-ui: environment: VIRTUAL_HOST: s.coreapi.com VIRTUAL_PORT: 8080 portainer: environment: VIRTUAL_HOST: d.coreapi.com VIRTUAL_PORT: 9000 nginx-proxy: container_name: nginx-proxy image: jwilder/nginx-proxy:alpine ports: - 80:80 - 443:443 volumes: - conf:/etc/nginx/conf.d - vhost:/etc/nginx/vhost.d - html:/usr/share/nginx/html - dhparam:/etc/nginx/dhparam - certs:/etc/nginx/certs:ro - /var/run/docker.sock:/tmp/docker.sockvolumes: conf: vhost: html: dhparam: certs:新建 launch.prod.ps1 腳本
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d添加 docker-compose.dev.yml
在我們發布上線后,唯一對外的流量入口就只能有 nginx 反向代理,所以要把 docker 對于宿主機的映射端口都去掉,并轉移到 docker-compose.dev.yml 中
docker-compose.yml:
version: '3.3'services: coreapi: container_name: coreapi image: siegrainwong/coreapi:latest depends_on: - sqlserver links: - sqlserver volumes: - ./Core.API/appsettings.docker.json:/app/appsettings.json:ro environment: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES: SkyAPM.Agent.AspNetCore SKYWALKING__SERVICENAME: coreapi restart: always sqlserver: image: mcr.microsoft.com/mssql/server:2017-latest container_name: sqlserver restart: always environment: ACCEPT_EULA: Y MSSQL_PID: Developer SA_PASSWORD: 'NetCore123!@#' volumes: - coredata:/var/opt/mssql ports: - 1433 elasticsearch: image: wutang/elasticsearch-shanghai-zone:6.3.2 container_name: elasticsearch restart: always ports: - 9200 - 9300 environment: discovery.type: single-node ES_JAVA_OPTS: "-Xmx256m -Xms256m" ulimits: memlock: soft: -1 hard: -1 sw-oap: image: siegrainwong/skywalking-oap:6.1.0 container_name: sw-oap depends_on: - elasticsearch links: - elasticsearch restart: always ports: - 11800 - 12800 environment: SW_STORAGE: elasticsearch SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200 sw-ui: image: apache/skywalking-ui:6.1.0 container_name: sw-ui depends_on: - sw-oap links: - sw-oap restart: always environment: SW_OAP_ADDRESS: sw-oap:12800 portainer: image: portainer/portainer container_name: portainer command: -H unix:///var/run/docker.sock restart: always volumes: - //var/run/docker.sock:/var/run/docker.sock - portainer_data:/datavolumes: coredata: portainer_data:docker-compose.dev.yml:
version: "3.3"services: coreapi: ports: - 5000:5000 sw-ui: ports: - 8080:8080 portainer: ports: - 9000:9000修改 launch.ps1,注意替換腳本中的路徑喲。
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -ddocker run --rm -it ` -v F:\Projects\docker-netcore\Part3:/app/ ` -v F:\Projects\docker-netcore\Part3\Core.API\appsettings.docker.json:/app/Core.API/appsettings.Development.json:ro ` -p 5000:5000 ` --link sw-oap ` --link sqlserver ` --name coreapi_dev ` --network part3_default ` --env ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore ` --env SKYWALKING__SERVICENAME=coreapi ` -w /app/Core.API mcr.microsoft.com/dotnet/core/sdk:2.2-stretch dotnet watch run執行 launch.prod.ps1 腳本
等待容器重新創建完畢,你會發現 localhost:9000、localhost:5000 等等都不能訪問了,因為我們關掉了映射,現在只有 nginx 可以訪問。
那么我們通過 curl 命令對 nginx 反代的服務進行訪問,以下命令二選一:
# powershellcurl -H @{'Host' = 'coreapi.com'} localhost/api/values# cmdurl -H "Host: coreapi.com" localhost/api/values如果你想查看生成出來的 nginx config 是什么樣的,或者你想通過這個來排錯,可以進入到 nginx-proxy 的控制臺執行cat /etc/nginx/conf.d/default.conf
不出意外的話,此刻你已經將三個需要外部訪問的容器全都通過 nginx 反代成功了。
配置 Let's Encrypt
這個配置也非常簡單,所以雖然看不出效果,但我還是放在這一章來講了,因為幾乎不會有坑,或者說我的這個方法幾乎不會有坑。
把 docker-compose.prod.yml 改成這樣,添加了三個環境變量跟一個服務,注意幾個加了注釋的地方:
version: '3.3'services: coreapi: environment: VIRTUAL_HOST: coreapi.com VIRTUAL_PORT: 5000 LETSENCRYPT_HOST: yourdomain.com # <- your domain here sw-ui: environment: VIRTUAL_HOST: s.coreapi.com VIRTUAL_PORT: 8080 LETSENCRYPT_HOST: s.yourdomain.com # <- your domain here portainer: environment: VIRTUAL_HOST: d.coreapi.com VIRTUAL_PORT: 9000 LETSENCRYPT_HOST: d.yourdomain.com # <- your domain here nginx-proxy: container_name: nginx-proxy image: jwilder/nginx-proxy:alpine ports: - 80:80 - 443:443 volumes: - conf:/etc/nginx/conf.d - vhost:/etc/nginx/vhost.d - html:/usr/share/nginx/html - dhparam:/etc/nginx/dhparam - certs:/etc/nginx/certs:ro - /var/run/docker.sock:/tmp/docker.sock letsencrypt: # <- add letsencrypt service image: jrcs/letsencrypt-nginx-proxy-companion container_name: letsencrypt environment: DEFAULT_EMAIL: youremail@gmail.com # <- using your email address NGINX_PROXY_CONTAINER: nginx-proxy volumes: - conf:/etc/nginx/conf.d - vhost:/etc/nginx/vhost.d - html:/usr/share/nginx/html - dhparam:/etc/nginx/dhparam - certs:/etc/nginx/certs:rw - /var/run/docker.sock:/var/run/docker.sock:ro network_mode: bridgevolumes: conf: vhost: html: dhparam: certs:這里的 yourdomain.com 顧名思義就是要修改成你的域名,letsencrypt 服務會在你的網站開始執行并能夠被外網訪問之后試圖從 Let's Encrypt 根據你填寫的 LETSENCRYPT_HOST 環境變量來申請證書。
需要注意的是每個月能申請的域名是有限的,所以不要亂寫,然后沒有發布到外網之前這個 compose file 我也不建議你執行 23333。
如果你自己有服務器那就自便了,具體方法是把 coreapi publish 到 dockerhub 或其他鏡像服務器,將幾個 compose 文件和腳本文件扔到服務器上跑就行了。
如果你還沒有域名話就買一個,而且下一章會用到服務器,沒有服務器的同學參照第一章開頭的介紹來獲取一個服務器,這里要說明的是我們要用的是 linux 的服務器,我個人使用的是 CentOS 7,配置要求單核,有個 4G 的內存就行了,因為 Skywalking 是 java 的那一套所以會比較吃內存(黑 java 成就達成)。
原文地址:https://siegrain.wang/article/2019/07/21/using-nginx-proxy-with-docker-compose
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的通过 nginx-proxy 实现自动反向代理和 HTTPS的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 动手造轮子:实现一个简单的 EventB
 - 下一篇: MediatR-进程内的消息通信框架