以一打十 - 使用 docker buildx 实现多平台编译

uyinn 2020-11-07 16:43:49
linux github optional Bash alpine linux


使用 docker buildx 实现多平台编译

docker registry api v2 支持多 CPU 架构镜像.

同时 harbor v2 也实现了 docker registry api v2 的支持.

0x01 准备

  • docker 开启实验模式
  • buildx 插件
  • qemu 模拟器
  • Linux kernel >= 4.8

linux 系统内核

由于 binfmt_misc 机制开启需要依赖 Linux kernel >= 4.8 。 因此,在对 linux 系统操作选型上有一定要求。

建议使用 发行版 出场内核已经满足需求的操作系统。 而不是选择自己升级系统内核。

  • ubuntu:18.04 LTS 及以上
  • debian:10 及以上

参考文章:

开启实验模式

当前 buildx 还是一个实验模式, 如需要支持, 需要进行如下配置

  1. 开启实验模式。 修改 /etc/docker/daemon.json, 增加 experimental 字段, 如下。
# vi /etc/docker/daemon.json
{
"experimental": true
}

安装 buildx

  1. buildx 放到 ~/.docker/cli-plugins/ 目录下
# https://github.com/docker/buildx/blob/master/README.md#docker-ce
BUILDX_VERSION=v0.4.1
ARCH=$(uname -m)
[ "${ARCH}" == "x86_64" ] && ARCH=amd64
[ "${ARCH}" == "aarch64" ] && ARCH=arm64
mkdir -p ~/.docker/cli-plugins
wget -c https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-${ARCH} -O docker-buildx\
&& chmod +x docker-buildx \
&& mv docker-buildx ~/.docker/cli-plugins/

安装 qemu

下载并安装 qumu/usr/bin/qemu-$(uname -m)-static

# https://github.com/multiarch/qemu-user-static#multiarchqemu-user-static-images
QEMU_VERSION=v5.0.0-2
wget -c https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-$(uname -m)-static -O qemu-$(uname -m)-static \
&& chmod +x qemu-$(uname -m)-static \
&& mv qemu-$(uname -m)-static /usr/local/bin/qemu-$(uname -m)-static

0x02 example

创建 buildx builder


## 1. 创建指定名称及指定平台的builder
docker buildx create --use --platform=linux/amd64,linux/arm64 --name localbuilder

### 创建随机名称的 默认参数 builder
# docker buildx create --use

创建 Dockerfile 和 bakefile

目录结构如下


# tree
# .
# ├── alpine-bake
# │ └── alpine.Dockerfile
# └── bake.hcl
  • alpine-bake/alpine.Dockerfile
FROM alpine:3.12
ARG TARGETARCH
RUN echo "TARGETARCH is $TARGETARCH"
  • docker-bake.hcl
group "default" {
targets = ["alpine"]
}
target "alpine" {
context = "./alpine-bake"
dockerfile = "alpine.Dockerfile"
tags = ["docker.io/tangx/alpine:buildx-bake-hcl"]
platforms = ["linux/amd64", "linux/arm64", "linux/arm/v6", "linux/arm/v7", "linux/s390x"]
## push to registry
output = ["type=registry"]
## pull base image always
pull = true
}
target "debian" {
context = "./debian-bake"
## default: Dockerfile
# dockerfile = "Dockerfile" 
tags = ["docker.io/tangx/debian:buildx-bake-hcl"]
platforms = ["linux/amd64", "linux/arm64", "linux/arm/v6", "linux/arm/v7", "linux/s390x"]
## push to registry
output = ["type=registry"]
## pull base image always
pull = true
}

使用 bake 执行编译

docker buildx bake -f bake.hcl # -f alias to bake

当命令中省略 -f 参数时, 默认 bake 文件为:

  • docker-bake.json
  • docker-bake.hcl
  • docker-compose.yaml

执行结果

可以在 tangx/alpine:buildx-bake-hcl 看到,生成的镜像, 支持了 5个 cpu 架构。

buildx-bake-demo

  • 执行过程
