TechFeedTechFeed
Cloud & DevOps

exec format error, 도커 플랫폼, arm64 | 맥에서 만든 이미지가 서버에서만 죽으면?

exec format error는 이미지 CPU와 서버 CPU가 다를 때 납니다. inspect와 uname을 대조하고 linux/amd64로 다시 굽거나 두 플랫폼을 한 태그로 푸시합니다. 소켓 권한 거절과 포트 점유와 문장을 가릅니다. 맥에서 구운 arm64를 서울 리전 리눅스에 올리는 흐름을 포함합니다. Docker, 배포, 한국 맥 개발. 2026년 9월 도커 문서.

by

exec format error는 도커파일 문법이 틀려서가 아니라, 이미지 CPU가 서버 CPU와 달라 커널이 실행을 거절한 줄입니다. 맥에서 구운 이미지를 올리기 전에 이미지 아키텍처와 uname -m을 나란히 보세요.


로컬 실행은 조용한데 우분투 가상머신에서만 엔트리포인트가 죽으면 이 칸일 가능성이 큽니다. 애플 실리콘은 보통 arm64로 굽고, 많은 클라우드 가상머신은 x86_64입니다.


소켓 권한 거절은 데몬에 붙기 전에 납니다. 이번 문장은 컨테이너가 시작된 뒤 첫 프로세스에서 납니다. 서버 플랫폼으로 다시 굽거나, 두 플랫폼을 한 태그로 푸시하면 됩니다.


문법이 아니라 CPU가 다르다

이미지 문법은 맞는데, 기계어만 다른 서버입니다.


컨테이너는 호스트 커널을 나눠 씁니다. 도커 멀티 플랫폼 문서는 그래서 linux/amd64 이미지를 arm64 호스트에서 에뮬레이션 없이 돌릴 수 없고, 윈도우 컨테이너를 리눅스 호스트에서 돌릴 수 없다고 적습니다. 커널이 파일 앞머리를 읽다가 자신의 명령 집합이 아니면 exec format error로 멈춥니다. Dockerfile의 FROM 철자와는 별개입니다.


도커 데스크톱은 빌드한 머신의 플랫폼을 기본값으로 씁니다. 한국에서 맥북으로 개발하고 클라우드 리눅스는 x86_64인 1인 개발자 조합에서, 로컬 실행은 arm64라 초록이고 서버 풀만 빨간 장면이 반복됩니다. 베이스 이미지를 다른 플랫폼으로 고정한 FROM --platform도 같은 결과를 냅니다.


데이터센터 서버 랙 통로. 빌드한 CPU와 실행 서버 CPU가 달라 컨테이너가 죽는 상황의 배경
이미지가 구워진 CPU와 서버 CPU가 다르면 엔트리포인트가 exec format error로 멈춘다

이미지와 호스트를 한 줄로 대조

두 글자가 다르면 더 이상 로그를 파지 않아도 됩니다.


확인할 곳명령읽는 값
이미지docker image inspect --formatlinux/amd64 또는 linux/arm64
서버uname -mx86_64면 amd64, aarch64면 arm64
데몬docker version --formatServer.Arch
레지스트리 태그docker buildx imagetools inspect매니페스트에 있는 플랫폼 목록

x86_64 서버에 arm64 이미지가 올라가 있으면 원인이 끝난 것입니다. 멀티 아키텍처 태그라면 목록에 서버 플랫폼이 있는지도 봅니다. 없으면 그 태그는 그 서버용으로 구워진 적이 없습니다.


이미지 아키텍처와 서버 기계 확인
docker image inspect myapp:latest --format '{{.Os}}/{{.Architecture}}' uname -m docker version --format '{{.Server.Arch}}'

서버 플랫폼으로 다시 굽기

실행할 서버가 하나면, 그 플랫폼만 지정해 다시 굽습니다.


일반적인 클라우드 가상머신과 깃허브 호스티드 우분투 러너는 x86_64인 경우가 많습니다. 그때는 docker buildx build --platform linux/amd64로 대상을 고정합니다. 로컬 도커에 올려 바로 실행해 보려면 단일 플랫폼에 --load를 붙입니다. 서버로 보낼 거면 레지스트리에 푸시한 뒤 서버에서 그 다이제스트를 다시 인스펙트합니다. 푸시 없이 로컬 이미지만 갱신하면 서버는 어제 자 arm64를 계속 받습니다.


이미 레지스트리에 맞는 플랫폼이 있으면 서버에서 docker pull --platform linux/amd64로 그 변형만 받을 수 있습니다. 태그가 단일 플랫폼으로만 푸시됐다면 풀 플래그만으로는 다른 기계어가 생기지 않습니다. 다시 구워야 합니다.


amd64 한 장으로 구워 로컬에 올리기
docker buildx build --platform linux/amd64 -t myapp:latest --load . docker image inspect myapp:latest --format '{{.Os}}/{{.Architecture}}'

두 플랫폼을 한 태그에

맥과 서버를 한 태그로 쓰려면 매니페스트 목록이 필요합니다.


도커 문서는 docker buildx build --platform linux/amd64,linux/arm64로 한 번에 여러 대상을 굽는다고 적습니다. 결과물은 단일 매니페스트가 아니라 매니페스트 목록입니다. 받을 때 데몬이 호스트에 맞는 변형을 고릅니다. 라즈베리 파이 같은 arm64는 arm64 레이어를, x86-64 노트북은 amd64 레이어를 받습니다.


