V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hujianxin
V2EX  ›  Docker

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

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

    各位 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
    HypoChen
        3
    HypoChen  
       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   ·   实用小工具   ·   1162 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:30 · PVG 02:30 · LAX 10:30 · JFK 13:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.