.NET Core容器化之多容器应用部署(Docker-Compose)

小灰灰 2021-06-26 16:06 545阅读 0赞

这里写图片描述

1.引言

紧接上篇.NET Core容器化@Docker,这一节我们先来介绍如何使用Nginx来完成.NET Core应用的反向代理,然后再介绍多容器应用的部署问题。

2. Why Need Nginx

.NET Core中默认的Web ServerKestrel

Kestrel is great for serving dynamic content from ASP.NET, however the web serving parts aren’t as feature rich as full-featured servers like IIS, Apache or Nginx. A reverse proxy-server can allow you to offload work like serving static content, caching requests, compressing requests, and SSL termination from the HTTP server.

Kestrel可以很好的用来为ASP.NET提供动态内容,然而在Web服务方面没有IIS、Apache、Nginx这些全功能的服务器完善。我们可以借助一个反向代理服务器接收来自互联网的HTTP请求并在经过一些初步处理(比如请求的缓存和压缩、提供静态内容、SSL Termination)后将其转发给Kestrel
这里写图片描述
借助反向代理服务器(本文使用Nginx),不仅可以给我们的Web网站提供了一个可选的附加层配置和防御,而且可以简化负载均衡和SSL设置。而更重要的是,反向代理服务器可以很好的与现有的基础设施进行整合。

3. Hello Nginx

同样我们还是基于Docker来试玩一下Nginx

  1. //拉取Nginx镜像
  2. $ docker pull nginx
  3. //启动Nginx容器
  4. $ docker run -d -p 8080:80 --name hellonginx nginx

上面我们以后台运行的方式启动了一个命名为hellonginxnginx容器,其端口映射到宿主机的8080端口,我们现在可以通过浏览器直接访问http://<ip address>:8080即可看到nginx的欢迎界面。
Hello Nginx

至此,一个Nginx容器就启动完毕了。那如何进行反向代理呢?别急,我们一步一步来。

4. 反向代理.NET Core MVC

4.1. 启动Web容器

还记得我们上一篇本地打包MVC项目创建的hellodocker.web的镜像吗?这里我们再启动该镜像创建一个容器:

  1. //启动一个helodocker.web的镜像并命名容器为hellodocker.web.nginx
  2. # docker run -d -p 5000:5000 --name hellodocker.web.nginx hellodocker.web
  3. 160166b3556358502a366d1002567972e242f0c8be3a751da0a525f86c124933
  4. //尝试访问刚刚运行的容器
  5. [root@iZ288a3qazlZ ~]# curl -I http://localhost:5000
  6. HTTP/1.1 200 OK
  7. Date: Sun, 24 Dec 2017 02:48:16 GMT
  8. Content-Type: text/html; charset=utf-8
  9. Server: Kestrel
  10. Transfer-Encoding: chunked

OK,我们开放了宿主机的5000端口用来映射我们启动的MVC容器。

4.2. 配置反向代理

下面我们就来配置Nginx来反向代理我们刚启动的Web容器。
要想Nginx成功代理指定的容器内运行的Web网站,首先我们得知道容器对应的IPAddress。使用docker inspect <container id/name>即可查到。

  1. //查看正在运行的容器列表
  2. $ docker ps
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. d046b7b878a0 hellodocker.web "dotnet run" 5 seconds ago Up 3 seconds 0.0.0.0:5000->5000/tcp hellodocker.web.nginx
  5. //使用`|`管道操作符加上`grep`过滤操作符可以直接提取我们要查找的关键字
  6. $ docker inspect hellodocker.web.nginx | grep IPAddress
  7. "SecondaryIPAddresses": null,
  8. "IPAddress": "192.168.0.5",
  9. "IPAddress": "192.168.0.5",

从上面可以看到我的Web容器运行在宿主机的192.168.0.5:5000。下面我们配置Nginx转发请求到192.168.0.5:5000即可完成反向代理。

Nginx配置反向代理的配置文件路径为:/etc/nginx/conf.d/default.conf
我们可以通过本地创建一个配置文件挂载到Nginx的容器内部进行反向代理配置。

  1. $ cd demo
  2. $ mkdir nginx
  3. //创建my_nginx.conf文件
  4. $ touch my_nginx.conf
  5. $ vi my_nginx.conf
  6. server {
  7. listen 80;
  8. location / {
  9. proxy_pass http://192.168.0.5:5000;
  10. }
  11. }

