Docker 开发环境与生产环境问题

2018-02-01 13:09:04 +08:00
 hujianxin

各位 docker 大佬,我最近使用 docker 有一个问题想不明白,就是开发环境和生产环境的问题。

我先将自己对 docker 的认识描述一下,以 python web 开发为例:

一、docker 最主要的使用场景是生产环境应用部署,在这个使用场景中,步骤如下:

  1. 通过类似的工程下的一个 Dockerfile 打包成镜像。
  2. 将镜像上传到 docker hub。
  3. 在服务器上docker pull下来之后运行。

这里的 dockerfile 里面,将工程目录 copy 进入 docker 镜像里,如下:

FROM kennethreitz/pipenv
LABEL maintainer="hujianxincn@foxmail.com"

COPY . /app
WORKDIR /app
ENV FLASK_APP=run.py
ENV FLASK_DEBUG=1
ENTRYPOINT [ "./boot.sh" ]

二、docker 也可以作为开发环境的一个工具使用,类似于 vagrant。(这一点其实是我疑惑的,大家用 docker 作为开发环境的多吗?) 在这个使用产经中,我使用 docker 的 volume 将本地工程目录,映射到 docker 容器内部,然后运行 docker 容器,映射端口供主机使用。

现在我的问题是:

  1. 我描述的生产环境使用流程正确吗?
  2. 我描述的开发环境使用流程正确吗?不正确的还请指正
  3. 如何做到 docker 既用来开发环境,也用于部署,形成一套流畅的工作流呢?

先谢过大家了!

11268 次点击
所在节点    Docker
19 条回复
wfd0807
2018-02-01 13:24:39 +08:00
v2 可以帮顶吗?
owenliang
2018-02-01 13:32:33 +08:00
开发可以 vagrant,线上需要 paas 平台,例如 marathon,k8s
HypoChen
2018-02-01 13:33:44 +08:00
1. 流程没问题,但可以更好,比如使用编排工具部署
2. 流程没问题,pycharm 也可以通过改配置实现类似操作,但是感觉有点繁琐,个人观点是开发怎么便捷怎么来
3. 参考 CICD
brickyang
2018-02-01 14:06:22 +08:00
从描述中没看出你的「开发环境」和「生产环境」有什么不同。是不是你对 Docker 的理解有哪里卡住了?

Docker 本身只是一个运行环境而已。至于把文件 COPY 进去还是 Volume 映射进去都是一样的。主要的区别只是映射进去的文件会保存在本地硬盘里,COPY 进去的文件与容器生死与共。

像你描述的这两种情况,也可以反过来用:

生产环境:代码文件放在服务器,启动 Docker 时用 -v 映射进去。
开发环境:启动 Docker 后在 container 中 git clone,开发完后 push 到 GitHub。

----------------------------------------------

我个人的实践经验是,在生产环境,会把 log 映射出来,因为容器里的文件不会保存,外部的日志工具也不能直接读取。

在开发环境,会用 Docker 启动数据库,日常需要的开发环境就在本地安装,没必要每次都启动 Docker,也不方便。

----------------------------------------------

Docker 的部署应该属于 CI/CD 的一部分,CI 跑完测试后自动构建打包并把 image push 到指定 registry,直接用就好了。非开源项目我喜欢用 GitLab.com ,提供了全套的免费工具。
Vogan
2018-02-01 14:12:36 +08:00
线上,要考虑容器挂了或僵死等问题,通常会部署多个节点,和快速拉起功能;

日志等,要拿出来,不然很容易撑死;

可以不做映射处理,直接将代码一起打包,做到对母鸡最小化影响。
tomczhen
2018-02-01 14:50:23 +08:00
开发环境的需求是统一开发运行环境,生产环境的需求是统一交付。

对于开发来说,重点是“运行环境”,对于生产来说,在环境的基础上还需要加上开发交付的代码。不管是虚拟机还是 Docker,都可以提供一个统一的运行环境。

环境的统一可以使用约定基础镜像来实现( FROM IMAGE ),实际开发中需不需要使用 Docker 容器远程 Debug,取决与实际需求,个人是觉得再提交代码之前开发本地用 Docker 运行测试代码即可( VOLUME ),倒是没必要追求必须在容器中完成开发过程。

开发交付时还是交付代码,利用 CI 平台进行 Docker 镜像构建(代码包含在镜像中),部署到生产环境时则是部署镜像,根据实际情况可能还需要对配置进行管理,之前参加的交流会看,有使用环境变量传入容器的,也有挂载配置文件的,也有不同环境不同镜像的。

另外也不觉得只要上 Docker 就得直接上 K8S,根据业务规模和需求 Docker Swarm 也可以考虑的,甚至仅仅单机靠编排文件( Docker Compose )也是可行的。当然,本着面向工资的原则尽量还是上 K8S。

