
QEMU를 사용하여 휴대용 크로스아키 Docker 컨테이너를 구축하려고 합니다. 그러나 호스트 시스템과 호스트에 설치된 프로그램에 따라 컨테이너는 다르게 동작합니다.
Windows에서 컨테이너를 실행하면 에뮬레이션이 제대로 작동합니다. Ubuntu 16.04에서도 잘 작동합니다.언제qemu-user-static이 설치되었습니다. 그러나 그렇지 않은 경우 에뮬레이션이 중지됩니다.
에뮬레이션은 호스트 커널(Linux의 Docker) 또는 VM 커널(Windows의 Docker)에서 binfmt 지원이 활성화되어 있고 컨테이너 파일 시스템에서 필요한 바이너리를 사용할 수 있는 한 작동합니다.
내 목표는 고객이 Host-OS 자체 또는 커널에 대한 수정을 금지하기 때문에 qemu를 커널의 인터프리터로 등록할 필요 없이 컨테이너를 이식 가능하고 실행 가능하게 만드는 것입니다. 그러나 현재는 컨테이너를 실행한 결과입니다.
$ sudo docker run -ti qemu:xenial_arm64
qemu-aarch64-static: /usr/bin/groups: cannot execute binary file: Exec format error
/usr/bin/lesspipe: line 28: /usr/bin/basename: cannot execute binary file: Exec format error
/usr/bin/lesspipe: line 282: /usr/bin/dirname: cannot execute binary file: Exec format error
/usr/bin/lesspipe: line 295: [: =: unary operator expected
qemu-aarch64-static: /usr/bin/dircolors: cannot execute binary file: Exec format error
root@41f2795e2569:/# uname -m
qemu-aarch64-static: /bin/uname: cannot execute binary file: Exec format error
그러나 qemu-user-static을 설치하면(qemu를 설치하면 binfmt_misc에서도 활성화됩니다):
$ sudo apt-get -yqq install qemu-user-static
Selecting previously unselected package qemu-user-static.
(Reading database ... 245713 files and directories currently installed.)
Preparing to unpack .../qemu-user-static_1%3a2.5+dfsg-5ubuntu10.42_amd64.deb ...
Unpacking qemu-user-static (1:2.5+dfsg-5ubuntu10.42) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up qemu-user-static (1:2.5+dfsg-5ubuntu10.42) ...
$ sudo docker run -ti qemu:xenial_arm64
root@7903b45a3c1e:/# uname -m
aarch64
이에 대한 나의 설명은 다음과 같습니다.
- qemu-aarch64-static이 /bin/bash 에뮬레이션을 시작합니다.
- /bin/bash는 execve(..)를 사용하여 다른 실행 파일을 호출합니다.
- 리눅스 호스트:
- 호스트 또는 컨테이너(Linux에서는 호스트와 Docker 게스트가 커널을 공유함)에 의해 binfmt_misc가 활성화된 경우 qemu는 arm64 실행 파일에 대한 인터프리터로 동적으로 할당됩니다.
- 그렇지 않으면 실행이 실패하고 "Exec 형식 오류"가 발생합니다.
- Windows 호스트:
- Windows와 Linux는 서로 다른 커널을 가지고 있으므로 syscall을 호스트 커널에 전달하여 Linux 게스트를 실행할 수 없습니다.
- 따라서 Windows에서는 컨테이너가 별도의 커널을 사용하여 VM 내부에서 실행됩니다. 해당 커널은 컨테이너와 공유됩니다.
- binfmt-support가 포함된 qemu-user-static이 컨테이너에 설치되고 활성화된 경우에도 여전히 해당 목적을 수행하고 qemu를 다른 아키텍처의 실행 파일에 대한 인터프리터로 동적으로 할당합니다.
Linux와 Windows에서 실행하면 동일한 결과가 나타납니다.
가능한 수정 방법은 --privileged 플래그를 사용하여 컨테이너를 시작하는 것입니다. 그러면 binfmt_misc를 마운트하여 qemu-user-static을 컨테이너 내부의 인터프리터로 등록할 수 있습니다. 하지만 우리 고객은 해당 플래그를 사용하는 것을 금지했습니다.
설명된 접근 방식을 이미 테스트했습니다.여기qemu-user의 -0 플래그도 마찬가지입니다. 둘 다 작동하지 않습니다.
도커파일:
FROM scratch
ADD xenial-arm64-rootfs /
ADD qemu-aarch64-static /usr/bin/qemu-aarch64-static
RUN chmod +x /usr/bin/qemu-aarch64-static
ENTRYPOINT ["/usr/bin/qemu-aarch64-static", "-0", "/usr/bin/qemu-aarch64-static"]
CMD ["/bin/bash"]
qemu-aarch64-static은 /usr/bin/qemu-aarch64-static에서 가져옵니다(qemu-user-static으로 설치됨). xenial-arm64-rootfs는 다음을 사용하여 생성됩니다.
qemu-debootstrap --arch=arm64 --components=main,universe,multiverse,restricted --variant=buildd --foreign xenial xenial-arm64-rootfs http://ports.ubuntu.com/ubuntu-ports/
에뮬레이션을 계속 진행하려면 어떻게 해야 합니까?