这个文章的题目起的比较长,我想实现这样一个产品: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了