上面我们通过指定listen配置nginx去监听80端口,指定proxy_pass为我们Web容器的IP和端口完成反向代理文件的配置。

接下来就是启动一个新的Nginx容器并通过挂载的方式将配置文件共享到容器内部。

  1. $ docker run -d -p 8080:80 \
  2. > -v $HOME/demo/nginx/my_nginx.conf:/etc/nginx/conf.d/default.conf \
  3. > nginx
  4. 95381aa56a336f65b6d01ff9964ae3364f37d25e5080673347c1878b3a5bb514
  5. /usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint elated_mccarthy (5a576d5991dd164db69b1c568c94c15e47ec7c67e43a3dd6982a2e9b83b60e08): Bind for 0.0.0.0:8080 failed: port is already allocated.

我们发现容器启动失败,原因是8080端口被我们刚刚第一次启动的nginx容器占用了。怎么办?两个方法:第一种就是将刚才创建的nginx容器干掉;第二种就是映射到新的端口。这里选择第一种。

  1. $ docker ps
  2. 1bd630b60019 nginx "nginx -g 'daemon off" 59 minutes ago Up 59 minutes 0.0.0.0:8080->80/tcp hellonginx
  3. //使用docker rm <container id>删除容器,指定-f进行强制删除
  4. $ docker rm 1bd630b60019 -f
  5. //重新启动Nginx容器
  6. $ docker run -d -p 8080:80 \
  7. > -v $HOME/demo/nginx/my_nginx.conf:/etc/nginx/conf.d/default.conf \
  8. > nginx
  9. 793d4c62ec8ac4658d75ea0ab4273a0b1f0a9a68f9708d2f85929872888b121d

启动成功后,我们再在浏览器中访问http://<ipaddress>:8080,发现返回的不再是Nginx的默认欢迎页,而是我们启动的Web容器中运行的MVC的首页,说明反向代理配置成功!
这里写图片描述

5. Docker Compose让一切更简单

上面的步骤虽然简单,但要分两步进行:第一个就是我们的WebNginx要分两次部署,第二个就是我们必须知道Web容器的IP和端口号,以完成反向代理文件的配置。

对于需要多个容器(比如需要Nginx、SqlServer、Redis、RabbitMQ等)协调运行的复杂应用中,使用以上方式进行部署时,很显然会很麻烦,而且还要为各个容器之间的网络连接而苦恼。

还好,Docker体贴的为我们想到了这一点。借助Compose模块,我们可以编写一个docker-compose.yml文件,使用声明性语法启动一系列相互连接的容器,即可一步完成上面的任务。

Docker Compose是一个用来定义和运行复杂应用的Docker工具。使用Compose,你可以在一个文件中定义一个多容器应用,然后使用一条命令来启动你的应用,完成一切准备工作。

5.1. 安装Docker Compose

依次执行以下命令:

  1. $ sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
  2. $ sudo chmod +x /usr/local/bin/docker-compose
  3. $ docker-compose --version
  4. docker-compose version 1.18.0, build 1719ceb

5.2. 编写第一个docker-compose.yml

dockers-compose.yml文件要定义在我们项目的文件夹下,我们的项目文件夹位于$HOME/demo/HelloDocker.Web

  1. $ cd $HOME/demo/HelloDocker.Web
  2. $ touch docker-compose.yml
  3. $ vi docker-compose.yml
  4. version: '2'
  5. services:
  6. hellodocker-web:
  7. container_name: hellodocker.web.compose
  8. build: .
  9. reverse-proxy:
  10. container_name: reverse-proxy
  11. image: nginx
  12. ports:
  13. - "9090:8080"
  14. volumes:
  15. - ./proxy.conf:/etc/nginx/conf.d/default.conf

