V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
csfreshman
V2EX  ›  程序员

请教大家一个 docker 镜像制作相关问题

  •  
  •   csfreshman · 2021-08-07 23:35:54 +08:00 · 2433 次点击
    这是一个创建于 1233 天前的主题,其中的信息可能已经有所发展或是发生改变。

    工作中最近用到 docker,今天看了一天网上的教程看网上的教程 https://www.runoob.com/docker/docker-dockerfile.html

    注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

    FROM centos
    RUN yum install wget
    RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
    RUN tar -xvf redis.tar.gz
    以上执行会创建 3 层镜像。可简化为以下格式:
    FROM centos
    RUN yum install wget \
        && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
        && tar -xvf redis.tar.gz
    

    这里我试了这两种写法,docker 镜像的大小一样,这里制作 docker 镜像这两种写法有没有区别? centos:v3 是 3 个 run 生成的,v4 是第二种写法生成的。

    [root Dockerfile]#docker image ls
    REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
    centos            v4        ede9b36dd800   8 seconds ago   260MB
    centos            v3        6df19efb1980   3 minutes ago   260MB
    nginx             v3        3ca44131eb70   6 hours ago     133MB
    
    12 条回复    2021-08-08 15:09:29 +08:00
    muzuiget
        1
    muzuiget  
       2021-08-07 23:41:47 +08:00
    你这个示例数据量不足到可以看出明显区别。

    加多一个 RUN rm redis.tar.gz 就好了,后一种方法会少一个 redis.tar.gz 的大小。
    singerll
        2
    singerll  
       2021-08-07 23:42:46 +08:00 via Android
    你的操作太少了,而且几乎都是下载文件的操作
    hefish
        3
    hefish  
       2021-08-07 23:48:28 +08:00
    我觉着就上面的操作,没啥区别。不在乎那点。
    jj256
        4
    jj256  
       2021-08-08 00:11:20 +08:00 via iPhone
    dockerfile 里每次 run 生成的层只包含不同的部分,这点可以看下 docker 的 overlay 文件系统。所以我觉得只要执行的指令是一样的,分几层对镜像大小影响不大。
    statumer
        5
    statumer  
       2021-08-08 01:08:36 +08:00   ❤️ 1
    不要过早搞优化,精简镜像有很多方式,你真正在工作中遇见镜像产生瓶颈的情况再处理
    在你这种情况,你观察一下命令行的输出会发现,实际上 docker 会自动移除一些中间层
    Bromine0x23
        6
    Bromine0x23  
       2021-08-08 01:20:44 +08:00
    如果命令执行结果只是单纯的文件新增,合不合并区别不大。但是如果存在文件修改和文件删除的话,合并后大小就能减少。
    原因就是分层存储导致文件修改和文件删除的变化并不会影响到上层,从而整个镜像存储了无用的数据。
    joetse
        7
    joetse  
       2021-08-08 03:40:10 +08:00
    开发中分几层都无所谓, 能复用降低 build 的时间就行, 最终精简几乎都是用 from alpine copy --from=builder xx:yy
    wd
        8
    wd  
       2021-08-08 07:25:21 +08:00 via iPhone
    膨胀主要是你在下一层无法清理上一层的文件,如果你没有这个需要,那应该无论顺序如何都一样。
    ampedee
        9
    ampedee  
       2021-08-08 08:41:17 +08:00 via Android
    由于联合文件系统的存在,分再多层对镜像的体积影响也不大,合并指令的目的是为了清理无用的中间过程文件。
    推荐花个几分钟看下这篇介绍容器镜像原理的文章:
    https://www.waynerv.com/posts/learn-image-and-container-with-oci-spec/
    ragnaroks
        10
    ragnaroks  
       2021-08-08 09:44:49 +08:00
    你这本来就没区别,都是增加文件的操作,你起码最后要有个移除文件的操作
    ch2
        11
    ch2  
       2021-08-08 09:45:47 +08:00
    镜像大小无所谓的,大不了删了就是
    jim9606
        12
    jim9606  
       2021-08-08 15:09:29 +08:00
    你这个例子只有新增文件,大小区别基本没有,只有包含删除文件的操作才能体现区别。
    如果你这里的增加到下载、解压、编译、安装步骤,那么后面把源码和中间产物删掉才能体现区别。
    我个人并不喜欢将这几个步骤合并,因为 build 镜像时没法保留中间结果,导致每次出错重试都得重下源码。我倾向于用多阶段构建( Dockerfile 包含多个 FROM )
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   981 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:05 · PVG 07:05 · LAX 15:05 · JFK 18:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.