wangxiaoaer
V2EX  ›  问与答

Docker 的一些疑问

  •  
  •   wangxiaoaer · Aug 15, 2018 · 1931 views
    This topic created in 2914 days ago, the information mentioned may be changed or developed.

    有个需要打造成产品化的应用,再 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 replies    2018-08-16 09:23:49 +08:00
    ThirdFlame
        1
    ThirdFlame  
       Aug 15, 2018
    同为 docker 的初学者 只能解决 image 导入 导出
    docker save 9045 > tomcat8-apr.tar
    docker save -o 要保存的文件名 要保存的镜像

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

    制作镜像时 每 RUN 一次,就生成一层,尽量一次 RUN 完。 你装的依赖越多,肯定就会越大。
    isCyan
        2
    isCyan  
       Aug 15, 2018
    1. 是
    2. 有许许多多的免费私有镜像仓库服务商,比如 daocloud tenxcloud 现在七牛也出了
    3. 在创建镜像的时候;是的
    4. 算法没有问题。容器服务就是贵。Docker Kubernates 都是开源的,一般企业自己搞搞都能用,省钱重要
    5. https://blog.bohan.co/2018/07/22/docker-china/
    Cbdy
        3
    Cbdy  
       Aug 15, 2018
    1. 尽量减少 RUN 命令条数,一次 RUN 会产生一个 layer
    2. 可以
    3. 创建的时候,是的
    4. ?
    5. deb/rpm 安装 docker,配置 Registry mirrors
    wangxiaoaer
        4
    wangxiaoaer  
    OP
       Aug 15, 2018
    3:按我的理解,创建的时候 npm install 是不是会增加 image 的体积,运行的时候不是更好,虽然第一次启动会慢点?
    isCyan
        5
    isCyan  
       Aug 15, 2018
    @wangxiaoaer 镜像的意思就是所有东西都固定了,版本都是一样的,在这台机器上能跑出 123 在另外一台机器上就不可能出 456,而且你可以用 tag 设定版本
    giuem
        6
    giuem  
       Aug 15, 2018
    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  
       Aug 15, 2018
    1. 是,更好的方式是区分 Depends 和 BuildDepends,在镜像 1 (=Depends + BuildDep )中编译,把编译出的文件拷贝到镜像 2 (=Depends,版本一致)
    2. 可以,但建议还是自己搭一个内部 DockerHub
    3. 创建时。是的,已经物理接触了做啥也没用
    4. 负载均衡你们怎么做?服务发现?网络调优会不会? I/O 性能不行怎么办?物理机挂了怎么自动迁移?开源版 Docker 的 Bug 怎么处理?这都是容器服务的成本
    5. 国内有源的镜像
    yanaraika
        8
    yanaraika  
       Aug 15, 2018
    @wangxiaoaer 这就失去了 docker 的意义。你可以 build 完清理一下 node_modules
    fuxkcsdn
        9
    fuxkcsdn  
       Aug 15, 2018 via iPhone
    关于网络问题,你可以在国外买一台 vps,镜像生成完导出传回本地,删除 vps,费用低,速度快。可以找免费保存自定义系统镜像的 vps 服务商,这样不用每次创建 vps 都要重新安装编译环境
    wangxiaoaer
        10
    wangxiaoaer  
    OP
       Aug 15, 2018
    @yanaraika #7 那和本地物理机编译后直接拷贝到 image 中有区别吗,如果版本都保持一致的话?
    wangxiaoaer
        11
    wangxiaoaer  
    OP
       Aug 15, 2018
    @isCyan #5 明白了,是说运行时 npm install 可能会导致安装的东西不一样,所以创建时就固话了?
    isCyan
        12
    isCyan  
       Aug 15, 2018   ❤️ 1
    @wangxiaoaer npm 的包都有版本,如果包更新了,再 build 出来的镜像就跟之前不一样了,程序就不知道跑不跑得起来。你可以在 Dockerfile 里面写好版本,这样每个 Dockerfile build 出来都该是一模一样的
    wangxiaoaer
        13
    wangxiaoaer  
    OP
       Aug 15, 2018
    @yanaraika #7

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

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

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

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