---
title: "构建多架构Docker镜像并分开推送到Dockerhub"
url: "https://lerry.me/post/2024/08/build-multi-arch-docker-images-and-push-separately-to-dockerhub"
date: 2024-08-09T15:57:00.000Z
updated: 2026-09-09T09:18:40.307Z
tags:
  - "Docker"
language: zh-CN
---

# 构建多架构Docker镜像并分开推送到Dockerhub

### 前提

我平时使用的PostgreSQL和Caddy的Docker镜像都是自己构建的，因为会用到一些额外的插件。  我使用的服务器多数是x86架构，也有一些是ARM架构的，所以需要构建多架构的镜像，如果直接分开构建、push，Dockerhub上只会保留最后一次的push，使用错误的架构，程序是无法启动的。

### 调查

其实Docker支持使用`docker buildx build --platform=linux/arm64,linux/amd64`的方式同时构建多架构镜像，但是异构镜像是使用qemu这样的虚拟机技术实现的，效率可想而知，特别是在性能有限的vps上，构建很慢，而且有时候还会报错。

最好的办法是分开构建，在ARM机器和x86机器上分开构建，这样效率最高。

经过研究发现Docker提供了[docker manifest](https://docs.docker.com/reference/cli/docker/manifest/) 这个命令用于解决这个问题。

### 使用

使用很简单，分开构建并推送，然后创建manifest并推送，如果你原来的镜像是`lerrybin/pg16:latest`，那么，  
1. 在x86机器上构建一个名为`lerrybin/pg16-amd64:latest`的镜像并推送到Dockerhub，镜像名称相比原来的名称多了一个架构后缀用于区分。  
2. 在ARM机器上构建一个名为`lerrybin/pg16-arm64:latest`的镜像，同样推送到Dockerhub。  
3. 创建manifest `docker manifest create lerrybin/pg16:latest lerrybin/pg16-amd64:latest lerrybin/pg16-arm64:latest`   
4. push manifest `docker manifest push lerrybin/pg16:latest`  

此时拉取镜像就会自动获取相应架构的镜像，需要注意的是，推送manifest之前要确保对应的镜像已经推送到Dockerhub，不然会报错。


### Makefile分享

另外附上我在用的一个Makefile，以供参考

```makefile
REPOSITORY := lerrybin
NAME := caddy-with-cloudflare
TAG := latest
CURRENT_ARCH := $(shell uname -m)


ifeq ($(CURRENT_ARCH),x86_64)
    BUILD_PLATFORM := linux/amd64
	SUFFIX := amd64
else
    BUILD_PLATFORM := linux/arm64
	SUFFIX := arm64
endif


# Pull the base caddy image
update:
	@echo "Pulling the base caddy image..."
	@docker pull caddy:2-builder

# Build the Docker image
build: update
	@echo "Building the $(NAME) image..."
	@docker build --platform=$(BUILD_PLATFORM) -t $(REPOSITORY)/$(NAME)-${SUFFIX}:$(TAG) . --push
	@docker manifest create -a $(REPOSITORY)/$(NAME):$(TAG) $(REPOSITORY)/$(NAME)-amd64:$(TAG) $(REPOSITORY)/$(NAME)-arm64:$(TAG)
	@docker manifest push $(REPOSITORY)/$(NAME):$(TAG)

all: update build

.PHONY: update build
.DEFAULT_GOAL := all
```

使用过程中遇到问题，可以查看文档 [https://docs.docker.com/reference/cli/docker/manifest/#manifest-create](https://docs.docker.com/reference/cli/docker/manifest/#manifest-create)
