通过 nginx-proxy 实现自动反向代理和 HTTPS
本章節(jié)代碼已經(jīng)上傳至?https://github.com/siegrainwong/.NET-Core-with-Docker/tree/master/Part3
系列大綱
這次我們講第三篇:
用 docker-compose 啟動 WebApi 和 SQL Server
在容器中集成 Skywalking APM
通過 nginx-proxy 對 Portainer、Skywalking、WebApi 實現(xiàn)自動反向代理和 HTTPS
通過 Azure DevOps 進(jìn)行 CI/CD 和藍(lán)綠發(fā)布
本章的東西很簡單,沒有特定的故障排除章節(jié)。
這里先糾正一個之前在大綱上的筆誤,之前本章的標(biāo)題其實是通過 nginx-proxy 對 ES、Skywalking、WebApi 實現(xiàn)自動反向代理和 HTTPS,ES 是錯的,ES 沒啥好反代的因為它不需要外網(wǎng)訪問,這里是純筆誤,需要反代的是 Portainer。
經(jīng)過我們第一章、第二章的學(xué)習(xí),docker-compsoe的對外服務(wù)已經(jīng)有了兩個,經(jīng)過本章新加的 Portainer 后會達(dá)到三個,這時候就會有個問題,能不能用一個統(tǒng)一的服務(wù)器來管理這些外網(wǎng)入口,從而在負(fù)載均衡、安全性、隔離性等問題上都有所保證?
答案就是用 nginx 反向代理,但 nginx 配置寫起來也挺麻煩的,有沒有能根據(jù) docker-compose 上的配置自動生成 nginx 配置的東西?答案就是 nginx-proxy 。
除此之外,nginx-proxy 還能自動幫你從 Let's Encrypt 上申請免費的 HTTPS 證書,簡直是不要太好用,不過因為申請證書要驗證網(wǎng)站所有權(quán),你的服務(wù)器必須要被外網(wǎng)訪問到才行,所以這一章只能先配置好,效果是看不到的。
集成 Portainer
我們現(xiàn)在的容器經(jīng)過這幾章后會“膨脹”到七個或者更多,每次都通過命令來查看容器的狀態(tài)太麻煩,效率也低,那么 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:然后,在項目根目錄執(zhí)行docker-compose up -d
訪問localhost:9000,將出現(xiàn)如下的初始化界面:
進(jìn)去之后,可以很方便的查看各個容器的情況、資源占用、日志、網(wǎng)絡(luò)等信息,大家就進(jìn)去多點兩下就知道有多好使了。
集成 nginx-proxy
添加 docker-compose.prod.yml
看名字應(yīng)該就知道,這是專門用于發(fā)布的 docker-compose 配置文件,因為我們開發(fā)階段是不需要用到這個反向代理的。
在 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
在我們發(fā)布上線后,唯一對外的流量入口就只能有 nginx 反向代理,所以要把 docker 對于宿主機(jī)的映射端口都去掉,并轉(zhuǎn)移到 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執(zhí)行 launch.prod.ps1 腳本
等待容器重新創(chuàng)建完畢,你會發(fā)現(xiàn) localhost:9000、localhost:5000 等等都不能訪問了,因為我們關(guān)掉了映射,現(xiàn)在只有 nginx 可以訪問。
那么我們通過 curl 命令對 nginx 反代的服務(wù)進(jìn)行訪問,以下命令二選一:
# powershellcurl -H @{'Host' = 'coreapi.com'} localhost/api/values# cmdurl -H "Host: coreapi.com" localhost/api/values如果你想查看生成出來的 nginx config 是什么樣的,或者你想通過這個來排錯,可以進(jìn)入到 nginx-proxy 的控制臺執(zhí)行cat /etc/nginx/conf.d/default.conf
不出意外的話,此刻你已經(jīng)將三個需要外部訪問的容器全都通過 nginx 反代成功了。
配置 Let's Encrypt
這個配置也非常簡單,所以雖然看不出效果,但我還是放在這一章來講了,因為幾乎不會有坑,或者說我的這個方法幾乎不會有坑。
把 docker-compose.prod.yml 改成這樣,添加了三個環(huán)境變量跟一個服務(wù),注意幾個加了注釋的地方:
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 服務(wù)會在你的網(wǎng)站開始執(zhí)行并能夠被外網(wǎng)訪問之后試圖從 Let's Encrypt 根據(jù)你填寫的 LETSENCRYPT_HOST 環(huán)境變量來申請證書。
需要注意的是每個月能申請的域名是有限的,所以不要亂寫,然后沒有發(fā)布到外網(wǎng)之前這個 compose file 我也不建議你執(zhí)行 23333。
如果你自己有服務(wù)器那就自便了,具體方法是把 coreapi publish 到 dockerhub 或其他鏡像服務(wù)器,將幾個 compose 文件和腳本文件扔到服務(wù)器上跑就行了。
如果你還沒有域名話就買一個,而且下一章會用到服務(wù)器,沒有服務(wù)器的同學(xué)參照第一章開頭的介紹來獲取一個服務(wù)器,這里要說明的是我們要用的是 linux 的服務(wù)器,我個人使用的是 CentOS 7,配置要求單核,有個 4G 的內(nèi)存就行了,因為 Skywalking 是 java 的那一套所以會比較吃內(nèi)存(黑 java 成就達(dá)成)。
原文地址:https://siegrain.wang/article/2019/07/21/using-nginx-proxy-with-docker-compose
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結(jié)
以上是生活随笔為你收集整理的通过 nginx-proxy 实现自动反向代理和 HTTPS的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动手造轮子:实现一个简单的 EventB
- 下一篇: MediatR-进程内的消息通信框架