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镜像,使应用更易于部署和维护。

相关推荐
滴答滴答嗒嗒滴2 小时前
全栈加速:FrankenPHP 架构原理与实战案例
docker·微服务·性能优化·架构·php·高并发·frankenphp
Fireworkitte4 小时前
Docker 日志
docker·容器·eureka
潘yi.5 小时前
Docker环境部署
docker·微服务·容器
福如意如我心意6 小时前
使用docker-compose安装kafka
docker·zookeeper·kafka
Fireworkitte7 小时前
Docker Swarm 与 Kubernetes 在集群管理上的主要区别
docker·容器·kubernetes
Fireworkitte8 小时前
在 CI/CD 流程中使用 Jenkins 与 Docker 集成
ci/cd·docker·jenkins
ALe要立志成为web糕手9 小时前
docker安全
安全·web安全·docker·云安全
mxpan17 小时前
Alpine Docker 容器中安装包缓存与 C/C++ 运行问题
运维·docker·容器
ldj202019 小时前
Docker制作镜像
java·docker·容器
yumuing blog19 小时前
实战指南:部署MinerU多模态文档解析API与Dify深度集成(实现解析PDF/JPG/PNG)
docker·pdf·ocr·markdown·dify·parse·mineru