docker-compose是个好东西,越用越香

简介: 本文会讲述企业级示例项目中用到的 docker volume、docker network、redis、sqlite、docker HealthCheck 等相关知识,忽略CentOS基本操作、Linux 下安装Docker、docker compose工具, Linux安装Redis等前置知识点。

头脑风暴


图片总是比文字更能表达思想,下面图示帮助同学们在头脑中快速临摹出本次企业级项目的业务、部署流程, 方便同学们对照实战。


a5e241d293fe835da976b25332db99da.png


Web App业务上依赖宿主机Redis服务、Sqlite数据库,可以想见我们会利用到 docker Volume机制和部分容器网络知识,


此处我们会以独立容器分别部署ASP.NETCore WebApp、Nginx容器,docker-compose 容器编排工具登场。


操作步骤


1. 准备应用程序部署文件


利用dotnet publish CLI命令或者 WebDeploy工具生成部署文件,这里因为还没有实现CI自动构建镜像,需要手动将部署文件拷贝到如下图示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
    logging:
      options:
        max-size: "200k"
        max-file: "10"
  proxy:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - "80:80"
    environment:
      TZ: Asia/Shanghai
    links:
    - app
    logging:
      options:
        max-size: "200k"
        max-file: "10"


这个配置定义了两个服务: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文件中增加一行主机名映射关系, 这个稍后会细说


  • 添加Logging配置节,配置web程序和nginx日志大小(10个日志文件,每个最大200k)


3. 创建独立镜像


① 在app目录创建Dockerfile文件


FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY publish .
EXPOSE 80
ENTRYPOINT ["dotnet","EqidManager.dll"]


将publish目录的部署文件拷贝进docker镜像, 配置容器在80端口监听请求


② 创建Nginx转发镜像


在nginx文件夹下创建Dockerfile 文件,使用基础nginx镜像和自定义的nginx.conf文件


FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf


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;
        }
    }
}


4. 构建容器集合 --> 运行集合


在CentOS上安装了docker-compose工具之后, docker-compose --help 会看到可以利用的工具指令:


// build 命令会构建/重建每一个服务, 然后使用项目名称和服务名称标记每个镜像、容器
docker-compose build
// up 命令创建并运行容器
docker-compose up


如下图示:docker-compose 默认会利用上级目录名EqidManager ,服务名称app 构建 ImageName=“EqidManager_app”镜像和对应容器。


本例中,访问localhost:80可验证是否成功部署。


深度解读


网桥模型


探究容器集合的网络连接, 这也是容器比较复杂的部分。


docker引擎刚建立的时候,会新建一个docker0网桥(driver= bridge), 新加入的容器默认都会加入这个网桥。


当执行docker-compose  up时:


① 创建名为 {project}_default 的网桥
② 定义的容器会加入{project}_default 网络。


现在可使用 “app” /  “nginx”  服务名访问容器。


为啥可以通过服务名访问容器?


是因为利用了Docker引擎内置的DNS, 查询服务名----> 查询DNS(服务名:对应容器IP),

所以在nginx.conf 文件[upstream app_servers]配置app:80能正确转发请求:


3dc5a954d2694885d681ebd2644c3e13.png


docker-compose.yml文件中[extra_hosts]的用法


当前程序中使用了宿主机的Redis服务,app容器内localhost指示的是容器自身,为访问宿主机redis:


[extra_hosts]指令用于主机名映射,定义宿主机在容器内的别名,可通过docker inspect [network_id] 查看宿主机在网桥上的映射IP:


本实例中docker-compose 新建的eqidmanager_default网桥网关是 172.18.0.1,在docker-compose.yml 文件中配置了上述[extra_hosts],在对应的app容器内我们cat  /etc/hosts 会发现新增的映射记录:


ed3d9196b1f744e4a164222f311953fc.png


# 相应的连接字符串
"connectionstrings": {
    ”sqlite": "Data Source=EqidManager.db",
     "redis": "dockerhost:6379,password=****@1,connectTimeout=10000,writeBuffer=40960"
},