# docker buildx bake -f bake.hcl
[+] Building 46.9s (19/19) FINISHED
=> [internal] booting buildkit 3.3s
=> [internal] load build definition from alpine.Dockerfile 0.1s
=> [internal] load .dockerignore 0.1s
=> [linux/arm/v6 internal] load metadata for docker.io/library/alpine:3.12 13.1s
=> [linux/arm64 internal] load metadata for docker.io/library/alpine:3.12 10.4s
=> [linux/amd64 internal] load metadata for docker.io/library/alpine:3.12 13.1s
=> [linux/s390x internal] load metadata for docker.io/library/alpine:3.12 13.1s
=> [linux/arm/v7 internal] load metadata for docker.io/library/alpine:3.12 13.1s
=> [linux/amd64 1/2] FROM docker.io/library/alpine:3.12@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a 6.1s
=> [linux/arm/v7 1/2] FROM docker.io/library/alpine:3.12@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a 5.9s
=> [linux/arm/v6 1/2] FROM docker.io/library/alpine:3.12@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a 6.0s
=> [linux/arm64 1/2] FROM docker.io/library/alpine:3.12@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a 6.1s
=> [linux/s390x 1/2] FROM docker.io/library/alpine:3.12@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a 6.3s
=> [linux/arm/v7 2/2] RUN echo "TARGETARCH is arm" 0.9s
=> [linux/arm/v6 2/2] RUN echo "TARGETARCH is arm" 0.8s
=> [linux/amd64 2/2] RUN echo "TARGETARCH is amd64" 0.7s
=> [linux/arm64 2/2] RUN echo "TARGETARCH is arm64" 0.5s
=> [linux/s390x 2/2] RUN echo "TARGETARCH is s390x" 0.4s
=> exporting to image 22.9s

使用命令行执行编译

# docker buildx build --platform=linux/amd64,linux/arm64 --file alpine-bake/alpine.Dockerfile --tag tangx/alpine:multi-arch --push alpine-bake/

参数解释

  • docker buildx build : 主命令及子命令
  • --platform=linux/amd64,linux/arm64 : 执行 cpu 架构
  • --file : 指定 Dockerfile 的文件及路径。 省略则表示当前目录下的 Dockerfile
  • --tag : 镜像名字及TAG
  • --push : 完成并推送到仓库
  • alpine-bake : docker context 的目录地址。

执行结果

相关文档

  1. buildx
  2. buildx bake
  3. docker

buildx hcl 支持的变量值

type Target struct {
Name string `json:"-" hcl:"name,label"`
// Inherits is the only field that cannot be overridden with --set
Inherits []string `json:"inherits,omitempty" hcl:"inherits,optional"`
Context *string `json:"context,omitempty" hcl:"context,optional"`
Dockerfile *string `json:"dockerfile,omitempty" hcl:"dockerfile,optional"`
Args map[string]string `json:"args,omitempty" hcl:"args,optional"`
Labels map[string]string `json:"labels,omitempty" hcl:"labels,optional"`
Tags []string `json:"tags,omitempty" hcl:"tags,optional"`
CacheFrom []string `json:"cache-from,omitempty" hcl:"cache-from,optional"`
CacheTo []string `json:"cache-to,omitempty" hcl:"cache-to,optional"`
Target *string `json:"target,omitempty" hcl:"target,optional"`
Secrets []string `json:"secret,omitempty" hcl:"secret,optional"`
SSH []string `json:"ssh,omitempty" hcl:"ssh,optional"`
Platforms []string `json:"platforms,omitempty" hcl:"platforms,optional"`
Outputs []string `json:"output,omitempty" hcl:"output,optional"`
Pull *bool `json:"pull,omitempty" hcl:"pull,optional"`
NoCache *bool `json:"no-cache,omitempty" hcl:"no-cache,optional"`
// IMPORTANT: if you add more fields here, do not forget to update newOverrides and README.
}

在 github action 上使用 buildx

https://github.com/marketplace/actions/customizable-docker-buildx

troubleshoot

  1. multiple platforms feature is currently not supported for docker driver

当前模式不支持 buildx : https://github.com/docker/cli/blob/master/experimental/README.md

# 开始实验模式 
# ~/docker/daemon.json
{
"experimental": true
}
# docker version -f '{{.Server.Experimental}}'
## true
  1. auto-push is currently not implemented for docker driver

缺少 builder

# 创建一个 builder 
docker buildx create --use # a random name
docker buildx create --user --name specified_name # specified name
  1. failed to solve: rpc error: code = Unknown desc = failed to load LLB: runtime execution on platform linux/arm64 not supported

参考 qemu-user-static #getting-started 执行以下命令。 如果正常返回,则表示成功

$ uname -m
x86_64
$ docker run --rm -t arm64v8/ubuntu uname -m
standard_init_linux.go:211: exec user process caused "exec format error"
$ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
$ docker run --rm -t arm64v8/ubuntu uname -m
aarch64

本文原载于笔者个人博客 https://tangx.in

如果觉得本文对你有帮助, 可以关注笔者微信公众号

mp-weixin


请笔者一杯咖啡

weixin-pay alipay

版权声明
本文为[uyinn]所创,转载请带上原文链接,感谢
https://my.oschina.net/uyinn/blog/4706948

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云