Linuxコンテナ内の/ binのバイナリを置き換える方法

Linuxコンテナ内の/ binのバイナリを置き換える方法

私は奇妙なコンテナを作りたいのですが、私の仕事の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.1Alpineのすべてのバイナリはこのインタプリタを要求するように構築されています。

# readelf -l /bin/busybox
<...>
      [Requesting program interpreter: /lib/ld-musl-x86_64.so.1]

したがって、unameUbuntuでビルドをビルドしてから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でカスタムバイナリを構築していることを示すため、このアプローチをお勧めします。

おすすめ記事