简单介绍下上面的配置文件,其中定义了两个服务:一个是hellodocker-web,即以我们当前项目目录来构建镜像并启动一个叫hellodocker.web.compose的容器。一个是reverse-proxy,用来使用nginx镜像进行反向代理,其中又通过指定volumes来使用挂载的方式进行配置。

  1. $ touch proxy.conf
  2. $ vi proxy.conf
  3. server {
  4. listen 8080;
  5. location / {
  6. proxy_pass http://hellodocker-web:5000;
  7. }
  8. }
  9. $ ls
  10. [root@iZ288a3qazlZ HelloDocker.Web]# ls
  11. appsettings.Development.json Controllers Models Startup.cs
  12. appsettings.json docker-compose.yml obj Views
  13. bin Dockerfile Program.cs wwwroot
  14. bundleconfig.json HelloDocker.Web.csproj proxy.conf
  15. [root@iZ288a3qazlZ HelloDocker.Web]#

其中要注意反向代理的配置:proxy_pass http://hellodocker-web:5000;,其中ip部分直接指定的是docker-compose.yml中定义的第一个服务的名称hellodocker-web
下面我们就来启动Compose

  1. $ docker-compose up -d
  2. Building hellodocker-web
  3. Step 1 : FROM microsoft/dotnet:latest
  4. ---> 7d4dc5c258eb
  5. Step 2 : WORKDIR /app
  6. ---> Using cache
  7. ---> 98d48a4e278c
  8. Step 3 : COPY . /app
  9. ---> 0cb9fc540afe
  10. Removing intermediate container 9fecf088f03f
  11. Step 4 : RUN dotnet restore
  12. ---> Running in 4bb7f34edbbe
  13. Restore completed in 597.13 ms for /app/HelloDocker.Web.csproj.
  14. Restoring packages for /app/HelloDocker.Web.csproj...
  15. Restore completed in 1.76 sec for /app/HelloDocker.Web.csproj.
  16. ---> 6869609ece23
  17. Removing intermediate container 4bb7f34edbbe
  18. Step 5 : EXPOSE 5000
  19. ---> Running in a97febf01e5a
  20. ---> 9b2639862a94
  21. Removing intermediate container a97febf01e5a
  22. Step 6 : ENV ASPNETCORE_URLS http://*:5000
  23. ---> Running in 4e2f4af28a8d
  24. ---> 0069661e891a
  25. Removing intermediate container 4e2f4af28a8d
  26. Step 7 : ENTRYPOINT dotnet run
  27. ---> Running in cbbf08d906f9
  28. ---> 0bbeef249b30
  29. Removing intermediate container cbbf08d906f9
  30. Successfully built 0bbeef249b30
  31. WARNING: Image for service hellodocker-web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
  32. Creating hellodocker.web.compose ... done
  33. Starting reverse-proxy ... done
  34. //执行docker-compose ps验证启动的服务
  35. $ docker-compose ps
  36. Name Command State Ports
  37. ---------------------------------------------------------------------------------------
  38. hellodocker.web.compose dotnet run Up 5000/tcp
  39. reverse-proxy nginx -g daemon off; Up 80/tcp, 0.0.0.0:9090->8080/tcp
  40. //使用curl指令验证nginx的反向代理
  41. $ curl -I http://localhost:9090
  42. HTTP/1.1 200 OK
  43. Server: nginx/1.13.7
  44. Date: Sun, 24 Dec 2017 04:37:35 GMT
  45. Content-Type: text/html; charset=utf-8
  46. Connection: keep-alive

可以看到,通过执行curl -I http://localhost:9090验证代理服务器配置成功,我们再通过浏览器访问http://<ip address>:9090发现正确返回了我们MVC项目的默认首页。

  1. // 查看当前运行的容器
  2. $ docker ps
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. a52830499cff hellodockerweb_hellodocker-web "dotnet run" 7 minutes ago Up 7 minutes 5000/tcp hellodocker.web.compose
  5. e1fe109e10bc nginx "nginx -g 'daemon off" 11 minutes ago Up 4 minutes 80/tcp, 0.0.0.0:9090->8080/tcp reverse-proxy

我们同时也发现通过docker-compose正确的创建了两个容器hellodocker.web.composereverse-proxy

6. 最后

经过以上的练习,我们对Nginx有了一定的了解,且知道如何进行配置。同时了解了如何借助docker-compose打包运行需要多容器的复杂应用。

本篇就先讲到这里,下一篇我们介绍如何在Linux上玩耍MySql并打通Nginx+Web+MySql的容器化部署。

发表评论

表情:
评论列表 (有 0 条评论,545人围观)

还没有评论,来说两句吧...

相关阅读