私は奇妙なコンテナを作りたいのですが、私の仕事の1つはuname
バイナリを置き換えることです。
私はそれをコーディングしました:
#include <stdio.h>
int main() {
printf("This is a fake uname\n");
return 0;
}
コンパイル:
gcc uname.c -o uname
Ubuntuで実行するとうまくいきます。
1つを作成してDockerfile
画像にコピーしました。
cat > Dockerfile <<EOF
FROM alpine:latest
RUN rm /bin/uname
COPY uname /bin/
ENTRYPOINT sh;
WORKDIR /home
EOF
そしてそれを構築docker build -t myimage -f Dockerfile .
画像を実行すると:
docker run -it --rm myimage
ファイルが存在するが実行しようとすると、存在しないと記録されます。
/home # uname
sh: uname: not found
/home # ls -lia uname
ls: uname: No such file or directory
/home # ls -lia /bin/uname
35 -rwxr-xr-x 1 root root 8600 Jan 29 13:27 /bin/uname
ベストアンサー1
問題は(Ubuntuを使用しているため)バイナリをビルドしてからAlpine(Ubuntuを使用しているため)glibc
で実行することです。musl
バイナリをビルドすると、一部のメタデータがハードコードされます。通訳(動的リンカー)位置。バイナリ実行中、カーネルはこのインタプリタを使用して、バイナリとすべてのランタイム依存関係をロードします。インタプリタ用にビルドすると、glibc
バイナリは次のように要求します(に似ています)。glibc
/lib64/ld-linux-x86-64.so.2
$ readelf -l /bin/uname
<...>
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
しかし、アルパインにはそのような通訳はありません。代わりに、/lib/ld-musl-x86_64.so.1
Alpineのすべてのバイナリはこのインタプリタを要求するように構築されています。
# readelf -l /bin/busybox
<...>
[Requesting program interpreter: /lib/ld-musl-x86_64.so.1]
したがって、uname
UbuntuでビルドをビルドしてからAlpineで実行すると、カーネルがインタプリタを見つけることができないので、見つかりません」。
興味深いことに、通訳者を手動で呼び出すことができます。これが問題の場合は機能します。ただ通訳から:
# /lib/ld-musl-x86_64.so.1 /bin/uname
This is a fake uname
しかし、これはもちろん問題解決の目的だけです。
だから何をしますか?
オプションは、バイナリを静的にリンクすることです(これにより、カーネルが独自にバイナリをロードして実行できるように、インタプリタとすべての共有ライブラリは必要ありません)。
gcc uname.c -static -o uname
またはAlpineでビルドしてください(おそらくDocker多段階構築?この場合、意図を明確に示し、元のAlpineのバイナリを置き換えるためにAlpineでカスタムバイナリを構築していることを示すため、このアプローチをお勧めします。