对于开发来讲,Docker 实践中需要注意的一个是日志处理,另一个就是环境配置了,日志已经有人说了,补充一下的是 Docker 的日志还是有挺多诟病的地方,根据解决方案不同,代码上也可能需要做一些处理。Docker 官方的推荐实践是通过 stdout 和 stderr 输出,然后使用 logdriver 配置容器日志输出和格式。环境配置官方推荐的方式是使用环境变量作为配置,这需要在代码中获取环境变量,当然,实际怎么做是不断妥协的结果,并不是一定要如此。
tomczhen
2018-02-01 14:54:42 +08:00
忘记说了,没有 CI 平台也是可以的,但这时开发要交付的不是代码,而是 Docker 镜像。
whileFalse
2018-02-01 17:20:14 +08:00
我司本地开发不用 docker。
线上有多套环境,都是 docker。
Les1ie
2018-02-01 17:33:48 +08:00
看来我用法不正确了,我都是把 dockerfile 和 compose 文件放到服务器上去自己构建的
feverzsj
2018-02-01 17:58:35 +08:00
你的开发环境和 docker 一样就可以啦,image 一般都是上传到自己的 registry,其实 docker 上开发很适合用 c/c++之类的原生语言,直接用 ldd 复制依赖就可以啦,你用的是什么系统都没关系
hujianxin
2018-02-01 18:35:37 +08:00
@wfd0807 @owenliang 谢谢二位
@HypoChen 打算搞搞 compose
@brickyang 谢谢指导,我区分 copy 和 volume 的原因在于,有一些软件的开发,需要用到 hot load 功能,就比如,我开发 flask 应用,代码里面改了一些功能之后,flask 会自动重启服务器,然后我只需要刷新页面就行了。这个功能,我可以通过 volume 来实现,但是 copy 的话,需要每次都重启 docker,比较麻烦。
@Vogan 感谢
@tomczhen 谢谢写了这么多,我消化一下
hujianxin
2018-02-01 19:22:31 +08:00
感谢各位的认真回复,非常感谢。

我刚开始正式使用 docker 不久,很多地方不太理解。

看过很多教程,都说 copy for production,volume for development,而我纠结在,如何将两者很好的结合。
其实,这个问题很简单,我想复杂了,我把我的理解和解决方案说一下,大家可能大呼:原来你说的是这个 easy 问题啊(囧

1. copy for production,因为交付部署的时候,肯定是要将代码成果(代码、或者二进制)放到镜像里面,在服务器上直接 pull 镜像,运行就 ok,所以,生产环境,需要在 dockerfile 里面把代码 copy 到镜像里面,构建,然后部署。
2. volume for development,因为在很多时候,开发过程中,需要快速的查看结果,并且与生产环境保持一致。如果想与生产环境保持一致,用 docker 作为开发环境是必须的。在开发 flask 或者别的应用的时候,我们修改一个代码,flask 会快速的 hot reload,然后刷新页面就可以看到改动。如果我们每次都 build 新的镜像,然后删除容器,运行镜像,这样就失去了 hotload 的便捷性,而且非常繁琐。这个时候,我们直接将本地开发目录通过 volume 映射到容器内,然后在容器内运行 flask,就 ok 了。
3. 如何将这两者完美的融合呢,其实很简单,保持第一条(生产环境的步骤)不变,在本地运行镜像的时候,直接将当前开发目录映射到容器里面就行了,我们对容器的任何修改,如果不 commit,则不会保存。(这个第三点是我最纠结的,结果自己用手试了一遍,发现,原来如此简单,纸上得来终觉浅呀!)

最后,附上一个 博客链接,我通过这篇文章找到思路的: https://medium.com/@McMenemy/godorp-docker-compose-for-development-and-production-e37fe0a58d61
tomczhen
2018-02-01 19:23:30 +08:00
@Les1ie 如果公司没有提供容器化的基础,把 Docker Compose 当成一键部署脚本用也是不错的做法,至少比来路不明的脚本安全多了。
brickyang
2018-02-01 20:48:31 +08:00
@hujianxin 我打这么多字算白说了。

明确说了 COPY 和 Volume 只是两种(可以互换的)方式,需要什么用什么,没有什么环境用什么的“标准动作”。

Docker 只是个环境而已。保持环境一致只是说避免部署在不同环境出现不可知错误。这是它的作用,而不是对使用方法的限制或要求。

你过于纠结在“怎么用”这种形式的东西上了。
hujianxin
2018-02-01 20:56:59 +08:00
@brickyang 我认为这不是两种可以互换的形式啊,就比如,应用 hot load 的问题,用 copy 就没法解决吧
brickyang
2018-02-01 23:43:13 +08:00
@hujianxin

首先,“可互换”主要针对你所谓的“ copy for production, volume for development ”的说法。我是向你强调这两种方式只是两种不同用法,并不是什么 for 什么。

其次,我没用过 flask,但仅就你的描述而言,进入 container 直接改文件后重启服务也是一样的,并不需要“每次都 build 新的镜像,然后删除容器,运行镜像”。

最后,并不存在“如果想与生产环境保持一致,用 docker 作为开发环境是必须的”。

给我的感觉,你一直在努力总结出一套“操作规范”来,而对概念的理解是模糊的。如果说的不对,也请包涵。
hujianxin
2018-02-02 06:40:14 +08:00
@brickyang 您说的有道理,我确实过于死板的,哈哈,我懂你的意思了,谢啦
singer
2018-02-02 09:34:10 +08:00
docker-compose 用用,开发的时候代码之类,日志之类的,配置文件之类的都挂出来。
这里注意配置文件。
线上部署,维护开发与线上环境一样。可以在线上用 COPY 把配置文件弄进去。
hujianxin
2018-02-03 11:10:28 +08:00
@singer 是的,我现在就是这么做的,哈哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/427681

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX