From c30677e612373e8abfc895dedf12bf3567485725 Mon Sep 17 00:00:00 2001 From: estom Date: Wed, 17 Jul 2024 10:53:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E9=98=B6=E6=AE=B5=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/12 分阶段构建.md | 99 +++++++++++++++++++++++++++++++++++++++ docker/13 覆盖原始命令.md | 13 +++++ 2 files changed, 112 insertions(+) create mode 100644 docker/12 分阶段构建.md create mode 100644 docker/13 覆盖原始命令.md diff --git a/docker/12 分阶段构建.md b/docker/12 分阶段构建.md new file mode 100644 index 00000000..9427e926 --- /dev/null +++ b/docker/12 分阶段构建.md @@ -0,0 +1,99 @@ +## 多阶段构建 +### Docker多阶段构建的好处 +使用Docker多阶段构建有以下几个好处: + +* 减小镜像大小:每个构建阶段只包含必要的依赖项和文件,从而减小了生成的镜像大小。这可以减少镜像的存储空间和传输时间。 +* 提高构建速度:每个构建阶段可以并行执行,因此可以提高构建速度。而且,每个构建阶段只构建所需的内容,从而减少了构建时间。 +* 简化Dockerfile:使用多个构建阶段可以将Dockerfile分解为更小的部分,从而使Dockerfile更加易于管理和维护。每个构建阶段都可以专注于特定的任务,而不必关注整个构建过程。 +* 提高安全性:使用多个构建阶段可以限制敏感信息的泄露。例如,在第一个构建阶段中,可以包含敏感信息,例如私有密钥或密码。而在第二个构建阶段中,可以只包含必要的文件和依赖项。 + + +### 单独执行rm并不会精简镜像体积 + +尽管在 Dockerfile 中使用 RUN rm -rf /tmp/* 删除了大量文件,但你可能会发现最终生成的 Docker 镜像的大小并没有显著变化。这是因为每个 Dockerfile 指令都会创建一个新的镜像层,而删除文件的操作并不会减少已有层的大小。 删除的文件其实仍然存在于之前的层中,导致镜像整体大小没有减少。 + +要优化镜像大小,你可以考虑以下几个方法: + +合并命令以减少镜像层数。将相关的运行命令合并到一个 RUN 指令中,以减少镜像层数。例如,你可以将安装软件包和删除缓存文件的操作合并到一个 RUN 指令中: +``` +FROM ubuntu:latest + +# 更新包列表、安装软件包并删除缓存文件 +RUN apt-get update && apt-get install -y \ + curl vim \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +``` +通过这种方式,删除操作和安装操作在同一个层完成,避免了无用文件占用空间。 + + + +### 多阶段构建精简镜像体积 +多阶段构建是一种优化 Docker 镜像大小的方法,可以在构建过程中使用临时构建环境,并在最终镜像中只保留必要的部分。COPY --from复制之前镜像中执行的必要的结果。 +``` +# 第一阶段:构建环境 +FROM node:14 AS builder + +# 在构建环境中执行构建操作 +WORKDIR /app +COPY package.json . +RUN npm install +COPY . . +RUN npm run build + +# 第二阶段:最终镜像 +FROM nginx:alpine + +# 仅复制构建产物,并删除临时文件夹 +COPY --from=builder /app/dist /usr/share/nginx/html + +# 删除不必要的目录 +RUN rm -rf /usr/share/nginx/html/temp + +# 定义容器启动时运行的命令 +CMD ["nginx", "-g", "daemon off;"] +``` + + +### 目录挂载精简镜像体积 + +在 Docker 构建过程中,通常是基于本地文件的路径进行操作的,但有时候可能需要从另一个镜像中获取文件。在 Docker 18.09 版本引入了 BuildKit 功能,其中一个特性是支持在 docker build 中使用挂载点(mounts)来访问其他镜像的文件。 + +以下是具体的方法和示例: + +使用 BuildKit 进行挂载 +* --mount=type=bind 和 --mount=type=cache 是 BuildKit 支持的特性,其中 type=bind 可以用来挂载本地文件系统中的文件,而 type=cache 则常用于缓存构建依赖。但是要访问另一个镜像的文件,通常使用 --mount=type=bind 结合 COPY --from 的多阶段构建来实现。 + +启用 BuildKit +首先确保 Docker Daemon 启用了 BuildKit。可以在环境变量中设置 DOCKER_BUILDKIT=1: +``` +export DOCKER_BUILDKIT=1 +``` +或者在 Docker 运行时添加 --build-arg BUILDKIT_INLINE_CACHE=1 选项: +``` +DOCKER_BUILDKIT=1 docker build . +``` +示例 +``` +# Dockerfile 示例:使用 npm 缓存 + +# 基础镜像 +FROM node:14-alpine AS builder + +WORKDIR /app + +# 挂载缓存目录并安装依赖 +RUN --mount=type=cache,target=/root/.npm \ + npm install + +# 添加应用程序源代码 +COPY . . + +# 构建应用程序 +RUN npm run build + +# 使用最小化的基础镜像 +FROM nginx:alpine + +# 复制构建产物到最终镜像 +COPY --from=builder /app/build /usr/share/nginx/html +``` \ No newline at end of file diff --git a/docker/13 覆盖原始命令.md b/docker/13 覆盖原始命令.md new file mode 100644 index 00000000..f0167cf6 --- /dev/null +++ b/docker/13 覆盖原始命令.md @@ -0,0 +1,13 @@ +如果你的 Dockerfile 中有如下定义: +``` +ENTRYPOINT ["python"] +CMD ["app.py"] +``` +你可以在启动容器时使用 --entrypoint 选项来覆盖 ENTRYPOINT,并且提供新的命令来覆盖 CMD: +``` +docker run --entrypoint /bin/sh +``` +或者同时覆盖 ENTRYPOINT 和 CMD: +``` +docker run --entrypoint /bin/sh -c "ls -la" +``` \ No newline at end of file