exec format error와 함께 즉시 종료되는 컨테이너는 잘못된 본능을 부릅니다: 기능을 추가하고, 장치를 마운트하고, 터널 구성을 편집하는 것입니다. 그중 어느 것도 문제에 닿지 않습니다. 커널이 바이너리를 전혀 실행할 수 없었고, 컨테이너에서 이는 거의 항상 이미지가 호스트와 다른 CPU 아키텍처를 대상으로 한다는 뜻입니다. 라우팅, 자격 증명, 권한에 대해 바꿀 수 있는 모든 것은 프로그램이 시작된 뒤에 일어나며, 어떤 프로그램도 시작되지 않았습니다.

구성 오류처럼 보이는 시작 메시지

exec 포맷 실패는 애플리케이션이 설정을 하나도 읽기 전에 로더에서 나옵니다. 그래서 그것을 쓸 살아 있는 프로세스가 없기 때문에 구성 경고도 터널 로그도 남지 않습니다. 실패는 또한 놀랍도록 빠르며, 컨테이너 로그에 한 줄도 나타나기 전에 발생하는 경우가 많습니다. 같은 짧은 메시지는 바이너리가 다른 아키텍처용이든, 다른 운영 체제용이든, 손상되었든 나타납니다.

런타임 환경과 아키텍처를 정확한 이미지 참조와 함께 기록하고, 그 참조가 실제로 무엇을 제공하는지 확인하세요. Docker Desktop에서 컨테이너 플랫폼은 노트북이 아니라 Linux 가상 머신에 속하므로 호스트 아키텍처만으로는 오해할 수 있습니다. 이 참조의 인덱스 항목 목록을 읽고, 태그 페이지의 마케팅 문구가 아니라 실제 내용을 확인하세요.

실행 명령 전에 이미지 인덱스를 읽으세요

레지스트리가 멀티 플랫폼 참조를 게시하면 태그는 인덱스를 가리키고, 각 항목은 고유한 digest를 가진 플랫폼을 지정합니다. 이웃 태그가 아니라 검토 중인 참조를 살펴보고, 무엇이 들어 있는지 추측하지 말고 인덱스를 읽으세요.

docker buildx imagetools inspect ghcr.io/example/vpn:1.4
docker image inspect --format '{{.Os}}/{{.Architecture}}' ghcr.io/example/vpn:1.4

첫 번째 명령은 참조가 게시하는 플랫폼을 나열합니다. 두 번째는 이미 로컬에 있는 이미지의 플랫폼을 보고하며, 런타임이 실행할 것은 바로 그것입니다. 항목이 하나뿐인 참조는 모든 호스트가 같은 바이너리를 받는다는 뜻이며, 그 태그는 한 번도 빌드된 적 없는 머신에는 도움이 되지 않습니다.

태그는 변형을 선택할 뿐, 만들지는 않습니다

멀티 플랫폼 인덱스는 런타임이 일치하는 항목을 고르게 해 주며, 이는 정말 편리하고 종종 이식성으로 오해됩니다. 선택은 조회이지 번역이 아니므로 변형이 없으면 고를 것이 없습니다. 따라서 같은 태그가 두 호스트에서는 서로 다른 두 바이너리로 해석될 수 있고, 한 호스트에서는 쓸 만한 것으로 해석되지 않습니다.

digest로 고정하면 digest가 테스트된 바이트를 정확히 식별하므로 모호함이 사라지고 나중의 검토도 가능해집니다. 그 digest를 배포 기록과 함께 보관하고, 우연히 최신이었던 태그에 의존하지 마세요.

에뮬레이션은 합의이지 번역 계층이 아닙니다

지원되는 런타임을 통한 에뮬레이션은 일부 비네이티브 사용자 공간 워크로드를 실행할 수 있으므로, 한 아키텍처가 다른 아키텍처의 이미지를 절대 실행할 수 없다는 단정은 틀렸습니다. 그것은 일반적인 해결책도 아닙니다. 에뮬레이션된 실행은 성능 특성이 다르며, 시작되는 사소한 프로세스는 터널 워크로드가 수용 가능하게 동작하는지에 대해 아무것도 알려 주지 않습니다.

Docker의 멀티 플랫폼 가이드는 네이티브 빌드, 크로스 컴파일, 에뮬레이션을 별개의 전략으로 다루며, 그것이 옵션을 읽는 올바른 방법입니다. 하나를 의도적으로 선택하고, 동등하다고 가정하지 말고 그 아래에서 VPN 워크로드를 평가하세요.

권한은 다른 문제를 해결합니다

네트워크 관리 기능을 부여하거나 TUN 장치를 전달해도 호환되지 않는 실행 파일이 실행되게 할 수는 없습니다. 이것은 실행 중인 프로세스가 사용하는 런타임 권한이며, 파일을 이미 거부한 로더에게는 보이지 않습니다.

반대도 마찬가지로 사실입니다. 네이티브 바이너리는 권한, 장치 접근, 리졸버 통합, 터널에 필요한 재시작 정책에 대해 아무것도 증명하지 않으므로 시작하는 컨테이너는 아직 동작하는 컨테이너가 아닙니다. 먼저 플랫폼 계약을 확립하고, 그다음 문서화된 옵션과 함께 런타임 계약으로 넘어가세요.

이미지 digest, 지원 대상, 구성을 같은 기록에 함께 보관하세요. 아키텍처를 조용히 바꾸는 태그 업데이트는 이전 digest가 적혀 있을 때, 유일한 증상이 익숙한 오류와 디버깅에 쓴 새로운 오후일 때보다 잡아내기 쉽습니다.

관련 글