2017 年に Vulhub に取り組み始めてから、私は厄介な問題に悩まされてきました。Dockerfile を書くときに、 1. Alpine Linuxの使用 Alpine Linux は、BusyBox と Musl Libc をベースにした Linux ディストリビューションです。最大の利点はサイズが小さいことです。純粋なベースの Alpine Docker イメージは、圧縮するとわずか 2.67 MB になります。 多くの公式 Docker イメージには、PHP などの Alpine バージョンがあります。 比較してみると、アルパインバージョンの画像の大きさは通常バージョンの約1/5であることがわかります。 しかし、Docker Hub では、Mysql や PHP-Apache など、ほとんどのイメージに Alpine バージョンがありません。これらの環境をベースに開発する必要がある場合は、自分で Alpine バージョンを作成するか、サードパーティのイメージを探す必要があります。 さらに、Alpine のもう 1 つの欠点は、従来の glibc の代わりに Musl Libc を使用していることです。ソフトウェアをコンパイルするときに、予期しない問題が発生する可能性があり、多くの無駄な時間を費やすことになります。 2. 最小限の依存関係のみをインストールする apt-get、yum、apk などのパッケージ マネージャーは、イメージをコンパイルするときに使用する必要があるツールです。純粋な Docker ベースのイメージには通常、wget、curl、git、gcc などのツールがないため、手動でインストールする必要があります。 apt を例に挙げてみましょう。ソフトウェアをインストールするときに、apt-get はオプション これにより、イメージのサイズはある程度縮小されますが、その副作用として、対象ソフトウェアの一部の機能が不足する可能性があります。 たとえば、この時点で wget はサーバー証明書の信頼性を検証できず、コマンド エラーが発生します。 したがって、私たちの一般的なやり方は、apt を使用するときに apt-get install --no-install-recommends wget ca-certificates 3. aptの混乱を解消する 一部のツールはコンパイル段階でのみ使用されます。貴重なイメージ容量を占有させたくありません。イメージのコンパイルが完了したら、これらの中間依存関係を削除できます。 apt を例に挙げてみましょう。apt を使用した後は、次の操作を行う必要があります。
このプロセスでは、どの依存関係が「不要」なのかという非常に難しい問題に遭遇します。 たとえば、PHP をコンパイルする場合、wget、libxml、gcc の 3 つのツールを使用できます。 PHP をコンパイルする前に、これら 3 つのツールをインストールする必要があります。しかし、コンパイルが完了した後、wget と gcc はアンインストールできますが、libxml はアンインストールできません。 その理由は、libxml は PHP が依存するダイナミック リンク ライブラリだからです。これをアンインストールすると、共有リンク ライブラリが見つからないというエラーが発生します。 ルート@8eab53da8d5b:/#php -v php: 共有ライブラリのロード中にエラーが発生しました: libxml2.so.2: 共有オブジェクトファイルを開けません: そのようなファイルまたはディレクトリはありません では、「共有リンク ライブラリ」ではない依存関係のみを自動的に検出して削除する、より便利な方法はありますか? もちろんあります。もっと簡単な方法は、新しくコンパイルされた実行可能ファイルを走査し、ldd コマンドを使用してそれが依存する共有リンク ライブラリ ファイル名を一覧表示し、ソース内でこのファイル名に対応するパッケージ名を検索することです。 これらのパッケージはすべて、PHP が依存するダイナミック リンク ライブラリです。次に、 その後、残りの未使用のパッケージを自動的にアンインストールできます。完全なシェル スクリプトは次のとおりです。 /usr/local を見つけます -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { $(NF-1) を印刷 }' \ | ソート -u \ | xargs -r dpkg-query --search \ | カット -d: -f1 \ | ソート -u \ | xargs -r apt-mark マニュアル \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; 4. 中間依存関係を1ステップでインストールおよびアンインストールする Docker イメージは、レイヤーで構成された階層化されたケーキです。docker Dockerfile の場合、後者のレイヤーが前のレイヤーに保存されたファイルを削除したとしても、これらのレイヤーのデータはイメージに保存されます。 たとえば、次の Dockerfile があります。 アルパインより:3.12 実行 truncate -s 50M /sample.dat rm -rf /sample.dat を実行します。 このコンパイルされたイメージの大きさは 58 MB です。 比較すると、通常の alpine:3.12 はわずか 5.57 MB です。つまり、 そのため、前述の「中間依存関係」を削除する際には、確実に領域を解放するために、インストール、使用、アンインストールの 3 つの部分を 1 つのステップで記述する必要があります。例えば: debian:buster より apt-get update を実行する\ && apt-get install gcc \ && gcc ... \ && apt-get purge --autoremove gcc \ && rm -rf /var/lib/apt/lists/* 5. 多段階コンパイル Docker バージョン 17.05 以降では、マルチステージ ビルドの概念が導入され、上記のすべての操作が大幅に簡素化されます。 簡単に言えば、マルチステージ ビルドを使用すると、Docker イメージのコンパイルを複数の「ステージ」に分割できます。たとえば、一般的なソフトウェアのコンパイルの場合、コンパイル段階を分離し、ソフトウェアのコンパイルが完了した後にバイナリファイルを新しいベースイメージに直接コピーすることができます。これの最大の利点は、2 番目のイメージにはコンパイル段階で使用される中間依存関係が含まれなくなり、クリーンで明確になることです。 最も一般的な Java プロジェクトを例にとると、Jar パッケージをコンパイルするときには JDK や Maven などのツールを使用する必要がありますが、実際の運用段階では JRE 環境のみが必要になります。 2 つのイメージ ( その差は2倍以上です。 Vulhub の Shiro 1.2.4 環境を例にとると、Dockerfile には 2 つの maven:3-jdk-8 AS ビルダーから ラベル MAINTAINER="phithon <[email protected]>" ./code/ /usr/src/ をコピー ワークディレクトリ /usr/src 実行cd /usr/src; \ mvn -U クリーンパッケージ -Dmaven.test.skip=true openjdk:8u102-jre から ラベル MAINTAINER="phithon <[email protected]>" コピー --from=builder /usr/src/target/shirodemo-1.0-SNAPSHOT.jar /shirodemo-1.0-SNAPSHOT.jar エクスポーズ8080 CMD ["java", "-jar", "/shirodemo-1.0-SNAPSHOT.jar"] 最初の 最終的に、マシン上に 2 つのイメージが残ります。1 つはビルダーで、もう 1 つは最終的に必要となる shiro 1.2.4 環境です。後者は他のユーザーが独立して使用できますが、前者は直接削除できます。 ユーザーは、ソフトウェアをコンパイルしてイメージを小さくするときに、中間依存関係をどのように削除するかを心配する必要がなくなりました。いずれにしても、最初の段階で使用された依存関係は、正式な本番環境に残されません。 しかし、マルチステージコンパイルでは、ダイナミックリンクライブラリに依存するという前述の問題が依然として残ります。コンパイル結果をコピーするときに実行可能ファイルのみをコピーすると、新しい環境で実行したときに共有リンクライブラリが見つからないというエラーが依然として発生します。そのため、個人的には、マルチステージコンパイルは、Java や golang などのクロスプラットフォームまたは静的コンパイルが可能な言語にのみ適しており、C や Python などの依存関係が多いプロジェクトにはまだ適していないと感じています。 6. 画像のスリムバージョンを使用する 注意深い学生なら、公式の Docker Debian イメージに、デフォルト バージョンの 2 倍以上のサイズのスリム バージョンがあることに気付いたかもしれません。 slim の中国語の意味は「スリム」です。名前が示すように、 一部の上位レベルのイメージは、Python など、Debian のスリム バージョンに基づいて作成されています。 Python プロジェクトを開発する場合は、 まとめると、6 つの方法は互いに影響を及ぼさず、同時に使用できます。しかし、5番目の多段階コンパイルは、将来的には主流の方法になるでしょう。 以上で、Docker イメージのサイズを小さくする 6 つの方法についての説明は終了です。Docker イメージのサイズを小さくする方法の詳細については、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
>>: 階段を転がす特殊効果を実現する JavaScript (jQuery 実装)
システム:セントOS7 RPM パッケージ: mysql-コミュニティクライアント-5.7.18-1...
序文Web 上でオンライン コード コンパイルの効果を実現したい場合は、 CodeMirrorを再度...
ページをデザインするときには、ログイン ウィンドウを中央に配置するなど、DIV を中央に配置し、ペー...
目次1. SVNとは何か2. SVNサーバーとクライアントの取得方法3. SVN ワークフローとアー...
目次1. テンプレート文字列とは何ですか? 2. 複数行のテンプレート文字列2.1 式付きテンプレー...
1. はじめになぜインデックスが必要なのでしょうか?一般的なアプリケーション システムでは、読み取り...
1. ノードサーバーのセットアップ + データベース接続ここでの操作は比較的簡単でわかりやすいです。...
目次過去1週間の時間を取得する過去1か月の時間を取得する過去3か月分を取得新しい Date() と ...
DockerをインストールするDocker をインストールする必要がありますが、それ以上の指示はあり...
他の人のウェブページを保存して見たことがあると思いますが、特にdwで開くと、多くのウェブページに&l...
感想:私はバックエンド開発者です。静的 (HTML) ページを取得すると、ページ構造と命名規則が極端...
負荷分散とは負荷分散は主に、専用のハードウェア デバイスまたはソフトウェア アルゴリズムによって実現...
1. インターネットで長時間検索しましたが、判定表が存在するかどうかがわからなかったので、漠然と削除...
実験環境:物理マシン Windows 10 x64物理NIC情報IPv4 アドレス: 192.168...
退屈だったので、ループに関する簡単な演習をいくつかまとめてみました。JS を学び始めたばかりの方に役...