Dockerfile 编写经验:优化大小与效率

文章目录

    • [Dockerfile 通用的技巧总结](#Dockerfile 通用的技巧总结)
      • [1. 使用多阶段构建](#1. 使用多阶段构建)
      • [2. 最小化层数](#2. 最小化层数)
      • [3. 彻底清理](#3. 彻底清理)
      • [4. 选择合适的基镜像](#4. 选择合适的基镜像)
      • [5. 仅安装必要的依赖](#5. 仅安装必要的依赖)
      • [6. 利用构建缓存](#6. 利用构建缓存)
    • 常见陷阱
    • 总结

Dockerfile 通用的技巧总结

1. 使用多阶段构建

  • 利用多阶段构建分离构建和运行时环境,仅将必要的产物(二进制文件、库、配置)复制到最终阶段,这通过排除构建工具和中间文件保持运行时镜像精简

  • 示例:仅从构建阶段复制编译后的二进制文件和特定资源

    dockerfile 复制代码
    WORKDIR /device-openvino
    # Copy binaries and resources from the builder stage
    COPY --from=builder /device-openvino/device-openvino-object-classification-c /device-openvino/device-openvino-object-classification-c
    # Copy the CSDK library (custom dependency built by build_deps.sh)
    COPY --from=builder /opt/iotech/iot/1.5/lib /opt/iotech/iot/1.5/lib
    COPY --from=builder /device-openvino/deps/device-sdk-c/build/release/_CPack_Packages/Linux/TGZ/csdk-0.0.0 /device-openvino/csdk
    # copy device service configuration file
    COPY res/configuration.yaml /device-openvino/res/configuration.yaml
    COPY res/profiles /device-openvino/res/profiles
    COPY res/devices /device-openvino/res/devices

2. 最小化层数

  • 将相关命令(例如,apt-get update && apt-get install )合并到单个 RUN 指令中,以减少层数。每个 RUN 都会创建一个新层,增加镜像大小。

  • 使用&&\保持可读性,同时串联命令。

    dockerfile 复制代码
    # Configure the image source and install runtime dependencies
    RUN sed -i 's/archive.ubuntu.com/mirror.nju.edu.cn/g' /etc/apt/sources.list && \
        sed -i 's/security.ubuntu.com/mirror.nju.edu.cn/g' /etc/apt/sources.list && \
        apt-get update && apt-get install -y curl gnupg && \
        # Configure OpenVINO repository
        curl -fsSL https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | apt-key add - && \
        echo "deb https://apt.repos.intel.com/openvino/2025 ubuntu22 main" | tee /etc/apt/sources.list.d/intel-openvino-2025.list && \
        # Configure Intel GPU repository
        curl -fsSL https://repositories.intel.com/gpu/intel-graphics.key | \
        gpg --yes --dearmor --output /usr/share/keyrings/intel-graphics.gpg && \
        echo "deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/gpu/ubuntu jammy unified" | \
        tee /etc/apt/sources.list.d/intel-gpu-jammy.list && \
        # Install runtime dependencies
        apt-get update && apt-get install -y \
        # base dependencies
        dumb-init \
        libyaml-dev \
        uuid-dev \
        libpaho-mqtt-dev \
        libcbor-dev \
    ...

3. 彻底清理

  • 在包安装后始终移除临时文件,例如APT缓存(/var/lib/apt/lists/*)。使用apt-get clean--no-install-recommends避免不必要的依赖。

  • 示例:

    dockerfile 复制代码
        # cleanup
        --no-install-recommends && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/*

4. 选择合适的基镜像

  • 选择满足需求的最小基镜像(例如,ubuntu:22.04 或更小的 debian:slim )。除非必要,避免使用臃肿的镜像。

  • 明确指定平台(例如,--platform=linux/amd64 )以确保兼容性

    dockerfile 复制代码
    # including its dependencies
    ARG BASE=ubuntu:22.04
    FROM --platform=linux/amd64 ${BASE} as builder
    LABEL license='SPDX-License-Identifier: Apache-2.0' \
    ...

5. 仅安装必要的依赖

  • 精确指定运行时依赖。避免在最终镜像中安装开发包(例如,libopencv-dev),除非必要。新版Dockerfile选择性安装OpenCV模块是一个很好的示例。
  • 使用apt-cache search或包文档确定确切的依赖。

6. 利用构建缓存

  • 按从最不可能更改到最可能更改的顺序排列指令(例如,先安装包,再复制源代码)。这最大化构建缓存的复用。

  • 新版Dockerfile在 make 之前复制源代码,确保早期层(例如依赖安装)被缓存,能大大节省构建时间!

    dockerfile 复制代码
    # build device service 
    COPY src /device-openvino/src
    COPY Makefile /device-openvino/Makefile
    RUN make clean build
    
    # Stage 2: Create the final runtime image
    FROM --platform=linux/amd64 ${BASE}

常见陷阱

  • 过度安装依赖 :在运行时镜像中安装广泛的包(例如,libopencv-dev)会增加体积。始终验证运行时需求。
  • 忘记清理:不移除APT缓存或临时文件会在镜像中留下不必要的数据。
  • 冗余指令:重复环境变量设置或存储库配置会增加层数和复杂性。
  • 未固定版本:不指定包版本可能导致构建不一致。
  • 广泛的COPY命令:不加筛选地复制整个目录会包含未使用的文件,增加大小。

总结

本文展示了如何通过合并命令、清理缓存和选择最小依赖等小而精心的更改,显著减少 Dockerfile 构建镜像的大小、开发过程的效率以及发布后的稳定性。通过遵循上述技巧,可以创建精简、安全且高效的Docker镜像,使应用更易于部署和维护。

相关推荐
IT利刃出鞘7 小时前
Nginx--手写脚本压缩和切分日志(也适用于docker)
运维·nginx·docker
ZPC82108 小时前
Docker+MobaXterm+x11实现容器UI界面转发本地
ui·docker·容器
qq_冯小阳9 小时前
Docker修改镜像存放位置
运维·docker·容器
ZHOU_WUYI9 小时前
FastAPI在 Nginx 和 Docker 环境中的部署
nginx·docker·fastapi
星垣矩阵架构师9 小时前
使用Dockerfile创建镜像
docker
hanzhuhuaa14 小时前
docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(1)
redis·docker·php
cxr82816 小时前
Docker Desktop for Windows 系统设置说明文档
windows·docker·容器
傅里叶的耶16 小时前
Docker系列(二):从零构建容器环境|服务自启配置×镜像源加速×免sudo提权×避坑手册
linux·ubuntu·docker·容器
默默无闻的白夜17 小时前
【Docker】存储卷
运维·docker·容器
CaseyWei18 小时前
(转)Docker与K8S的区别
docker·容器·kubernetes