Docker Buildx 构建多系统镜像
由于开发调试编译需要,需要编译amd64
、aarch64
、arm64
等不同平台指令二进制;为了方便使用者,编译多系统
平台架构
以golang
简单demo为例:
package main
import (
"net/http"
"os"
"time"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("this is muti arch demo: GOARCH:" + os.Getenv("GOARCH")))
})
mux.Handle("/metrics", promhttp.Handler())
s := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: time.Second * 5,
WriteTimeout: time.Second * 5,
MaxHeaderBytes: 1 << 20, // 1048576; 1MiB
}
s.ListenAndServe()
}
# Builder
FROM dongjiang1989/alpine:golang-1.18.8-alpine3.15 as builder
RUN mkdir -p /go/src/server
WORKDIR /go//src/server/
COPY main.go main.go
COPY vendor/ vendor/
COPY go.sum go.sum
COPY go.mod go.mod
RUN export GOPATH=/go/src
RUN export GO111MODULE=off
RUN go build -a -ldflags "-linkmode external -extldflags -static" -o /demo-server main.go
# Server
FROM dongjiang1989/alpine:golang-1.18.8-alpine3.15
EXPOSE 8080
COPY --from=builder /demo-server /demo-server
ENTRYPOINT ["/demo-server"]
多平台架构需要使用docker buildx version
查看docker是否支持多架构编译:
dongjiang@MacBook Pro:buildx $ docker buildx create --use --name muti-builder --driver docker-container --buildkitd-flags --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
muti-builder
dongjiang@MacBook Pro:buildx $ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
muti-builder * docker-container
muti-builder0 desktop-linux inactive
default docker
default default running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux docker
desktop-linux desktop-linux running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
编译多架构镜像
dongjiang@MacBook Pro:buildx $ docker buildx build -t dongjiang1989/muti-arch-demo-server:latest --platform=linux/arm64,linux/amd64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6 .
[+] Building 0.7s (10/10) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 540B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CANCELED [linux/arm/v6 internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/ppc64le internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/arm64 internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/riscv64 internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/s390x internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/arm/v7 internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/amd64 internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15 0.7s
=> CANCELED [linux/386 internal] load metadata for docker.io/dongjiang1989/alpine:golang-1.18.8-alpine3.15
......
check多架构镜像
dongjiang@MacBook Pro:muti-arch $ docker manifest inspect dongjiang1989/muti-arch-demo-server:latest
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:786d66907396720dc98cf332f9d59dc423c0a28791e1f63d4f002f7ebb73bb4c",
"platform": {
"architecture": "386",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:2e97c5212297685386fa22b8155b75f4ac2f758705c253cbe6707a48a8011497",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:e41b2fad89dc900ef10376a82ab4fd70a0a739a04d57d96b2589f938eca99b83",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v6"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:e8d64dfa17f80eb3cc7bf4ccc648c0136e40b507272de1151fcfc13534cddaa8",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:394e182faddaa3b168f9e976f88900623c51e561d808d951e32a08e037acf591",
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:d2e537ab91efb65344017ec40142cc09aa2b615ee0ef11aa5d6a9bf897861430",
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1679,
"digest": "sha256:c1f25a3aa9744f8a00f533c736abad0d23eff5d32908b426b37387829f4122e0",
"platform": {
"architecture": "s390x",
"os": "linux"
}
}
]
}
总结
- docker 需要 使用dockerx编译
- 编译平台需要支持qemu切换gcc
- 基础镜像也需要支持多架构
- Dockerfile编译指令中,不能写死
GOARCH
、GOOS
- 业务代码中,需要支持多架构代码;比如
syscall
,os
调用等