Golang 도커 멀티플랫폼 빠르게 빌드하기
🚀

Golang 도커 멀티플랫폼 빠르게 빌드하기

배경

Apple M1 맥북, AWS Gravition의 등장으로 arm64 플랫폼과 amd64 플랫폼을 함께 지원하는 컨테이너 이미지 빌드의 필요성이 커지고 있습니다. Docker Buildx를 활용하면 쉽게 이런 멀티플랫폼 이미지를 만들 수 있지만 buildx의 작동 방식이 빌드를 수행하는 머신과 다른 플랫폼의 경우 QEMU를 이용하기 때문에 속도가 느립니다.

해결

golang은 자체적으로 다양한 OS, 아키텍쳐를 모두 빠르게 크로스 컴파일 할 수 있는 특장점이 있습니다. 이 특징을 이용하면 빠른 멀티플랫폼 컨테이너 이미지 빌드가 가능합니다. 각 플랫폼 별로 Dockerfile 내에서 느리게 빌드를 수행하는 것이 아닌, golang으로 플랫폼 별로 빠르게 만든 실행파일을 복사하는 것으로 대체합니다.

느린 멀티플랫폼 이미지 빌드 예

Dockerfile
FROM golang:1.16 as builder COPY . . RUN go mod download RUN CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags="-w -s" FROM gcr.io/distroless/base COPY --from=builder /go/bin /app ENTRYPOINT ["/app/apigateway"]
Shell
$ docker buildx build --platform linux/amd64,linux/arm64 .

빠른 멀티플랫폼 이미지 빌드 예

Makefile
GOPATH:=$(shell go env GOPATH) APP?=apigateway .PHONY: build build: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -ldflags="-w -s" -o bin/${APP}.linux.amd64 cmd/main.go CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -a -installsuffix cgo -ldflags="-w -s" -o bin/${APP}.linux.arm64 cmd/main.go CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags="-w -s" -o bin/${APP} cmd/main.go
Dockerfile
FROM golang:1.16 as build WORKDIR /apigateway/bin COPY ./bin ./ RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then mv apigateway.linux.amd64 apigateway; fi RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then mv apigateway.linux.arm64 apigateway; fi FROM --platform=$TARGETPLATFORM gcr.io/distroless/base COPY --from=build /apigateway/bin/apigateway /app/apigateway EXPOSE 8080 ENTRYPOINT ["app/apigateway"]
Shell
$ docker buildx build --platform linux/amd64,linux/arm64 .
Repository
 

Links

amd64 머신에서 arm64 빌드시 10배 이상 느린 케이스
golang이 지원하는 플랫폼 목록