개발 블로그
← 블로그 목록

맥미니 M1에서 Docker 운영하기 — ARM 호환성 문제와 해결 방법


맥미니 M1으로 홈서버를 운영하면서 가장 자주 마주친 문제가 Docker 이미지 호환성입니다. M1은 ARM 아키텍처라 x86(amd64) 기반으로 만들어진 이미지가 그냥 실행되지 않는 경우가 있습니다. 실제로 겪은 문제들과 해결 방법을 정리합니다.

아키텍처 문제가 생기는 이유

Docker Hub에 있는 이미지 중 상당수는 linux/amd64(x86_64) 전용으로만 빌드되어 있습니다. M1/M2 맥은 linux/arm64 아키텍처입니다. Docker Desktop은 Rosetta 2 에뮬레이션으로 x86 이미지를 실행할 수 있지만, 성능 저하가 있고 일부 이미지는 에뮬레이션에서도 오작동합니다.

$ docker pull some-image
WARNING: The requested image's platform (linux/amd64) does not match
the detected host platform (linux/arm64/v8) and no specific platform
was requested

이 경고가 뜨면 에뮬레이션으로 실행되고 있다는 의미입니다.

멀티 아키텍처를 지원하는 이미지 사용

주요 공식 이미지들은 대부분 멀티 아키텍처를 지원합니다. 같은 이미지 태그라도 ARM에서 pull하면 자동으로 arm64 버전을 가져옵니다.

# 이런 이미지들은 ARM에서도 정상 동작
eclipse-temurin:17-jre       # Java 런타임
postgres:16                  # PostgreSQL
redis:7                      # Redis
nginx:alpine                 # Nginx
rabbitmq:3-management        # RabbitMQ

이미지가 멀티 아키텍처를 지원하는지 확인하려면 Docker Hub에서 해당 이미지의 Tags 탭에서 OS/ARCH 항목을 보면 됩니다. linux/arm64가 있으면 M1에서 네이티브로 실행됩니다.

amd64 전용 이미지 강제 실행

arm64 버전이 없는 이미지를 꼭 써야 할 때는 platform을 명시해서 에뮬레이션으로 실행합니다.

# docker run에서 platform 지정
docker run --platform linux/amd64 some-amd64-only-image

# docker-compose.yml에서 지정
services:
  some-service:
    image: some-amd64-only-image
    platform: linux/amd64

에뮬레이션으로 실행되므로 CPU 사용량이 올라가고 속도가 느립니다. 홈서버에서 24시간 돌리는 서비스라면 ARM 네이티브 이미지를 찾거나 직접 빌드하는 편이 낫습니다.

직접 빌드할 때 주의사항

Dockerfile로 직접 이미지를 빌드할 때 FROM에 사용하는 베이스 이미지가 arm64를 지원해야 합니다. Jenkins 컨테이너가 빌드한 WAR를 실행하는 이미지는 직접 구성했는데, eclipse-temurin 베이스 이미지가 arm64를 잘 지원해서 문제없이 사용했습니다.

# ARM에서 정상 동작하는 Dockerfile
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY app.war .
CMD ["java", "-jar", "app.war"]

Jenkins에서 빌드할 때 platform 문제

Jenkins 컨테이너 안에서 Docker 이미지를 빌드하거나 pull할 때, Jenkins 컨테이너 자체가 ARM으로 실행 중이라면 빌드된 이미지도 arm64가 됩니다. CI/CD로 배포할 때 빌드 환경과 실행 환경의 아키텍처가 일치하는지 확인이 필요합니다.

macOS 파일 시스템 볼륨 마운트 성능

아키텍처 문제는 아니지만 macOS에서 Docker를 쓸 때 또 하나의 주의사항입니다. macOS의 Docker Desktop은 Linux VM 안에서 컨테이너를 실행하기 때문에 볼륨 마운트 I/O 성능이 Linux 네이티브보다 느립니다. 로그 파일이나 업로드 파일처럼 I/O가 많은 디렉토리를 볼륨으로 마운트할 때 체감됩니다.

실제 운영 결과

맥미니 M1 16GB에서 현재 Spring Boot 서비스 4개, PostgreSQL, Redis, RabbitMQ, Nginx, Jenkins, Dozzle을 동시에 Docker 컨테이너로 운영 중입니다. 주요 이미지들이 arm64를 지원하게 되면서 에뮬레이션 없이 대부분 네이티브로 실행되고 있습니다. CPU는 평소 10% 미만, 메모리는 8~10GB 정도 사용합니다.

팁: docker inspect <container> | grep Architecture로 실행 중인 컨테이너의 아키텍처를 확인할 수 있습니다. arm64가 나오면 네이티브 실행, amd64가 나오면 에뮬레이션 중입니다.