這個文章的題目起的比較長,我想實現這樣一個產品:php
前端是微信小程序,後端是基於docker運行的asp.net core webapi。webapi經過nginx實現的反向代理接入,nginx一樣基於docker來運行。開擼!前端
微信小程序註冊有一個限制,一個郵箱只能註冊一個小程序。我用的qq郵箱,由於以前使用qq郵箱的默認帳號註冊過一個,可是qq郵箱能夠針對同一個郵箱設置不一樣的帳戶(好像是三個),因此能夠先設置一個額外的帳號,而後經過這個帳號來註冊小程序python
你要創建api必須得有一臺服務器,我從騰訊雲申請了一臺免費的(3個月)2核心4G的服務器。linux
申請域名是有一個緣由的,你能夠參考看看是否是否和你的條件,不然,你能夠跳過這步。個人緣由是首先小程序若是要接入api這個api必須是一個https的鏈接,https的鏈接涉及到ssl/tls證書,我採用let's encrypt來獲取證書。可是let's encrypt不容許使用ip地址來獲取證書,須要域名。因此,我又申請了一個域名。域名申請在騰訊雲官網完成,花了45(原價55,10塊的代金券)塊錢申請了一個域名,有效期一年。可是須要注意你申請域名的時候必須得先有一臺服務器。服務器用於一個公網ip。nginx
當你完成購買服務器和申請域名的步驟後,能夠開始申請證書了。個人證書是經過let's encrypt來申請的,let's encrypt發佈了一個certbot的工具,經過certbot來對證書進行獲取和管理。certbot的網址是https://certbot.eff.org/web
固然還有不少其餘的工具,好比certbot-auto和acme.sh等,這裏不作過多介紹,百度吧。docker
首先是安裝certbot,我是用的是centos7,certbot是包含在epel(extra packges for enterprise linux)中的,因此須要安裝epel包源,另外,須要python的運行環境。在centos7中,這些默認都有,因此,我直接運行小程序
sudo yum install certbot
就完成了安裝。windows
關於epel的官網在這裏:https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F 你能夠對照你的操做系統來查看如何安裝這個包源。後端
關於certbot的官網在這裏:https://certbot.eff.org/lets-encrypt/centosrhel7-nginx 你能夠查看相關文檔。
安裝好以後就是獲取證書的環節了:
certbot certonly
鍵入上述命令後,根據提示操做,很快就會完成,而後在/etc/letsencrypt/live/you.domain.com
下面會有你的證書和證書對應的key證書和key都是pem文件,證書的名字是fullchain.pen,key的名字是privkey.pem.
docker:https://docs.docker.com/install/
windows開發機上的docker安裝過程省略。下面是服務器(centos7.2)的安裝步驟
centos安裝docker的條件是系統在7以上,而且開通了centos-extras包源,它默認是開啓的。從https://wiki.centos.org/AdditionalResources/Repositories上面能夠查看centos關於這方面的一些信息。確認完上述信息後,按照一下步驟來完成安裝:
sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
yum-utils
提供了 yum-config-manager
這個工具,而device-mapper-persistent-data 和lvm2對於devicemapper
存儲驅動程序來講是必須的。而後配置包源:
sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
而後安裝docker:
sudo yum install docker-ce docker-ce-cli containerd.io
安裝文檔在這裏:https://docs.docker.com/install/linux/docker-ce/centos/ 不細說了。
個人nginx是經過docker來安裝的。
docker pull nginx
上述命令會安裝最新版的nginx docker鏡像。
關於nginx的docker鏡像能夠參考我翻譯的一篇文章。
nginx的主配置文件是/etc/nginx/nginx.conf,子配置文件在/etc/nginx/conf.d/default.conf主配置文件會使用include指令來調用子配置文件。
當使用nginx鏡像時,咱們在宿主系統上寫好配置,而後經過將容器的目錄掛載到宿主的相應目錄上便可。
我建立了一個asp.net core 的webapi,這個web服務監聽了5000端口:
它的本地目錄是這樣的:
Source目錄是這樣:
列出目錄的主要目的是要書寫Dockerfile。Dockerfile裏面有對路徑的操做。Source目錄裏面放的就是api的工程文件了。Source目錄的上一級放了Dockerfile文件,Dockerfile文件內容以下:
FROM microsoft/dotnet:2.2-sdk-alpine AS dotnetcore-sdk #以這個鏡像爲基礎鏡像 WORKDIR /source #定義工做路徑,下面的命令都是以這個工做路徑爲基礎 #複製工程文件 COPY Source/Widget.Application/Widget.Application.csproj ./Widget.Application/ #COPY命令有兩個參數,第一個參數是宿主的目錄,第二個參數是鏡像上面的目錄,若是是相對路徑,那都是相對於WORKDIR的 COPY Source/Widgets.Core/Widgets.Core.csproj ./Widgets.Core/ COPY Source/Widgets.Domain/Widgets.Domain.csproj ./Widgets.Domain/ COPY Source/Widgets.Infrastructure/Widgets.Infrastructure.csproj ./Widgets.Infrastructure/ COPY Source/Widgets.UI/Widgets.UI.csproj ./Widgets.UI/ #執行命令 RUN dotnet restore ./Widgets.UI/Widgets.UI.csproj #將Source目錄複製到鏡像中(WORKDIR指定的目錄下) COPY Source . #構建和發佈 FROM dotnetcore-sdk as dotnetcore-publish #以上一個FROM子句製做好的鏡像爲基礎鏡像,並給了這個鏡像一個新的命名 RUN dotnet publish ./Widgets.UI/Widgets.UI.csproj -c Release -o /publish #執行publish命令並將發佈的內容放到容器內的/publish目錄下 #ASP.NET CORE RUNTIME 用上一步發佈好的dotnet core鏡像做爲基礎鏡像 FROM microsoft/dotnet:2.2-aspnetcore-runtime-alpine AS aspnetcore-runtime WORKDIR /app #定義工做目錄 COPY --from=dotnetcore-publish /publish . #--from=dotnetcore-publish這個參數說明COPY的第一個參數是從哪裏複製的 EXPOSE 5000 #對外暴露5000端口 ENTRYPOINT [ "dotnet","Widgets.UI.dll" ] #鏡像啓動時執行的命令
上面就是這個dockerfile作的工做。裏面有詳細說明。咱們從這個dockerfile構建一個鏡像出來:
docker build -t widgets:1.0 .
上面的命令是在dockerfile這個目錄下執行的,必須從這裏執行,最後面有一個點,表示的就是執行路徑。-t參數指明瞭鏡像的名稱和標籤。
構建完鏡像後,須要吧鏡像上傳到服務器,我沒有構建私有倉庫,我採用docker image save的方式將鏡像保存成tar文件:
docker image save widgets:1.0 C:\\registry\widgets.tar
我將這個鏡像保存成一個tar文件,而後上傳到雲服務器,而後在雲服務器上面,使用下面命令將tar文件還原成鏡像:
docker image load -i /path/to/widgets.tar
這樣就從tar文件還原了一個鏡像,而後以後後續的步驟。
我是分別作了兩個鏡像,一個是nginx的,一個是asp.net core的,nginx做爲asp.net core的反向代理來使用。這兩個鏡像運行後獲得兩個容器。由於nginx容器要和asp.net core容器進行交互,因此我須要一種方式來實現這個需求,我採用的是docker network命令來建立一個橋,而後吧這兩個應用都運行在這個橋上。具體以下:
首先是nginx:
docker run -d -p 443:443 --name nginx \ --network=widgetsweb \ --network-alias=nginx \ -v /home/wallee/nginx/conf.d:/etc/nginx/conf.d \ -v /home/wallee/nginx/nginx.conf:/etc/nginx/nginx.conf \ -v /home/wallee/nginx/log:/var/log/nginx \
-v /etc/letsencrypt:/etc/letsencrypt \ nginx
解釋一下這個命令的參數:
而後啓動asp.net core容器:
docker run -d -p 5000:5000 --name widgetsweb \ --network=widgets \ --network-alias=widgetsweb \ widgets:1.0
我將容器內的5000端口映射到外部的5000端口,並將容器運行到widgets這個橋上,這樣,asp.net core容器和nginx容器都在一個橋上,實現了互通訊息的目的。而後,我給asp.net core 容器的橋起了一個別名,這個別名在nginx的配置中有用,下面來看看nginx的配置文件是怎楊的:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
這個nginx的主配置文件分了幾個模塊:
events模塊主要定義了工做者進程的鏈接數,https模塊定義了一些在http模塊上下文的全局參數如日誌格式,長鏈接過時時間等,而後它裏面有一個include指令,這個指令將conf.d文件夾下的defualt.conf文件包含了進來,default.conf文件的內容以下:
upstream widgets{ server widgetsweb:5000; } server{ listen 443 ssl; server_name www.bankskit.com; ssl_certificate /etc/letsencrypt/live/www.bankskit.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.bankskit.com/privkey.pem; location / { proxy_pass http://widgets; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
upstream模塊定義了上游服務器的一些信息,upstream主要用來作負載均衡,這裏面只定義了一臺服務器,這個服務器就是asp.net core容器運行的服務。注意看這句:
server widgetsweb:5000
widgetsweb這個就是運行asp.net core容器時給這個容器的橋器的別名。這裏配置成這樣是生效的。
在server模塊中定義了監聽的地址(https的標準端口)和ssl證書以及證書的密鑰。location模塊中定義了代理的地址,proxy_pass http://widgets這句話中的widgets是upstream後面定義的名稱。
到此主要的配置已經完成。
而後在瀏覽器上訪問你的網站已經成功。
而後就須要在微信小程序中將你申請好的域名配置到裏面,而後你的小程序就能訪問你創建好的api了