一、前言
1、本文主要内容
使用Docker Buildx构建支持AMD64、ARM、ARM64等架构的镜像并传到到Docker Hub
2、本文环境信息
环境 | 说明 |
---|---|
Docker | Docker CE 23.0.5 |
Docker Desktop | 4.19 |
Docker Buildx | 0.10.4 |
Docker Golang镜像 | 1.20 |
Golang | 1.20 |
Windows | Windows 11 |
curl for Windows | 7.87 |
3、前置知识
Docker入门:使用Dockerfile构建Docker镜像
https://ken.io/note/docker-image-build-with-dockerfile
二、镜像制作准备
创建镜像制作根目录,例如:d:\docker\helloworld(Windows),~/docker/helloworld(macOS),后续所有文件都放在该目录中
1、准备应用代码
用golang写的一个简单http server,监听8000端口,默认输出helloworld,并返回操作系统、HostName以及IP地址信息
新建helloworld.go保存以下代码
package main
import (
"fmt"
"log"
"net"
"net/http"
"os"
"runtime"
"strings"
)
func getHostName() string {
hostname, err := os.Hostname()
if err != nil {
log.Fatalf("Failed to open log file: %v", err)
}
return hostname
}
func getIpAddresses() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
log.Fatal(err)
return ""
}
var ips []string
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
ips = append(ips, ipnet.IP.String())
}
}
}
return strings.Join(ips, ",")
}
func handler(w http.ResponseWriter, r *http.Request) {
log.Println("received request from", r.RemoteAddr, r.URL.Path[1:])
var welcome = r.URL.Path[1:]
if len(welcome) == 0 {
welcome = "World"
}
fmt.Fprintf(w, "Hello, %s! ---ken.io \r\n", welcome)
fmt.Fprintf(w, "OS:%s/%s,Host:%s,IP:%s\r\n", runtime.GOOS, runtime.GOARCH, getHostName(), getIpAddresses())
}
func main() {
http.HandleFunc("/", handler)
log.Println("starting server on port 8000")
log.Fatal(http.ListenAndServe(":8000", nil))
}
2、编写Dockerfile文件
Dockerfile 是用于Docker镜像的文本文件(默认无后缀名),包含所有我们需要用于创建Docker镜像的命令,例如:指定基础镜像、安装依赖的软件、配置环境变量、添加文件和目录、定义容器启动时运行的命令等
新建helloworld.build并保存以下内容
# 使用官方提供的 Go 镜像作为基础镜像
FROM golang:1.20
# 将工作目录设置为 /app
WORKDIR /app
# 将helloworld.go复制到 /app 下
COPY helloworld.go /app
# 设置go mod 镜像
RUN go env -w GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct
# 导入依赖的Redis go module
RUN go mod init helloworld
# 允许宿主机访问容器的 8000 端口
EXPOSE 8000
# 设置容器进程为:go run helloworld.go
CMD go run helloworld.go
三、镜像制作
1、确认BaseImage支持架构
以Golang的官方镜像镜像为例,我们可以在找到指定版本,查看支持的系统架构
2、登录账号
访问 https://hub.docker.com/signup 注册账号,然后在Docker Desktop登录账号,或者通过命令登录
# 登录命令
docker login
# 根据命令号交互输入注册时的账号密码即可成功登录
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: kentalk
Password:
Login Succeeded
Logging in with your password grants your terminal complete access to your account.
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
3、构建镜像
Docker从19.03版本提供了构建工具Buildx,可以通过—platform参数指定构建的目标平台,例如:linux/amd64、linux/arm64或、darwin/amd64等等,通过Buildx可以连接面向不同架构的Docker节点分别构建,也可以直接将构建信息推送到Docker Hub,这里选择后者,毕竟不需要准备面向不同架构的Docker节点,更省事儿
# 进入目录
d: && cd d:\docker\helloworld
# 查看Buildx版本(确认buildx已启用,如未启用,使用docker buildx install安装)
docker buildx version
# 构建镜像(默认为latest)(注意结尾一定要加.)
# 这里选择构建常见的linux/amd64,linux/arm64 架构,如需其他的可以自行追加
docker buildx build \
--platform linux/amd64,linux/arm64 \
-f helloworld.build \
-t kentalk/helloworld --push .
4、查看构建结果
访问 https://hub.docker.com/r/kentalk/helloworld/tags 查看构建的结果
5、镜像测试
# 拉取镜像
docker pull kentalk/helloworld
# 启动容器
docker run --name myhello -p 8000:8000 -d kentalk/helloworld
# 访问测试
curl localhost:8000
# 输出示例
Hello, World! ---ken.io
OS:linux/arm64,Host:3426a278c72e,IP:172.17.0.3
6、查看镜像信息
docker buildx imagetools inspect kentalk/helloworld
# 输出示例
*****************省略部分内容******************
Manifests:
Name: docker.io/kentalk/helloworld:latest@sha256:e84a3c9b0ebfa61af984594dedfbaaba092fa592e0e881f62fe7999f17e44b53
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/amd64
Name: docker.io/kentalk/helloworld:latest@sha256:df49a99b6f5ddbcd5e79826c5cd1086cb5edff4601be35c8f4358616f0e2d749
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/arm64
*****************省略部分内容******************