前文演示了在单一容器中部署 Nginx和ASP.NET Core WebApp, 正在前文评论区某大牛指出的,容器化部署 nginx+ASP.NET Core 有更符合实战的部署选择:多容器独立部署。 这次记录我在工作中利用 docker-compose部署企业级web应用。 本文会讲述企业级示例项目中用到的 docker volume、docker network、redis、sqlite、docker HealthCheck 等相关知识, 略去CentOS平台基本操作、Linux 下安装Docker ,docker compose工具, Linux安装Redis等前置知识点。 头脑风暴 图片总是比文字更能表达思想,下面图示帮助同学们在头脑中快速临摹出本次企业级项目的业务、部署流程, 方便同学们对照实战。 Web App业务上依赖第三方服务、容器外Redis服务、Sqlite数据库,可以想见我们会利用到 docker Volume机制和部分容器网络知识, 此处我们会以独立容器分别部署ASP.NETCore WebApp、Nginx容器,docker-compose 容器编排工具登场。 操作步骤 1. 准备应用程序部署文件 利用dotnet publish CLI命令或者 WebDeploy工具生成部署文件,将部署文件拷贝到如下图示publish文件夹 复制代码 EqidManager ├── app │ ├── Dockerfile │ └── publish ├── applogs ├── docker-compose.yml ├── EqidManager.db └── nginx ├── Dockerfile └── nginx.conf 复制代码 2. 应用docker-compose 工具 这次将涉及两个独立的Docker容器,Docker Compose工具将两者连接在一起。 Docker 的优势非常明显,尤其是对于开发者来说,它提供了一种全新的软件发布机制:使用 docker镜像作为软件产品的载体,使用 docker容器提供独立的软件运行上下文环境,使用 docker hub 等提供镜像的集中管理,这其中最重要的是使用 Dockerfile 定义容器的内部行为和关键属性来支持软件运行。 但实际的生产环境往往需要定义数量庞大的 docker 容器,并且容器之间具有错综复杂的联系,手动的记录和配置这些复杂的容器关系,不仅效率低下而且容易出错。所以迫切需要一种类似于【Dockerfile定义docker容器】那样能够【定义容器集群编排和部署】的工具。于是Docker Compose 出现了(其实应该说 Fig 出现了,docker 收购了 Fig 并改名为 compose)。 针对以上应用程序,在根目录下创建docker-compose.yml 文件: 复制代码 version: "3.4" services: app: build: context: ./app dockerfile: Dockerfile expose: - "80" extra_hosts: - "dockerhost:172.18.0.1" environment: TZ: Asia/Shanghai volumes: - type: bind source: /mnt/eqidmanager/eqidlogs target: /app/eqidlogs - type: bind source: /home/huangjun/eqidmanager/applogs target: /app/logs - type: bind source: /home/huangjun/eqidmanager/EqidManager.db target: /app/EqidManager.db healthcheck: test: ['CMD','curl','-f','http://localhost/healthcheck'] interval: 1m30s timeout: 10s retries: 3 start_period: 6s proxy: build: context: ./nginx dockerfile: Dockerfile ports: - "80:80" environment: TZ: Asia/Shanghai links: - app 复制代码 这个配置定义了两个服务: app、nginx 对于每个服务,【build】 告诉Docker Compose怎样为每个服务构建镜像 【expose】和【ports】控制服务与 network bridge、宿主机交互的方式 【links】表明链接另外的容器,意味着nginx启动的时会去启动app服务 在本应用程序中有业务数据需要被持久化, 同时使用了Sqlite数据库,所以使用 【Volumes】来映射宿主机路径到 app 容器内路径 本应用程序中因为涉及按小时生成业务日志文件,与本地时间有很大关联性,这里特意强调容器内外最好使用同一时区, 容器内默认时区可能与宿主机本地不符,使用【TZ】环境变量配置容器内时区 应用程序在http://localhost/healthcheck 配置了健康检查能力, 这里使用Docker内置的【HealthCheck】指令轮询 app内的健康检查端口, 以判断容器是否持续以预期的方式运作, 更多信息,请参考... 其中的【extra_hosts】在容器内添加主机名映射, 类比与 在我们的电脑上hosts文件中增加一行主机名映射关系, 这个稍后会细说 3. 创建独立镜像 ① 在app目录创建Dockerfile文件 View Code 上面的Dockerfile 显示将publish 文件件下的部署文件拷贝进docker镜像, 配置容器在80端口监听请求 ② 在nginx文件夹下创建Dockerfile 文件,将会使用基础nginx镜像和自定义的nginx.conf文件 View Code nginx.conf 文件与前文类似: 复制代码 worker_processes 4; events { worker_connections 1024; } http { sendfile on; upstream app_servers { server app:80; } server { listen 80; location / { proxy_pass http://app_servers; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } } } 复制代码 该nginx.conf与前文的区别是第9 行,前文因为app和nginx在一个容器,所以【upstream app_servers】配置为 server localhost:5000, 这里我们更改为server app:80, 其中app是在docker-compose.yml 文件中指定的服务名称。 4. 构建容器集合 --> 运行集合 在CentOS上安装了docker-compose工具之后, docker-compose --help 会看到可以利用的工具指令: // build 命令会构建/重建每一个服务, 然后使用项目名称和服务名称标记每个镜像、容器 docker-compose build // up 命令创建并运行容器 docker-compose up 如下图示: docker-compose 默认会利用项目名称EqidManager , 应用程序服务名称app 构建 ImageName=“EqidManager_app”镜像和对应容器。 本例中,访问localhost:80可验证是否成功部署。 Network 最后我们来探究容器集合的网络连接, 这也是容器比较复杂的部分。 当执行docker-compose时,会创建一个共享网桥设备,集合内所有服务都可通过该网桥交流。 创建名称是 {project}_default 的网桥 使用【app】配置创建容器,同时将名为app的服务加入 {project}_default 网络 使用【nginx】配置创建容器,同时将名为nginx的服务加入 {project}_default 网络 每一个容器现在可使用 “app”/“nginx” 主机名,这些主机名可得到正确的容器IP, 所以在nginx.conf 文件中我们给 【upstream app_servers】配置 app:80 能正确转发请求: docker-compose.yml文件中【extra_hosts】的用法: 当前程序架构中使用的Redis 服务是宿主机的常驻服务,在app 容器内不能再使用localhost:6379引用redis服务, 因为容器内localhost 指向的是容器自身。 【extra_hosts】指令用于主机名映射,该主机名代表了宿主机的机器IP,可通过docker inspect [network_id] 查看宿主机在网桥上的映射IP: View Code 本实例中宿主机在这个eqidmanager_default 网桥上的网关是 172.18.0.1,所以在docker-compose.yml 文件中配置了上述【extra_hosts】,在对应的app容器内我们cat /etc/hosts 会发现新增的映射记录: 相应的连接字符串是 : "connectionstrings": { ”sqlite": "Data Source=EqidManager.db", "redis": "dockerhost:6379,password=****@1,connectTimeout=10000,writeBuffer=40960" }, That‘s all, 编写一个企业级docker-compose.yml 文件需要对项目业务流程和部署流程有全盘了解,同时必须要具备完备的计算机操作原理和网络原理知识; 当然,当你编写完一个企业级docker-compose.yml文件并成功运行,这也印证了你已经全盘熟悉项目架构同时也重温了计算机操作原理和网络原理, 心中窃喜, docker-compose是个好东西,越用越香, 希望本文对初涉容器平台的同学能有一个抛砖引玉的效果。 作者:Julian_酱 感谢您的认真阅读,如有问题请大胆斧正,如果您觉得本文对你有用,码甲何必为难码甲,不妨帮忙点个或加关注,蟹蟹 ~。。~ 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置注明本文的作者及原文链接,否则保留追究法律责任的权利。 分类: Nosql,Web后端 标签: docker 好文要顶 关注我 收藏该文 Julian_酱 关注 - 29 粉丝 - 27 +加关注 5 0 « 上一篇:使用ASP.NET Core实现Docker的HealthCheck指令 posted @ 2019-05-24 17:50 Julian_酱 阅读(1333) 评论(7) 编辑 收藏 https://www.cnblogs.com/JulianHuang/p/10919346.html