Files
Kubernetes/Docker/Builder/Buildkit/README.md
2025-08-25 17:53:08 +08:00

360 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> 本文作者:丁辉
# Buildkit构建镜像
## 最小化使用 Buildkit 构建镜像
1. 修改 docker 守护进程配置
```bash
vi /etc/docker/daemon.json
```
2. 加入
```bash
{
"features": {
"buildkit": true
}
}
```
重载 docker
```bash
systemctl daemon-reload && systemctl reload docker
```
> 如果报错提示需要安装 Buildx , 则查看 [BUILDX安装](https://gitee.com/offends/Kubernetes/tree/main/Docker/Builder/Buildx/README.md) 安装一下
3. 构建镜像
```bash
DOCKER_BUILDKIT=1 docker build --no-cache -t app:v1 .
```
## 使用完全体 Buildkit 构建镜像
[官方文档](https://docs.docker.com/build/buildkit/)
### 安装
1. 克隆代码
```bash
git clone https://gitee.com/offends/Kubernetes.git
cd Kubernetes/Docker/Builder/Buildkit
```
2. 安装 Buildkit
> 这里使用 . 执行脚本否则需要手动执行 `source /etc/profile`
```bash
. install.sh
```
3. 安装 Buildx(非必选, 如果不希望安装Buildx, 则直接看文档"基础命令"部分来构建镜像)
查看此文档: [BUILDX安装](https://gitee.com/offends/Kubernetes/tree/main/Docker/Builder/Buildx/README.md)
### Dockerfile 写法介绍
> Dockerfile `# syntax = docker/dockerfile:<声明>` 是必加的
[官方文档](https://docs.docker.com/build/dockerfile/frontend/#custom-dockerfile-syntax)
1. `# syntax=docker/dockerfile:1`
这个指令指定了 Dockerfile 使用的语法版本。在这个例子中,`:1` 表示使用 Dockerfile 的第一个版本。这个版本引入了基本的 Dockerfile 功能,是最基础的语法规则。它是 Dockerfile 的最低版本,提供了最基本的指令和结构,不包含较新的特性。
2. `# syntax = docker/dockerfile:experimental`
这个语法声明告诉 Docker 使用实验性特性来解析 Dockerfile。`experimental` 标记引入了一些实验性的功能,可能包含一些不稳定或尚未广泛测试的功能,允许使用一些较新的、可能还不是标准的 Dockerfile 特性。使用这个标记可以在 Dockerfile 中尝试新的、实验性的功能。
### 挂载缓存目录 cache
> 这里是通过存储 Docker 缓存当中实现的,咱们通过两次构建演示过程
1. 编写 Dockerfile
```bash
vi Dockerfile
```
- 第一次构建
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine
RUN --mount=type=cache,target=/data,id=file_dir,sharing=locked \
echo "hello" >> /data/file.txt
```
- 第二次构建
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine
RUN --mount=type=cache,target=/data,id=file_dir,sharing=locked \
echo "hello-2" >> /data/file.txt; \
cp /data/file.txt /
```
2. 开始构建
```bash
docker build -t app:v1 .
```
3. 检查结果
```bash
docker run -it --rm app:v1 sh
cat file.txt
```
> 发现有两行内容则代表容器第二次构建已经使用到缓存了
**参数解释**
| 参数 | 描述 |
| ------- | --------------------------------------------------- |
| id | 用于标识不同缓存的可选ID。默认为目标值。 |
| target1 | 挂载路径。 |
| ro | 如果设置,只读。 |
| sharing | 其中一个 shared、private 或 locked。默认为 shared。 |
| from | 用作缓存挂载基础的构建阶段。默认为空目录。 |
| source | 要挂载的源自 from 的子路径。默认为 from 的根目录。 |
| mode | 新缓存目录的文件模式(八进制)。默认为 0755。 |
| uid | 新缓存目录的用户ID。默认为 0。 |
| gid | 新缓存目录的组ID。默认为 0。 |
**sharing参数**
1. **Shared (shared)**: 这是默认设置。在共享模式下,多个写入者可以同时使用相同的缓存挂载。这意味着多个构建可以同时读取和写入缓存数据。
2. **Private (private)**: 当设置为私有模式时,如果存在多个写入者,它会为每个写入者创建一个新的挂载。这样可以避免并发写入的冲突,但也可能导致存储空间的浪费。
3. **Locked (locked)**: 锁定模式会暂停第二个写入者的操作,直到第一个写入者释放挂载。这确保了在任何给定时刻只有一个写入者能够访问缓存挂载,从而避免了并发写入的问题,但也可能导致构建延迟。
### 挂载文件 bind
> 将一个镜像或上一构建阶段的文件挂载到指定位置
1. 编写 Dockerfile
```bash
vi Dockerfile
```
内容如下
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine AS builder
RUN apk add git \
&& git clone https://gitee.com/offends/Docs.git \
&& tar -cvf Docker-Template.tar ./Docker-Template
FROM alpine
# 挂载上一构建阶段文件
RUN --mount=type=bind,from=builder,source=/Docker-Template.tar,target=/Docker-Template.tar \
cp /Docker-Template.tar /Docker-Template.tar.bak
# 挂载另一个镜像的文件
RUN --mount=type=bind,from=nginx:alpine-slim,source=/etc/nginx/nginx.conf,target=/nginx.conf \
cp /nginx.conf /nginx.conf.bak
```
2. 开始构建
```bash
docker build -t app:v1 .
```
3. 检查结果
```bash
docker run -it --rm app:v1 sh
ls
```
> / 目录下存在 nginx.conf.bak 和 Docker-Template.tar.bak 则代表成功
### 挂载文件系统 tmpfs
> 将文件系统挂载到指定位置
1. 编写 Dockerfile
```bash
vi Dockerfile
```
内容如下
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine
RUN --mount=type=tmpfs,size=100m,target=/temp \
echo "hello" > /temp/file.txt
```
2. 开始构建
```bash
docker build -t app:v1 .
```
3. 检查结果
```bash
docker run -it --rm app:v1 sh
ls /temp
```
> 没有文件则正确,因为在 RUN 执行完命令之后挂载的文件系统将会被卸载
### 加密内容管理
> 为了更好的看到效果我们拿创建目录 hello-file 举例
#### 示例一(加密文件挂载)
[官网文档](https://docs.docker.com/engine/reference/builder/#run---mounttypesecret)
1. 编写挂载文件
```bash
cat > file_secret <<EOF
hello-file
EOF
```
2. 编写 Dockerfile
```bash
vi Dockerfile
```
内容如下
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine
RUN --mount=type=secret,id=file_secret,target=/run/secrets/file_secret \
mkdir $(cat /run/secrets/file_secret)
```
3. 开始构建
```bash
docker build --no-cache --secret id=file_secret,src=./file_secret -t app:v1 .
```
4. 检验结果
```bash
docker run -it --rm app:v1 sh
ls
```
> 看到 / 下存在 hello-file 目录,并且挂载的 file_secret 也消失了,则代表加密内容已成功传入。
#### 示例二(加密变量传入)
[官网文档](https://docs.docker.com/engine/reference/commandline/buildx_build/#env)
1. 编写 Dockerfile
```bash
vi Dockerfile
```
内容如下
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine
RUN --mount=type=secret,id=env_secret,target=/run/secrets/env_secret \
mkdir $(cat /run/secrets/env_secret)
```
2. 开始构建
```bash
env_secret=hello-file docker buildx build --no-cache --secret id=env_secret -t app:v1 --load .
```
### SSH 密钥管理
[官网文档]()
> gitee 仓库举例
1. 编写 Dockerfile
```bash
vi Dockerfile
```
内容如下
```dockerfile
# syntax = docker/dockerfile:1
FROM alpine
# 如果是Github 则使用 github.com
RUN apk add --no-cache openssh-client git \
&& mkdir -p -m 0600 ~/.ssh && ssh-keyscan gitee.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh git clone git@gitee.com:offends/Docker.git
```
2. 开始构建
```bash
docker build --ssh default=~/.ssh/id_rsa -t app:v1 .
```
# 基础命令
1. 清理缓存
```bash
docker builder prune
```
2. 构建镜像并打包
> 镜像不会存在于 docker images 内,用于单纯的打包最好不过了
```bash
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--output type=docker,name=app:v1,dest=image.tar
```
**参数解释**
| 参数 | 描述 |
| ----------------------------------------------- | ------------------------------------------------------------ |
| --frontend=dockerfile.v0 | 使用的构建前端,这里是 Dockerfile 的版本。 |
| --local context=. | 指定本地上下文路径,即构建过程中使用的上下文路径(当前目录)。 |
| --local dockerfile=. | 指定本地 Dockerfile 路径,即 Dockerfile 所在的路径(当前目录)。 |
| --output type=docker,name=app:v1,dest=image.tar | 输出设置,指定输出的类型为 Docker 镜像type=docker镜像的名称为 app:v1name=app:v1输出目标为 image.tar 文件dest=image.tar。 |