V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
wangxiaoaer
V2EX  ›  问与答

Docker 的一些疑问

  •  
  •   wangxiaoaer · 2018-08-15 21:37:15 +08:00 · 1166 次点击
    这是一个创建于 2271 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有个需要打造成产品化的应用,再 linux 下运行,需要编译 c++的代码给 nodejs 用,觉得如果每次都到客户服务器去安装各种环境比较麻烦,所以在想 docker 是不是合适。

    如果合适的话有一些疑问:

    1 镜像制作

    在创建 dockerfile 的时候,首先把 c++代码拷贝进去,然后安装依赖,编译,删掉源码,清理安装包,是这个流程吗? 但是如何保障清理到位,安装的依赖可能很多,如果清理不干净是不是会导致 image 特别大?

    2 镜像发布

    创建好的镜像不适合放到 dockerhub 上,直接拷贝到目标机器可以吗?

    3 镜像运行

    类似 npm install 这种命令是在创建镜像的时候运行还是容器启动的时候运行?另外,第三方如果接触到了服务器,是不是可以通过 docker 的交互命令把编译好的内容拷贝出来?

    4 成本(这里的成本跟上面说的那个产品无关,说的是我们自己的一些应用)

    按我的理解,一般一个应用一个 docker 容器,如果是自己的物理服务器,配置高点,可以跑很多个容器。但是如果是购买类似阿里云上面的容器服务,感觉稍微高点的配置就很贵,比如一个计算型的 4 核 8g 的实例将近 2.5 元一个小时,一年 1.8w 左右,同样的物理服务器 1 年 1w 多点。

    假设我们有 10 个应用,1 个 java 内存耗的多点,买了那个计算型的实例,其他 9 个买的低内存实例,1 年 2.5 万差不多了。

    但是购买 ECS 的话,4 核 8g 上面跑 10 个应用问题不大,因为 java 那个应用未必一直占用资源,算下来即使扩充到 4 核 16g,1 年也不会超过 2w。这个算法有什么问题吗?还是使用方式不当?

    5 网络环境

    docker hub 可以用国内镜像,但是通过 apt 安装 docker 费了老大劲,因为 docker.com 被墙了啊,客户服务器环境难道还需要临时搭建一个科学上网的服务?

    docker 新手,上面问题恳请大佬帮帮忙。

    24 条回复    2018-08-16 09:23:49 +08:00
    ThirdFlame
        1
    ThirdFlame  
       2018-08-15 21:45:40 +08:00
    同为 docker 的初学者 只能解决 image 导入 导出
    docker save 9045 > tomcat8-apr.tar
    docker save -o 要保存的文件名 要保存的镜像

    docker load < tomcat8-apr.tar
    docker load --input 文件

    制作镜像时 每 RUN 一次,就生成一层,尽量一次 RUN 完。 你装的依赖越多,肯定就会越大。
    isCyan
        2
    isCyan  
       2018-08-15 21:47:20 +08:00
    1. 是
    2. 有许许多多的免费私有镜像仓库服务商,比如 daocloud tenxcloud 现在七牛也出了
    3. 在创建镜像的时候;是的
    4. 算法没有问题。容器服务就是贵。Docker Kubernates 都是开源的,一般企业自己搞搞都能用,省钱重要
    5. https://blog.bohan.co/2018/07/22/docker-china/
    Cbdy
        3
    Cbdy  
       2018-08-15 21:47:24 +08:00
    1. 尽量减少 RUN 命令条数,一次 RUN 会产生一个 layer
    2. 可以
    3. 创建的时候,是的
    4. ?
    5. deb/rpm 安装 docker,配置 Registry mirrors
    wangxiaoaer
        4
    wangxiaoaer  
    OP
       2018-08-15 21:52:52 +08:00
    3:按我的理解,创建的时候 npm install 是不是会增加 image 的体积,运行的时候不是更好,虽然第一次启动会慢点?
    isCyan
        5
    isCyan  
       2018-08-15 21:54:54 +08:00
    @wangxiaoaer 镜像的意思就是所有东西都固定了,版本都是一样的,在这台机器上能跑出 123 在另外一台机器上就不可能出 456,而且你可以用 tag 设定版本
    giuem
        6
    giuem  
       2018-08-15 21:55:21 +08:00
    1. 大体是这个流程,或者使用 multi-stage builds https://docs.docker.com/develop/develop-images/multistage-build/

    2. 可以使用私有 registry,官方或自建都可以。国内像阿里、七牛都有提供容器镜像服务。比如阿里的 https://www.aliyun.com/product/acr?spm=5176.8142029.search.3.e9396d3etWSdTb

    3. npm install 在创建镜像的时候运行,每次启动再安装依赖不得慢死;可以通过 docker cp 拷贝

    4. 没看懂

    5. 可以使用国内镜像安装
    ```
    curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
    ```
    yanaraika
        7
    yanaraika  
       2018-08-15 21:58:16 +08:00
    1. 是,更好的方式是区分 Depends 和 BuildDepends,在镜像 1 (=Depends + BuildDep )中编译,把编译出的文件拷贝到镜像 2 (=Depends,版本一致)
    2. 可以,但建议还是自己搭一个内部 DockerHub
    3. 创建时。是的,已经物理接触了做啥也没用
    4. 负载均衡你们怎么做?服务发现?网络调优会不会? I/O 性能不行怎么办?物理机挂了怎么自动迁移?开源版 Docker 的 Bug 怎么处理?这都是容器服务的成本
    5. 国内有源的镜像
    yanaraika
        8
    yanaraika  
       2018-08-15 21:59:25 +08:00
    @wangxiaoaer 这就失去了 docker 的意义。你可以 build 完清理一下 node_modules
    fuxkcsdn
        9
    fuxkcsdn  
       2018-08-15 21:59:32 +08:00 via iPhone
    关于网络问题,你可以在国外买一台 vps,镜像生成完导出传回本地,删除 vps,费用低,速度快。可以找免费保存自定义系统镜像的 vps 服务商,这样不用每次创建 vps 都要重新安装编译环境
    wangxiaoaer
        10
    wangxiaoaer  
    OP
       2018-08-15 22:04:03 +08:00
    @yanaraika #7 那和本地物理机编译后直接拷贝到 image 中有区别吗,如果版本都保持一致的话?
    wangxiaoaer
        11
    wangxiaoaer  
    OP
       2018-08-15 22:06:09 +08:00
    @isCyan #5 明白了,是说运行时 npm install 可能会导致安装的东西不一样,所以创建时就固话了?
    isCyan
        12
    isCyan  
       2018-08-15 22:08:06 +08:00   ❤️ 1
    @wangxiaoaer npm 的包都有版本,如果包更新了,再 build 出来的镜像就跟之前不一样了,程序就不知道跑不跑得起来。你可以在 Dockerfile 里面写好版本,这样每个 Dockerfile build 出来都该是一模一样的
    wangxiaoaer
        13
    wangxiaoaer  
    OP
       2018-08-15 22:16:20 +08:00
    @yanaraika #7

    第一点是为了解决清理干净的问题吧,就是把编译好的包拷贝到另外一个容器?全部通过 docker 命令实现还是?
    yanaraika
        14
    yanaraika  
       2018-08-16 00:29:17 +08:00   ❤️ 1
    @wangxiaoaer
    1. 如果能完全保持一致当然是可以的,但实际上总会有不可预料的 inconsistency 发生,新开一个容器编译更可控可靠
    2. 嗯,见 https://yq.aliyun.com/articles/181178。
    zmj1316
        15
    zmj1316  
       2018-08-16 02:22:05 +08:00 via Android
    1 docker 镜像每一步 run 都有 layer 的 你把源码删了应该只影响下一级的 layer 上一级的还是有源码。。。
    zgray
        16
    zgray  
       2018-08-16 07:21:25 +08:00 via iPhone
    对于 1 应考虑编译与运行分离
    wangxiaoaer
        17
    wangxiaoaer  
    OP
       2018-08-16 08:21:46 +08:00
    @yanaraika #14

    感谢大佬!!!!! 这个多阶段构建恰好能满足我的需求啊。
    mritd
        18
    mritd  
       2018-08-16 09:09:30 +08:00 via iPhone
    手机回复,记不住太多问题,请见谅

    第一点编译问题,对于 c 系的编译,在编译期需要安装大量编译依赖,比如 gcc 等,这会造成镜像体积庞大,解决办法有 2 种,尽量压缩命令到一个 RUN 内,然后在编译完成后手动移除,比如 "RUN 安装 && 编译 && 清理",另一种办法采用多步构建,即从一个镜像内构建,然后将构建发布物复制到另一个纯粹的运行时镜像内,这种方案需要你对你的应用足够了解,比如编译生成的哪些文件是有用的
    mritd
        19
    mritd  
       2018-08-16 09:12:34 +08:00 via iPhone
    第二点,镜像发布除了可开源的,比如自己做了一些好用的基础镜像,类似 tomcat 这种,你可以开源推送到 docker hub,否则包含你们业务代码的绝对不可推送上去,尤其是脚本语言项目,那跟开源自己公司代码一样,正确做法是搭建私服,比如使用 harbor,将私有镜像推送到内网私服
    znood
        20
    znood  
       2018-08-16 09:15:56 +08:00 via iPhone
    构建环境和生产环境要区分,不要用同一个镜像,可以使用 ci pipeline
    mritd
        21
    mritd  
       2018-08-16 09:17:04 +08:00 via iPhone
    第三点,npm install 这种应当在镜像制作时完成,因为这算做运行时依赖(runtime),docker 有一部分功能就是保证运行时一致性,如果你在启动后做,那么恕我直言,npm 的尿性包管理配置不好很可能在不同时间点 出现有的成功有的失败这种情况(比如某些包要去 github 下载文件,过几天 guthub 文件被删了),最终你要保证一点,runtime 在 build 期固化,运行时只应当做一些启动动作,或者额外附加一些 文件的权限修复 (chmod)
    mritd
        22
    mritd  
       2018-08-16 09:20:37 +08:00 via iPhone
    第四点,成本问题没法回答你,自己测试自己算喽🙃

    第五点,docker 安装包可以离线下载,正常情况你也不应该每个机器都用 包管理器从网络安装,因为在不同时间点你可能安装出多个版本来,版本间兼容性可能影响你的稳定性,同一个集群应当保持版本一致,还有一点也是我被坑过的事,apt 安装后会在本地写入 apt 源,有一天有人没看就来了一下 apt uograde -y
    uorz
        23
    uorz  
       2018-08-16 09:21:46 +08:00 via Android
    用 docker 的分段编译,完全不用担心最后的 images 过大。最简单的方式是在你本地编译通过,然后用 ldd 看需要哪些 so 文件,,这样根本不关 gcc 啥事,用 ADD 把这些文件添加到 docker 里面,然后 export 一下你的 docker image。生成的文件像 binary 一样拷过去 import 一下就成了。
    uorz
        24
    uorz  
       2018-08-16 09:23:49 +08:00 via Android
    用 export 完全不用担心啥 docker history 被泄露
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1474 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:38 · PVG 01:38 · LAX 10:38 · JFK 13:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.