문제 상황
개발환경에서 DockerHub에 Docker 이미지를 푸시하고, 배포서버에서 pull해서 사용하려고 하자 실행시WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
와 같은 에러가 발생했다.
이는 개발환경은 WSl2 Ubuntu (linux/amd64) 이고, 배포 서버는 linux/arm64 아키텍처이기 때문이다.
따라서 로컬에서 docker image를 빌드 시, 해당 아키텍처용 이미지를 만들어주어야 한다.
이를 위해선 docker buildx가 필요한데, buildx란 다양한 아키텍처에서 컨테이너 이미지를 빌드하고 관리하는 도구이다.
Buildx를 사용하기 위해서는 Docker 엔진 19.03 이상이 필요하다.
buildx를 사용한 빌드
애뮬레이터 설치
멀티 플랫폼 빌드를 위해 tonistiigi/binfmt를 실행한다. 이를 통해 Docker 이미지 안에서 다양한 애뮬레이터 환경이 구성된다.
docker run --privileged --rm tonistiigi/binfmt --install all
빌드 컨텍스트 설정
다음 명령어로 기본 빌드 컨텍스트로 buildx를 사용하도록 한다.
docker buildx create --name multi-arch-builder --bootstrap --use
bootstrap
: 빌더 생성이 끝나면 자동 초기화 합니다.use
: 새로 생성한 빌더를 사용하도록 자동 설정 합니다.
정상적으로 생성되었다.
이미지 빌드
다음과 같이 image를 빌드해준다.
linux/arm64/v8,linux/amd64 자리에는 원하는 플랫폼들을 ,구분자로 나열해주면 된다.
docker buildx build --platform linux/arm64/v8,linux/amd64 -t {dockerhub username}/{project명}:{tag} {projectPath}
빌드한 이미지가 보이지 않을 때
그러나 위와 같이 빌드 시, 빌드한 이미지가 이미지 목록에 나타나지 않는 문제상황을 겪었다.
그 이유는 빌드된 플랫폼별 이미지는 캐싱되어 있기 때문이다. 이 이미지를 어디로 내보낼지 설정해야 한다.
--push
옵션으로 멀티 플랫폼 이미지를 빌드함과 동시에, 컨테이너 레지스트리(Docker Hub, ECR,GCR 등)에 push 할 수 있다.
이때, -t 옵션에 올바른 컨테이너 레지스트리 URI를 사용해야하고, docker login
으로 로그인 되어 있어야 한다.
docker buildx build --platform linux/arm64/v8,linux/amd64 -t eogns47/linkcrawler:ServerCrawler --push .
--load
옵션을 사용하면 buildx 없이 빌드할 때 처럼 로컬에 저장이 가능하고, docker images로 확인 가능하다.
그러나 멀티 플랫폼 옵션과 함께 로컬에 저장하려고 하면, 다음과 같은 에러가 발생한다.
ERROR: docker exporter does not currently support exporting manifest lists
아마 다른 아키텍쳐의 이미지를 받으려고 해서 그런 것 같은데, dockerhub같은 레지스트리에 업로드 하고, 다운받는 방법을 사용하자.
생성된 이미지 확인
docker hub에서 이미지가 아키텍처별로 잘 생성되고, push되었는지 확인해보자.
옵션으로 준 arm64와 amd64 모두 정상적으로 push 된 모습!
이제 이 이미지를 pull 받으면, pull 받은 환경의 OS에 맞는 버전으로 이미지를 가져온다.
reference