分阶段构建

This commit is contained in:
estom
2024-07-17 10:53:45 +08:00
parent b002270ab2
commit c30677e612
2 changed files with 112 additions and 0 deletions

View File

@@ -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
```

View File

@@ -0,0 +1,13 @@
如果你的 Dockerfile 中有如下定义:
```
ENTRYPOINT ["python"]
CMD ["app.py"]
```
你可以在启动容器时使用 --entrypoint 选项来覆盖 ENTRYPOINT并且提供新的命令来覆盖 CMD
```
docker run --entrypoint /bin/sh <image>
```
或者同时覆盖 ENTRYPOINT 和 CMD
```
docker run --entrypoint /bin/sh <image> -c "ls -la"
```