---
title: "ARM Docker에서 x86 에뮬레이션 — 설정이 똑같은데 왜 하나만 되는 거야"
published: 2026-02-11T23:10:02.000Z
canonical: https://jeff.news/article/685
---
# ARM Docker에서 x86 에뮬레이션 — 설정이 똑같은데 왜 하나만 되는 거야

ARM에서 Docker x86 에뮬레이션 시 tonistiigi/binfmt는 되는데 systemd-binfmt는 안 되는 미스터리 디버깅기. 원인은 QEMU가 동적 링크라서 F 플래그로 메모리에 올려도 의존 라이브러리가 Docker 네임스페이스에 없었던 것.

- ARM(라즈베리 파이) 위에서 x86/amd64 Docker 컨테이너를 돌리려고 binfmt_misc + QEMU를 세팅하는데, **겉으로 완전히 동일한 설정이 전혀 다르게 동작**해서 대혼란에 빠진 디버깅 이야기임. 한때 대장장이로 전직할까 고민했다고 함

## 문제 상황

- Archive Team의 Docker 이미지를 ARM에서 돌리려면 QEMU로 x86 에뮬레이션이 필요함. Docker 공식 방법은 `tonistiigi/binfmt` 이미지를 실행하는 거임

- 근데 재부팅마다 매번 Docker 명령 치기 귀찮으니까, ArchLinux ARM의 **systemd-binfmt**를 쓰면 부팅 시 자동 설정될 거라 생각함

- **Docker 방식**: 동작함 ✅
- **systemd-binfmt 방식**: 파일시스템에서는 x86 바이너리 실행 가능한데, Docker 컨테이너 안에서는 `exec format error` ❌
- `/proc/sys/fs/binfmt_misc/qemu-x86_64` 내용: **완전히 동일** 🤯

## 원인

- 핵심은 **F(fix_binary) 플래그**의 실제 동작 방식임. 이 플래그가 설정되면 에뮬레이터 바이너리를 등록 시점에 열어서 메모리에 유지함. mount namespace나 chroot 환경에서도 동작하려면 이게 필수임

- `tonistiigi/binfmt` 컨테이너는 **자체 정적 컴파일된 QEMU 바이너리**를 가지고 있어서, F 플래그로 메모리에 올린 뒤 컨테이너가 사라져도 동작함. `/proc`에 표시되는 interpreter 경로는 이미 존재하지 않는 경로인데 상관없음

- systemd-binfmt가 실패한 이유: ArchLinux의 QEMU가 **동적 링크된 바이너리**였기 때문임. F 플래그로 바이너리 자체는 메모리에 있지만, 의존하는 라이브러리들은 없으니까 Docker의 네임스페이스 안에서 실행이 안 됨

```
$ file /usr/bin/qemu-x86_64
ELF 64-bit LSB pie executable, ARM aarch64, dynamically linked...
```

- ArchLinux 문서에도 "정적 링크된 QEMU는 보통 필요 없다(usually not needed)"고 적혀있음. 보통은요... 😅

## 해결

- `tonistiigi/binfmt` 컨테이너에서 정적 컴파일된 QEMU 바이너리를 추출해서 `/usr/bin/qemu-x86_64-static`으로 복사
- `/etc/binfmt.d/qemu-x86_64.conf`를 오버라이드해서 정적 바이너리를 가리키도록 수정 + FPOC 플래그 설정
- systemd-binfmt 재시작하면 끝

## 교훈

- 단서는 다 눈앞에 있었지만 경험이 부족해서 조합을 못 했음: Docker 이미지가 자체 QEMU를 가지고 있다는 것, F 플래그의 진짜 의미, 바이너리가 없는데도 실행될 수 있다는 것, 동적/정적 링킹의 차이...

- Claude한테 러버덕 디버깅 시도했는데 **할루시네이션이 트럭 한 대 분량**이었다고 함 — 존재하지 않는 systemd 기능, 없는 커맨드 플래그 등으로 삽질을 유도당함

> [!TIP]
> ARM에서 Docker x86 에뮬레이션이 안 되면, QEMU가 정적 링크인지 먼저 확인할 것. `file /usr/bin/qemu-x86_64`로 "dynamically linked"가 나오면 그게 원인임

## 핵심 포인트

- Docker 방식과 systemd-binfmt 방식이 동일한 /proc 설정을 보여줬지만 동작이 달랐음
- 핵심 원인: ArchLinux의 QEMU가 동적 링크 바이너리라서 Docker 네임스페이스에서 라이브러리 접근 불가
- 해결: 정적 컴파일된 QEMU 바이너리를 추출해서 교체

## 인사이트

binfmt_misc의 F 플래그가 바이너리를 메모리에 유지한다는 것과 동적/정적 링킹의 실제 차이를 체감할 수 있는 훌륭한 디버깅 사례.