도커 데스크톱과 엔진 29의 containerd 이미지 스토어는 이 목록을 기본으로 담을 수 있다고 문서는 설명합니다. 옛 스토리지 드라이버는 docker buildx create --name container-builder --driver docker-container --bootstrap --use처럼 컨테이너 드라이버 빌더를 따로 만듭니다. 그 드라이버의 결과물은 로컬 엔진 스토어에 자동으로 실리지 않고, docker build --push로 레지스트리에 바로 보냅니다. QEMU 에뮬레이션은 컴파일처럼 무거운 단계에서 느립니다. 가능하면 언어의 크로스 컴파일(BUILDPLATFORM, TARGETARCH)이나 네이티브 노드를 씁니다.


두 플랫폼을 레지스트리 한 태그로
docker buildx build \ --platform linux/amd64,linux/arm64 \ -t myorg/myapp:latest \ --push .
노트북이 닫힌 작업 책상과 모니터. 로컬 빌드와 서버 배포의 CPU를 나누는 장면
로컬에서 초록이어도 푸시된 매니페스트에 서버 플랫폼이 없으면 배포는 죽는다

아키텍처가 같은데 같은 문장이면

CPU가 이미 같으면 엔트리포인트 파일의 첫 줄을 봅니다.


셸 스크립트 첫 줄이 #!/bin/sh가 아니거나, 윈도우 줄바꿈 CRLF가 붙어 인터프리터 이름이 sh 더하기 캐리지 리턴으로 읽히면 커널이 같은 형식 오류를 냅니다. 아키텍처 대조가 일치한 뒤에만 이 갈래로 오세요. file entrypoint.sh에 CRLF가 보이면 저장소의 셸 스크립트를 LF로 맞추고 다시 굽습니다. 베이스 이미지의 바이너리가 깨진 경우도 같은 문장으로 끝나니, 공식 태그를 다른 다이제스트로 한 번 더 받는 확인이 뒤따릅니다.


소켓 권한 거절은 데몬 그룹 문제라 컨테이너 로그까지 오지 않습니다. 포트 점유는 주소가 이미 쓰여 바인드 단계에서 멈춥니다. 이번 문장은 프로세스를 실행하는 순간에만 나옵니다.


한국에서 맥으로 이미지를 만들고 서울 리전의 리눅스에 올리는 흐름이면, 배포 스크립트에 플랫폼을 적는 한 줄이 재발 방지입니다. 사람이 노트북에서 구운 태그를 그대로 서버 풀로 보내지 말고, 러너가 서버와 같은 기계로 굽게 하세요. 같은 태그 문자열이라도 어제 자 다이제스트가 남아 있으면 새 빌드가 도착한 것이 아닙니다. 서버에서 아키텍처를 한 번 읽고 롤백 기준을 그 다이제스트로 남기면, 다음 장애 때 형식 오류와 앱 오류를 섞지 않아도 됩니다. 빌드 로그의 플랫폼 한 줄을 배포 노트에 같이 적어두면 나중에 같은 태그를 다시 밀 때 헷갈리지 않습니다.


로컬 초록을 배포 완료로 보지 않기 | 맥에서 docker run이 떠도 그 이미지는 arm64일 수 있습니다. 서버에서 inspect로 amd64가 보이기 전에는 끝난 배포가 아닙니다.


참고 자료


내부 연계: docker.sock 권한, 포트 점유, 열린 파일 한도


플래그 설명은 2026년 9월 도커 문서 기준입니다.


자주 묻는 질문

맥에서는 되는데 서버만 죽어요.

로컬 uname이 aarch64이고 서버가 x86_64이면 이번 칸입니다. 서버에서 이미지 아키텍처를 읽고, linux/amd64로 다시 구워 그 다이제스트를 배포하세요. 로컬 재시작만으로는 서버 레이어가 안 바뀝니다.


--platform을 줬는데도 서버가 arm64를 받아요.

빌드는 바뀌었는데 푸시가 빠졌거나, 서버가 예전 태그를 캐시했을 수 있습니다. 푸시 로그의 다이제스트와 서버 inspect 다이제스트를 비교하세요. 같기 전에는 새 플랫폼이 도착한 것이 아닙니다.


두 플랫폼 빌드가 로컬에 안 올라와요.

컨테이너 드라이버 빌더는 결과를 로컬 엔진에 자동으로 넣지 않습니다. 레지스트리로 --push 하거나, 시험은 플랫폼 하나만 --load 하세요. 데스크톱과 엔진 29의 containerd 스토어는 목록을 담을 수 있다고 도커가 안내합니다.


permission denied랑 같은 건가요?

다릅니다. docker.sock 권한은 데몬 소켓의 그룹 문제이고, 컨테이너 프로세스가 시작되기 전입니다. exec format error는 이미지 안 첫 프로그램을 실행할 때 납니다.


아키텍처는 같은데 같은 문장이에요.

엔트리포인트 셔뱅과 줄바꿈을 확인하세요. CRLF가 붙은 셸은 인터프리터 이름이 어긋나 같은 오류를 냅니다. 베이스 이미지 다이제스트를 한 번 바꿔 받는 확인도 같이 하세요.


QEMU로 서버에서 arm64를 억지로 돌리면요?

도커 데스크톱은 에뮬레이션을 기본으로 갖고, 리눅스 엔진은 binfmt 등록이 필요할 수 있습니다. 운영 서버의 상시 에뮬레이션은 느리고 장애 면도 넓습니다. 그 서버의 네이티브 플랫폼으로 굽는 쪽이 짧습니다.


이 오류는 이미지 CPU와 서버 CPU가 다를 때 먼저 의심하면 됩니다. inspect와 uname이 어긋나면 그 플랫폼으로 다시 구워 푸시하세요. 관련 글: 소켓 권한, 포트 점유, 파일 한도.


exec format error도커arm64amd64buildx플랫폼배포맥클라우드개발자

함께 보면 좋은 문제 해결

EXPLORE / Cloud & DevOps

이어서 읽어보기

전체 토픽 둘러보기 →