司开星的博客

使用Docker快速部署多应用方案(一)需求及思路

背景

今年部门主要对外输出自研产品,为此需要设计一套快速交付项目的方案,目标一天部署完成十几个独立应用。

应用包括ELK/DB/Python后端/Java后端/Node前端等。

整体思路

为实现快速部署,有以下几个基本思想:

  • 不同应用尽量使用统一的部署方法,且尽量不需要改动现有代码;
  • 减少部署过程中需要手动操作的步骤;
  • 根据项目及依赖为不同应用分组;
  • 与部署环境有关的参数(比如mysql地址)放到配置文件中方便修改;
  • 配置文件统一存放,部署人员无需关注不同应用之间的差别。

根据公司应用实际情况,使用如下方案:

  • 除agent等特殊组件(比如osquery、salt-minion、prometheus node等),其他所有应用均使用Docker部署;
  • 默认需要手动操作的逻辑尽量改为自动操作(比如salt-master的minion accept,sync_modules,及项目初始化数据等);
  • 使用docker-compose为应用分组;
  • 使用docker-compose原生的.env修改配置/环境变量;
  • 应用配置统一到同目录下。

人员职责

为了更清晰地区分部署阶段,将部署过程涉及的人员分为三类:开发人员、打包人员、部署人员。

开发人员

应用的开发人员不需要关注部署过程,只需要为打包做好一些准备:

  • 确保配置为独立文件(或可通过环境变量修改);
  • 确保应用能使用docker正常运行;
  • 提供配置文件挂载路径及所需的持久化数据挂载路径;
  • 初始数据尽量改为自动导入,无需手动操作;
  • 编写应用首次运行的验证文档。

开发人员只要提供符合要求的代码分支即可。

打包人员

为了真正实现快速部署,需要有人负责整合所有应用并编写打包相关脚本,总体来说是要实现“把原始代码转换成可以在客户现场部署的状态”。

具体任务包括:

  • 优化应用Dockerfile(包括减小image大小、去掉image内无关或机密数据等);

  • 根据项目实际情况为应用及依赖组件分组(比如某个项目的前后端一定要同时运行才能正常使用,这样就可以分为一组),同一组的应用放在同个docker-compose.yml文件内;

  • 编写docker-compose.yml;
  • 为简化每次打包流程,编写打包相关脚本(包括整合代码加密、npm build、maven package、统一修改配置等);
  • 编写整体部署文档(应先假定部署者非开发者及打包者,部署文档需清晰完整。);
  • 根据客户实际环境填写配置,并完成打包、导出image。

假设有以下几个应用:app1_backend、app1_front、app2_api,依赖以下组件:mysql、redis。打包人员每次打包完成,实际产出文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
部署文档.txt

# image目录存放镜像文件
image/db.tar(db组image文件,包括mysql、redis)
image/app1.tar (app1组image文件)
image/app2.tar (app2组image文件)

# config目录存放应用配置文件
config/app1/app1_backend/config.py
config/app1/app1_front/config.js
config/app1/app1_front/config.yml

# run目录存放docker-compose
run/docker-compose-db.yml
run/docker-compose-app1.yml
run/docker-compose-app2.yml
run/.env

# data目录存放初始化需要的文件及容器挂载数据
data/init/mysql
data/app1/app1_backend

为方便传输,可以统一压缩为tar.gz。

部署人员

部署人员需要熟悉docker相关运行及调试命令,遇到应用本身运行问题要配合开发人员远程调试。

Q&A

为什么一台机器不使用同一个docker-compose.yml,而是根据不同分组使用多个?

如果几十个应用放在同个docker-compose里同时启动,启动日志太多影响问题排查。且一个docker-compose文件太长也不方便修改。

为什么不是开发人员优化docker镜像,而是打包人员优化?

优化docker镜像涉及到一些docker相关知识,所有应用的开发者都要去研究一遍费时费力,打包人员根据目标统一优化节省人力成本。

为什么不使用打包后的代码直接部署,需要导出docker image?

理论上打包以后的代码就可以拿到客户现场部署了,并且代码文件比image小很多。不过部署代码过程中需要联网下载基础镜像、依赖包等,这对网络要求比较高,并且如果应用没做好严格的依赖版本限制,可能会出现不兼容现场下载的依赖包。

所以,除非客户现场对部署需要使用的文件大小有严格限制,否则直接使用docker image部署会更快。