Docker 开发环境与生产环境问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hujianxin
V2EX    Docker

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

  •  
  •   hujianxin 2018-02-01 13:09:04 +08:00 11625 次点击
    这是一个创建于 2881 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    FROM kennethreitz/pipenv LABEL maintainer="[email protected]" 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 既用来开发环境,也用于部署,形成一套流畅的工作流呢?

    先谢过大家了!

    第 1 条附言    2018-02-01 19:22:24 +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
    19 条回复    2018-02-03 11:10:28 +08:00
    wfd0807
        1
    wfd0807  
       2018-02-01 13:24:39 +08:00
    v2 可以帮顶吗?
    owenliang
        2
    owenliang  
       2018-02-01 13:32:33 +08:00
    开发可以 vagrant,线上需要 paas 平台,例如 marathon,k8s
    Hyponet
        3
    Hyponet  
       2018-02-01 13:33:44 +08:00
    1. 流程没问题,但可以更好,比如使用编排工具部署
    2. 流程没问题,pycharm 也可以通过改配置实现类似操作,但是感觉有点繁琐,个人观点是开发怎么便捷怎么来
    3. 参考 CICD
    brickyang
        4
    brickyang  
       2018-02-01 14:06:22 +08:00   1
    从描述中没看出你的「开发环境」和「生产环境」有什么不同。是不是你对 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
        5
    Vogan  
       2018-02-01 14:12:36 +08:00
    线上,要考虑容器挂了或僵死等问题,通常会部署多个节点,和快速拉起功能;

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

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

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

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

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

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

    对于开发来讲,Docker 实践中需要注意的一个是日志处理,另一个就是环境配置了,日志已经有人说了,补充一下的是 Docker 的日志还是有挺多诟病的地方,根据解决方案不同,代码上也可能需要做一些处理。Docker 官方的推荐实践是通过 stdout 和 stderr 输出,然后使用 logdriver 配置容器日志输出和格式。环境配置官方推荐的方式是使用环境变量作为配置,这需要在代码中获取环境变量,当然,实际怎么做是不断妥协的结果,并不是一定要如此。
    tomczhen
        7
    tomczhen  
       2018-02-01 14:54:42 +08:00   1
    忘记说了,没有 CI 平台也是可以的,但这时开发要交付的不是代码,而是 Docker 镜像。
    whileFalse
        8
    whileFalse  
       2018-02-01 17:20:14 +08:00
    我司本地开发不用 docker。
    线上有多套环境,都是 docker。
    Les1ie
        9
    Les1ie  
       2018-02-01 17:33:48 +08:00
    看来我用法不正确了,我都是把 dockerfile 和 compose 文件放到服务器上去自己构建的
    feverzsj
        10
    feverzsj  
       2018-02-01 17:58:35 +08:00
    你的开发环境和 docker 一样就可以啦,image 一般都是上传到自己的 registry,其实 docker 上开发很适合用 c/c++之类的原生语言,直接用 ldd 复制依赖就可以啦,你用的是什么系统都没关系
    hujianxin
        11
    hujianxin  
    OP
       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
        12
    hujianxin  
    OP
       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
        13
    tomczhen  
       2018-02-01 19:23:30 +08:00
    @Les1ie 如果公司没有提供容器化的基础,把 Docker Compose 当成一键部署脚本用也是不错的做法,至少比来路不明的脚本安全多了。
    brickyang
        14
    brickyang  
       2018-02-01 20:48:31 +08:00 via iPhone
    @hujianxin 我打这么多字算白说了。

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

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

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

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

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

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

    给我的感觉,你一直在努力总结出一套“操作规范”来,而对概念的理解是模糊的。如果说的不对,也请包涵。
    hujianxin
        17
    hujianxin  
    OP
       2018-02-02 06:40:14 +08:00 via Android
    @brickyang 您说的有道理,我确实过于死板的,哈哈,我懂你的意思了,谢啦
    singer
        18
    singer  
       2018-02-02 09:34:10 +08:00 via iPhone
    docker-compose 用用,开发的时候代码之类,日志之类的,配置文件之类的都挂出来。
    这里注意配置文件。
    线上部署,维护开发与线上环境一样。可以在线上用 COPY 把配置文件弄进去。
    hujianxin
        19
    hujianxin  
    OP
       2018-02-03 11:10:28 +08:00
    @singer 是的,我现在就是这么做的,哈哈
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4010 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 47ms UTC 00:58 PVG 08:58 LAX 16:58 JFK 19:58
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86