ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 멀티 플랫폼 빌드를 위한 Docker Buildx
    Container/Docker 2022. 1. 19. 19:30
    반응형

    개요

    최근 Apple M1 기반의 맥북의 등장, AWS 그라비톤 서버군의 등장으로 ARM64 기반의 서버들을 지원하기 위한 도커 이미지 빌드가 필수로 되가고 있다. 따라서 이를 위한 방법으론 크게 2가지가 있다.

    1. docker build 서버를 프로세서 별로 1개씩 만들어둔다.
    2. docker buildx를 이용하여 멀티 플랫폼 빌드를 한다.

    첫 방법은 매우 쉽지만 프로세스가 늘수록 서버의 대수도 늘어나야 한다. CI 배포 환경을 만들었다면, 해당 잡을 담당하는 리소스(ex: Gitlab의 gitlab-runner)가 선형적으로 증가할 것이다. 두 번째 방법은 쉬운데, 리소스 증가도 없다. 간단하게 더 많은 플랫폼들을 위한 이미지를 만들어 둘 수 있다.

     

    docker buildxdocker 19 버전부터는 실험적으로 도입되더니 20 버전부터는 멀티 플랫폼 빌드를 위한 buildx가 내장되어있다. 이 문서에서는 멀티 플랫폼에 도커 이미지를 빌드하기 위한 도구 docker buildx를 다룬다. 나의 개발 환경은 다음과 같다.

    • desktop: macbook pro 13 2020 (intel cpu)
    • aws ec2 인스턴스 t2.micro 1대, t4g.nano 1대

    준비 사항

    먼저 각 머신에 docker가 설치 되어있어야 한다. 특히 맥북은 v20 이상의 도커가 필요하다. 그리고 테스트를 위한 앱이 필요하다. 먼저 적당한 디렉토리에 nodejs 기반의 앱을 만들기 위해서 다음 파일들을 준비한다.

     

    app.js

    const http = require("http");
    const os = require("os");
    
    console.log("Gurumee Server Start!");
    
    var handler = (req, res) => {
        console.log(`Received request fron ${req.connection.remoteAddress}`);
        res.writeHead(200);
        res.end(`You've hit ${os.hostname()}\n`);
    };
    
    var www = http.createServer(handler);
    www.listen(8080);

    Dockerfile

    FROM node:fermium-buster-slim
    ARG BUILDPLATFORM
    RUN echo $BUILDPLATFORM
    ADD app.js /app.js
    ENTRYPOINT ["node", "app.js"]

    시나리오 1. 일반적인 도커 이미지 빌드

    이미지 빌드

    먼저 일반적으로 도커 이미지를 빌드해보자. 필자의 맥북은 intel cpu니까 amd64 계열의 도커 이미지가 만들어질 것이다. 터미널에 다음을 입력한다.

    # 이미지 빌드
    # docker build . -t <자신의 도커 Hub ID>/buildx-test
    $ docker build . -t gurume92/buildx-test
    
    # 이미지 푸쉬
    # docker push <자신의 도커 Hub ID>/buildx-test
    $ docker push gurumee92/buildx-test

    그 다음 Docker Hub에서 자신이 푸시한 이미지를 확인해보자.

    OS/ARCH 부분에 "linux/amd64"가 적혀 있는 것을 확인할 수 있다. 이제 amd64, arm64 기반의 머신에서 각각 이미지를 다운로드하고 컨테이너를 실행시켜보자.

    AMD64 기반의 머신

    인스턴스 타입 t2.micro인 AWS 서버는 AMD64 기반의 프로세서를 사용한다. 따라서 위의 빌드한 이미지를 사용하는데 아무런 문제가 되지 않는다. 서버에 접속하여 다음을 입력해보자.

    # 아키텍처 확인
    $ arch
    # amd64는 x86_64라 나온다.
    x86_64
    
    # 도커 이미지 다운 및 실행
    # docker run --rm -d -p 8080:8080 <자신의 도커 Hub ID>/buildx-test
    $ docker run --rm -d -p 8080:8080 gurumee92/buildx-test
    Unable to find image 'gurumee92/buildx-test:latest' locally
    latest: Pulling from gurumee92/buildx-test
    72a69066d2fe: Pull complete
    24892ef5fd86: Pull complete
    dc487aa44207: Pull complete
    55e7fe023a95: Pull complete
    c0af22759c8f: Pull complete
    ee1b69d7c7cf: Pull complete
    Digest: sha256:070e42cba630eccaeed098f63eba2f96610a3e95747868168dd96b557aedd9ea
    Status: Downloaded newer image for gurumee92/buildx-test:latest
    ec230bb450fa99386eae444e1733e32fed3230c4479171a8c605ace6f9ea96b0
    
    # 컨테이너에 매핑된 8080번 포트에 HTTP 요청
    $ curl localhost:8080
    You've hit ec230bb450fa

     

    각 명령어들이 잘 실행되는 것을 확인할 수 있다.

    ARM64 기반의 머신

    인스턴스 타입 t4g.nano인 AWS 서버는 그라비톤 기반의 서버로 위의 서버들보다 같은 사양임에도 훨씬 저렴하게 쓸 수 있는 서버군이다. 이들은 모두 ARM64기반의 프로세서를 사용한다.

     

    위의 AMD64 기반의 서버처럼 도커 이미지를 설치하고 컨테이너를 실행해보자. 과연 잘 될까?

    # 아키텍처 확인
    $ arch
    # arm64는 aarch64라 나온다.
    aarch64
    
    # 도커 이미지 다운 및 실행
    $ docker run --rm -d -p 8080:8080 gurumee92/buildx-test
    Unable to find image 'gurumee92/buildx-test:latest' locally
    latest: Pulling from gurumee92/buildx-test
    72a69066d2fe: Pull complete
    24892ef5fd86: Pull complete
    dc487aa44207: Pull complete
    55e7fe023a95: Pull complete
    c0af22759c8f: Pull complete
    ee1b69d7c7cf: Pull complete
    Digest: sha256:070e42cba630eccaeed098f63eba2f96610a3e95747868168dd96b557aedd9ea
    Status: Downloaded newer image for gurumee92/buildx-test:latest
    WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
    3253ed6dc9b9b9076204185f403ee0a8a3a6a865a96e0fc1ad1213c6794486ea

     

    도커 이미지를 다운 받았지만, 머신에 알맞는 플랫폼이 없기 떄문에 실행에 실패한다.

    시나리오 2. 멀티 플랫폼을 위한 Buildx 도커 이미지 빌드

    멀티 플랫폼 빌드를 위한 준비 (맥북)

    이제 위 시나리오1의 문제를 해결하기 위해서 docker buildx를 이용한 멀티 플랫폼 빌드를 진행해보자. 먼저 빌드 플랫폼을 만들어두어야 한다. 다음을 입력한다.

    $ docker buildx create --name multiarch-builder --use
    multiarch-builder

     

    그 후, docker buildx inspect --bootstrap 명령어를 치면, 현재 buildx가 쓰는 빌더가 지원하는 플랫폼들을 확인할 수 있다.

    $ docker buildx inspect --bootstrap
    Name:   multiarch-builder
    Driver: docker-container
    
    Nodes:
    Name:      multiarch-builder0
    Endpoint:  unix:///var/run/docker.sock
    Status:    running
    Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

    이미지 빌드

    이제 nodejs 기반의 앱을 다음 명령어를 통해 빌드 및 푸쉬한다.

    $  docker buildx build \
    --push \
    --platform linux/arm64/v8,linux/amd64 \
    --tag gurumee92/buildx-test .

     

    그러면 Docker Hub에서 이미지를 확인했을 때 다음처럼 OS/ARCH 부분에 "linux/amd64" 부분이 추가된 것을 확인할 수 있다.

    멀티 플랫폼 빌드를 위한 준비 (AWS 서버들)

    이제 새롭게 빌드된 이미지를 다운받기 위해서 먼저 다음 명령어들을 입력해, 컨테이너들과 이미지를 모두 제거한다.

    # 모든 컨테이너 중지
    $ docker stop $(docker ps -aq)
    
    # 모든 컨테이너 삭제
    $ docker rm -f $(docker ps -aq)
    
    # 모든 이미지 삭제
    $ docker rmi $(docker images -a)

    AMD64 기반의 머신

    위와 같이 다음 명령어들을 실행한다. 당연히 잘 실행이 된다.

    # 아키텍처 확인
    $ arch
    # amd64는 x86_64라 나온다.
    x86_64
    
    # 도커 이미지 다운 및 실행
    # docker run --rm -d -p 8080:8080 <자신의 도커 Hub ID>/buildx-test
    $ docker run --rm -d -p 8080:8080 gurumee92/buildx-test
    Unable to find image 'gurumee92/buildx-test:latest' locally
    latest: Pulling from gurumee92/buildx-test
    72a69066d2fe: Pull complete
    24892ef5fd86: Pull complete
    dc487aa44207: Pull complete
    55e7fe023a95: Pull complete
    c0af22759c8f: Pull complete
    2acdfce94c6e: Pull complete
    Digest: sha256:f467bd8d3b5c1158db51961405eb231d6e9fbb2ef530fb1e1dc071c365c1afa8
    Status: Downloaded newer image for gurumee92/buildx-test:latest
    073b3a80ea0f11328dcf26eb02a3926b2b940e42400b5343f67f287935e63248
    
    # 컨테이너에 매핑된 8080번 포트에 HTTP 요청
    $ curl localhost:8080
    You've hit 4b3ce68eb5f3

    ARM64 기반의 머신

    역시 위와 같이 다음 명령어들을 실행한다.

    # 아키텍처 확인
    $ arch
    # amd64는 x86_64라 나온다.
    x86_64
    
    # 도커 이미지 다운 및 실행
    # docker run --rm -d -p 8080:8080 <자신의 도커 Hub ID>/buildx-test
    $ docker run --rm -d -p 8080:8080 gurumee92/buildx-test
    Unable to find image 'gurumee92/buildx-test:latest' locally
    latest: Pulling from gurumee92/buildx-test
    753408153c81: Pull complete
    171d9ed4ffc4: Pull complete
    291ed111d511: Pull complete
    3dd37e658027: Pull complete
    78c70382c62d: Pull complete
    2acdfce94c6e: Pull complete
    Digest: sha256:f467bd8d3b5c1158db51961405eb231d6e9fbb2ef530fb1e1dc071c365c1afa8
    Status: Downloaded newer image for gurumee92/buildx-test:latest
    4b3ce60fa5333ec67d756e287c57bbd596dc646259fb80f783ce23c9c5d17327
    
    # 컨테이너에 매핑된 8080번 포트에 HTTP 요청
    $ curl localhost:8080
    You've hit 4b3ce60fa533

     

    지난 시나리오와는 달리 이번엔 amd64 기반의 프로세서 위에서도 잘 실행이 된다.

    'Container > Docker' 카테고리의 다른 글

    Linux에서 Docker 설치하기 (Amazon Linux2)  (0) 2022.01.17
    Mac에서 Docker 설치하기 (Intel Chip)  (0) 2021.12.08
Designed by Tistory.