tip:这里假定每次执行docker-compose up/down命令,网关/子网都不变, 实际上很有可能变动, 所以最好使用自定义网桥


总结


That‘s all, 编写一个企业级docker-compose.yml 文件需要对项目业务流程和部署流程有全盘了解,同时必须要具备完备的计算机操作原理和网络原理知识;


当然,当你编写完一个企业级docker-compose.yml文件并成功运行,这也印证了你已经全盘熟悉项目架构同时也重温了计算机操作原理和网络原理,心中窃喜。


docker-compose是个好东西,越用越香,希望本文对初涉容器平台的同学能有一个抛砖引玉的效果。

相关文章
|
机器学习/深度学习 人工智能 自然语言处理
四张图片道清AI大模型的发展史(1943-2023)
现在最火的莫过于GPT了,也就是大规模语言模型(LLM)。“LLM” 是 “Large Language Model”(大语言模型)的简称,通常用来指代具有巨大规模参数和复杂架构的自然语言处理模型,例如像 GPT-3(Generative Pre-trained Transformer 3)这样的模型。这些模型在处理文本和语言任务方面表现出色,但其庞大的参数量和计算需求使得它们被称为大模型。当然也有一些自动生成图片的模型,但是影响力就不如GPT这么大了。
5371 0
|
Java Docker 微服务
如何使用Docker和Docker Compose部署微服务
【2月更文挑战第12天】
1355 0
|
6月前
|
数据安全/隐私保护 云计算
如何从零开始创建AWS账号
本文详细介绍如何从零开始创建AWS账号,涵盖访问官网、选择免费套餐、填写账户信息、设置密码、选择使用场景、输入账单信息、验证电话号码、选择支持计划及最终确认等完整注册流程,适合初学者快速入门。
|
机器学习/深度学习 人工智能 JavaScript
JavaScript和TypeScript的未来发展趋势及其在Web开发中的应用前景
本文探讨了JavaScript和TypeScript的未来发展趋势及其在Web开发中的应用前景。JavaScript将注重性能优化、跨平台开发、AI融合及WebAssembly整合;TypeScript则强调与框架整合、强类型检查、前端工程化及WebAssembly的深度结合。两者结合发展,特别是在Vue 3.0中完全采用TypeScript编写,预示着未来的Web开发将更加高效、可靠。
648 4
|
11月前
|
JSON API UED
商品信息API接口的设计与实现
商品信息API接口的设计与实现,遵循RESTful原则以确保高效、可维护和良好的用户体验。API支持获取、查询、创建、更新和删除商品资源,URL模式直观易懂。请求参数通过查询字符串传递,支持分页和过滤。响应体结构化,包含数据、链接和元数据字段,便于解析。错误处理采用HTTP状态码结合JSON错误描述,提供明确反馈。
|
机器学习/深度学习 传感器 人工智能
AI与环境保护:可持续发展的伙伴
在科技日新月异的时代,人工智能(AI)不仅改变了我们的生活和工作方式,还在环保和可持续发展领域发挥重要作用。AI通过环境监测、资源优化、垃圾分类、绿色出行和环保教育等多方面的应用,为环保事业注入新活力,推动社会向更加绿色、可持续的方向发展。
|
并行计算 异构计算
卸载原有的cuda,更新cuda
本文提供了一个更新CUDA版本的详细指南,包括如何查看当前CUDA版本、检查可安装的CUDA版本、卸载旧版本CUDA以及安装新版本的CUDA。
13616 3
卸载原有的cuda,更新cuda
|
JavaScript Java
hyengine垃圾回收问题之过程卡顿如何解决
hyengine垃圾回收问题之过程卡顿如何解决
181 4
|
索引 Python
【Python 基础】解释Range函数
【5月更文挑战第6天】【Python 基础】解释Range函数
|
缓存 NoSQL Java
Springboot整合之Shiro和JWT技术实现无感刷新6
Springboot整合之Shiro和JWT技术实现无感刷新6

热门文章

最新文章