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

Dockerfile 该如何优化?

  •  
  •   dream4ever · 23 天前 · 1732 次点击

    目前在用 Strapi 这个项目作为后端提供服务,为了让服务器环境尽量“干净”一点,整个项目是跑在 Docker 中的,包括 Node.js 程序和 MySQL 数据库。

    由于 Strapi 经常有功能更新和安全更新,所以服务器上的 Docker 镜像也需要经常更新。

    目前的 Docker 镜像在编译的时候分成了两部分,不会变化的 Node.js 和基础环境作为一个底层镜像,在此基础之上,再给不断升级版本的 Strapi 安装好 npm 包,然后编译成最终要用的镜像。

    底层镜像和最终镜像的 Dockerfile 内容如下面两段代码所示,分别用命令 docker build -t strapi.node-base -f ./Dockerfile.node-base .docker build -t strapi.final -f .\Dockerfile.final . 来构建镜像。

    想问一下以下两段 Dockerfile 有什么可以优化的地方么?去年给 4.15.5 版本的 Strapi 生成的镜像是 890MB ,今年给 4.24.2 版本的 Strapi 生成的镜像已经 1.23GB 了。希望能够优化一下 Dockerfile ,减小生成的镜像体积。

    # 底层镜像
    FROM node:18-alpine as strapi.node-base
    
    # 设置时区为东八区,这样在查看日志时才能显示正确的时间
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    
    # Installing libvips-dev for sharp Compatibility
    RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
      && apk update \
      && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
    ARG NODE_ENV=development
    ENV NODE_ENV=${NODE_ENV}
    
    WORKDIR /opt/
    COPY package.json yarn.lock ./
    RUN yarn global add node-gyp
    
    # 最终镜像
    FROM strapi.node-base as build
    RUN yarn config set network-timeout 600000 -g && yarn config set registry https://registry.npmmirror.com && yarn install
    ENV PATH /opt/node_modules/.bin:$PATH
    
    WORKDIR /opt/app
    COPY . .
    RUN chown -R node:node /opt/app
    USER node
    RUN ["yarn", "strapi", "ts:generate-types"]
    RUN ["yarn", "build"]
    EXPOSE 1337
    CMD ["yarn", "develop"]
    
    22 条回复    2024-06-03 12:49:03 +08:00
    defunct9
        1
    defunct9  
       23 天前
    没啥可优化的,就这么大。
    ho121
        2
    ho121  
       23 天前 via Android
    指令尽量少,每个指令都会多分一层。比如 RUN 尽量写一起
    ho121
        3
    ho121  
       23 天前 via Android
    安装、编译留下的缓存也要删掉
    iyiluo
        4
    iyiluo  
       23 天前
    为啥不用官方提供的镜像,官方提供的一般就是最优的
    dream4ever
        5
    dream4ever  
    OP
       23 天前
    @ho121 刚发现可以查看镜像的层信息,4.24.2 版本的 Strapi 用 yarn 安装好 npm 包之后,比 4.15.5 的 node_modules 文件夹多了 400M+ 的体积😂
    dream4ever
        6
    dream4ever  
    OP
       23 天前
    @iyiluo Strapi 官方的镜像已经是好几年前的了,官方文档也是建议自己弄。
    0o0O0o0O0o
        7
    0o0O0o0O0o  
       23 天前
    例如你 yarn build 之后,我觉得你就可以挑选一个合适的 base image 然后 COPY --from=build 来只包括真正需要的东西,而不是直接拿 builder 跑。
    ultimate42
        8
    ultimate42  
       23 天前
    FROM node:16-slim as base
    用精简版 node
    zhuisui
        9
    zhuisui  
       23 天前
    第一个,apk update/add 完之后,可以清理清理缓存。甚至看看有没有更小的基础镜像自己装 node
    第二个,yarn 也一样,安装完之后清理缓存,build 完之后清理开发依赖。如果不知道要清理啥,那就和 #7 说的一样,把 built 和 node_modules 拿出来用。

    最大的就是 node_modules ,没太多优化空间
    ultimate42
        10
    ultimate42  
       23 天前
    @ultimate42 #8 我去 我记反了 alpine 更小好像
    solos
        11
    solos  
       23 天前
    node_modules 搞到 docker 里?这个可是黑洞啊,你把黑洞放到 docker 镜像里了,哈哈哈
    ysc3839
        12
    ysc3839  
       23 天前 via Android
    基本思路就是 RUN 全写到一起,不然每一个 RUN 都会生成一个 layer ,然后包管理啥的缓存记得清理
    guanzhangzhang
        13
    guanzhangzhang  
       23 天前
    你那个 RUN chown -R 就大了

    ```
    COPY 一个 100M 二进制 bin_file /opt/bin_file
    RUN chmod a+x /opt/bin_file
    ```

    这样实际镜像带出去有两个 bin_file ,属性不一样,读取的是最后一个
    你可以下载个 dive 分析下 waste space ,后续我会打算写一个 github book ,关于镜像如何优化大小
    hefish
        14
    hefish  
       23 天前
    @guanzhangzhang 楼上正解。
    建议直接 ADD 或者 COPY 的时候 带上 --chown 参数。
    keakon
        15
    keakon  
       23 天前
    用 multi-stage 构建,第二个镜像用 FROM node:18-alpine ,然后 COPY --from=strapi.node-base ...
    如果没有 C 库依赖的话,COPY node_modules 就行了
    minoic
        16
    minoic  
       23 天前
    COPY . .
    RUN chown -R node:node /opt/app

    这两行要写在一起的,要不然体积翻倍。

    另外 build 操作为何在最终镜像里,感觉最终镜像应该只有运行环境和编译输出的代码吧?

    可以参考一下之前写的关于 Go 镜像的 [文章](
    https://www.minoic.top/%e5%87%8f%e5%b0%8f-go-%e5%ba%94%e7%94%a8%e7%9a%84-docker-%e9%95%9c%e5%83%8f%e4%bd%93%e7%a7%af/)
    dream4ever
        17
    dream4ever  
    OP
       23 天前
    @zhuisui
    @ysc3839 我去,Dockerfile 里加了一句 yarn cache clean 之后,本地编译出来的镜像体积直接从 3.51GB 降到了 1.67GB ,真爽,哈哈。
    dream4ever
        18
    dream4ever  
    OP
       22 天前
    @guanzhangzhang
    @hefish
    @minoic 把 COPY 和 chown 写一起了,又减少了 200M+ 的体积,真香。
    dream4ever
        20
    dream4ever  
    OP
       15 天前
    @guanzhangzhang 多谢,太棒了!
    guanzhangzhang
        21
    guanzhangzhang  
       13 天前
    @dream4ever #20 好兄弟,求个 star
    dream4ever
        22
    dream4ever  
    OP
       13 天前
    @guanzhangzhang 木有问题啊,已 star ,哈哈。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2391 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 15:30 · PVG 23:30 · LAX 08:30 · JFK 11:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.