在Docker中使用数据映射的原则

常规的业务部署/运行流程

将一个业务部署到线上环境,通常来说会有以下几个步骤:

  1. 拷贝业务的代码包到服务器
  2. 修改配置文件(可选),有时候是通过环境变量来实现
  3. 启动进程,让业务跑起来

业务过程中会遇到的哪些文件?

  1. 代码包文件
  2. 配置文件
  3. 业务代码输出的日志文件
  4. 业务运行过程中用户数据

针对第四点有必要解释下:
比如: 用户上传的图片文件,存在网站的根目录下
比如: 数据库业务中数据文件

哪些文件应该被打进镜像,哪些文件被映射?

代码包文件在开发环境映射,在其他环境打进镜像

文件是否被映射我觉得是取决与你的使用场景的,开发环境怎么顺手怎么来,用脚本语言(php/python)写的业务,改一行代码还要走docker build 、 docker run这些操作,烦不烦呀。
但是提交给其他人的时候,就不要这样玩了,哪怕是改了一个字母也应该打入到镜像而不是被映射本地文件。

配置文件都打进镜像,本地不一样的时候映射本地的文件

这里的配置文件其实应该包含两层,一层是默认配置,一层是配置模板。

  1. 默认配置是为了方便,不用做任何改动应该就能用起来。
  2. 配置模板是为了通用,把配置模板变成真正的配置一般来说在endpoint的脚本里面完成,可以通过环境变量来确定应该如何生成配置。

ps:通过配置模板也有两种写法,一种是写全量的配置到配置文件中,分成 config_dev.ini/config_test.ini/config_prod.ini 等等,代码中用到的是config.ini,启动容器的时候(ENTRYPOINT)环境变量传 dev/test/prod 就可以确定用哪个配置,然后就 mv config_xxx.ini config.ini
另一种是直接将信息写在环境变量中,模板中写替换符,如在config.ini中写一个ip=$IP$,启动容器的时候用 sed -i s/$IP$/192.168.1.11/g 替换就行了。

业务代码输出的日志看个人习惯,开发环境可映射可不映射,生产环境应该映射,方便排错

关于自己输出的日志,开发环境本身是不稳定的,历史的也没啥意义,随时都可以重现,所以不用映射出来,如果日志文件太大,rm掉容器,重新启动一个新的容器,日志就被清理掉了。

用户的数据没什么好说的,一定要放在容器之外。

容器是一个极不稳定的环境(很容易被销毁的意思,如迁移,docker重置都有可能造成容器的消失),所以一定不要在容器中放重要的数据,例如用户数据。当然开发环境随意,影响范围可控,只要自己不怕麻烦。

如果你在本地用了docker run的方式,你最好有个地方记录你run的时候用到的所有的方式,以及在哪个目录运行的,你可以写一个shell脚本固化,最好不要裸写,以后自己都不知道是什么情况了。

1
docker run -p 3306:3306 --name mymysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

写在最后:

我觉得要用容器的话,最好不要用Volume的功能,这样会丧失容器本身的意义,因为容器本身是无状态可以随时迁移的,如果跟宿主主机的某个目录绑定,迁移不就没有意义啦?

  1. 用户上传的东西,尽量用云服务的 对象存储,而不是往服务器上扔
  2. 机器上的日志往远程打,如果远程日志实在没有必要,就用本机的rsyslog来接受。
  3. 关于配置文件,有人在创建镜像的时候就已经确定了,我觉得还是在运行的时候确定吧,这样可以少很多个镜像,要不然一个版本你要为测试、预发布、正式各打一个镜像。