微信小程序和asp.net core基於docker和nginx的交互

這個文章的題目起的比較長,我想實現這樣一個產品: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

四、申請ssl/tls證書

當你完成購買服務器和申請域名的步驟後,能夠開始申請證書了。個人證書是經過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

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

個人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 api應用並製做鏡像

我建立了一個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

我是分別作了兩個鏡像,一個是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

解釋一下這個命令的參數:

  • -d:後臺運行
  • -p端口映射,從容器外部到容器內部的映射
  • --name指定容器名稱
  • --network指定容器運行在那個橋,橋使用docker network create來建立的,這裏橋的名稱是widgetsweb
  • --network-alias指定容器運行的橋的別名,這個別名在nginx的配置中有用
  • 第一個-v 將宿主上的conf.d掛載到容器的conf.d上,包含了default.conf這個子配置文件
  • 第二個-v將宿主上的nginx.conf掛載到容器的的nginx.conf文件中,包含了nginx的主配置文件
  • 第三個-v將宿主上的log文件掛載到容器的log,包含了access.log和error.log
  • 第四個-v將宿主上的/etc/letsencrypt掛載到容器的/etc/letsencrypt上,包含了證書(ssl)的相關信息

而後啓動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了

相關文章
相關標籤/搜索