Kubernetes/Docker/Builder/Buildkit
offends 7a2f41e7d6
All checks were successful
continuous-integration/drone Build is passing
synchronization
2024-08-07 18:54:39 +08:00
..
buildkitd.service synchronization 2024-08-07 18:54:39 +08:00
buildkitd.toml synchronization 2024-08-07 18:54:39 +08:00
install.sh synchronization 2024-08-07 18:54:39 +08:00
README.md synchronization 2024-08-07 18:54:39 +08:00

本文作者:丁辉

Buildkit构建镜像

最小化使用 Buildkit 构建镜像

  1. 修改 docker 守护进程配置

    vi /etc/docker/daemon.json
    
  2. 加入

    {
      "features": {
        "buildkit": true
      }
    }
    

    重载 docker

    systemctl daemon-reload && systemctl reload docker
    

    如果报错提示需要安装 Buildx , 则查看 BUILDX安装 安装一下

  3. 构建镜像

    DOCKER_BUILDKIT=1 docker build --no-cache -t app:v1 .
    

使用完全体 Buildkit 构建镜像

官方文档

安装

  1. 克隆代码

    git clone https://gitee.com/offends/Kubernetes.git
    cd Kubernetes/Docker/Builder/Buildkit
    
  2. 安装 Buildkit

    这里使用 . 执行脚本否则需要手动执行 source /etc/profile

    . install.sh
    
  3. 安装 Buildx(非必选, 如果不希望安装Buildx, 则直接看文档"基础命令"部分来构建镜像)

    查看此文档: BUILDX安装

Dockerfile 写法介绍

Dockerfile # syntax = docker/dockerfile:<声明> 是必加的

官方文档

  1. # syntax=docker/dockerfile:1

    这个指令指定了 Dockerfile 使用的语法版本。在这个例子中,:1 表示使用 Dockerfile 的第一个版本。这个版本引入了基本的 Dockerfile 功能,是最基础的语法规则。它是 Dockerfile 的最低版本,提供了最基本的指令和结构,不包含较新的特性。

  2. # syntax = docker/dockerfile:experimental

    这个语法声明告诉 Docker 使用实验性特性来解析 Dockerfile。experimental 标记引入了一些实验性的功能,可能包含一些不稳定或尚未广泛测试的功能,允许使用一些较新的、可能还不是标准的 Dockerfile 特性。使用这个标记可以在 Dockerfile 中尝试新的、实验性的功能。

挂载缓存目录 cache

这里是通过存储 Docker 缓存当中实现的,咱们通过两次构建演示过程

  1. 编写 Dockerfile

    vi Dockerfile
    
    • 第一次构建

      # syntax = docker/dockerfile:1
      FROM alpine
      
      RUN --mount=type=cache,target=/data,id=file_dir,sharing=locked \
          echo "hello" >> /data/file.txt
      
    • 第二次构建

      # 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. 开始构建

    docker build -t app:v1 .
    
  3. 检查结果

    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

    vi 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. 开始构建

    docker build -t app:v1 .
    
  3. 检查结果

    docker run -it --rm app:v1 sh
    ls
    

    / 目录下存在 nginx.conf.bak 和 Docker-Template.tar.bak 则代表成功

挂载文件系统 tmpfs

将文件系统挂载到指定位置

  1. 编写 Dockerfile

    vi Dockerfile
    

    内容如下

    # syntax = docker/dockerfile:1
    FROM alpine
    
    RUN --mount=type=tmpfs,size=100m,target=/temp \
        echo "hello" > /temp/file.txt
    
  2. 开始构建

    docker build -t app:v1 .
    
  3. 检查结果

    docker run -it --rm app:v1 sh
    ls /temp
    

    没有文件则正确,因为在 RUN 执行完命令之后挂载的文件系统将会被卸载

加密内容管理

为了更好的看到效果我们拿创建目录 hello-file 举例

示例一(加密文件挂载)

官网文档

  1. 编写挂载文件

    cat > file_secret <<EOF
    hello-file
    EOF
    
  2. 编写 Dockerfile

    vi 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. 开始构建

    docker build --no-cache --secret id=file_secret,src=./file_secret -t app:v1 .
    
  4. 检验结果

    docker run -it --rm app:v1 sh
    ls
    

    看到 / 下存在 hello-file 目录,并且挂载的 file_secret 也消失了,则代表加密内容已成功传入。

示例二(加密变量传入)

官网文档

  1. 编写 Dockerfile

    vi 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. 开始构建

    env_secret=hello-file docker buildx build --no-cache --secret id=env_secret -t app:v1 --load .
    

SSH 密钥管理

官网文档

gitee 仓库举例

  1. 编写 Dockerfile

    vi 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. 开始构建

    docker build --ssh default=~/.ssh/id_rsa -t app:v1 .
    

基础命令

  1. 清理缓存

    docker builder prune
    
  2. 构建镜像并打包

    镜像不会存在于 docker images 内,用于单纯的打包最好不过了

    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