Dockerイメージサイズを最適化する一般的な方法

Dockerイメージサイズを最適化する一般的な方法

通常、私たちが構築する Docker イメージはサイズが大きく、多くのディスク領域を占有します。コンテナを大規模に展開すると、貴重な帯域幅リソースも浪費されます。この記事では、Docker イメージのサイズを最適化するための一般的な方法をいくつか紹介します。ここでは、公式 Docker Hub の Redis イメージを例として使用します。

手動管理

直接的に考えられる方法は、公式の Redis イメージの Dockerfile ファイルを直接変更し、コンテナの実行後に不要なコンポーネントを手動で削除して、新しいイメージを再構築することです。この方法は理論的には実行可能ですが、エラーが発生しやすく、効果も特に明らかではありません。主な問題は、公式ミラーとリアルタイムで同期できないことです。

多段階ビルド

この問題を解決するために、Docker はバージョン 17.05 以降、マルチステージ ビルド機能を提供しています。このアプローチは、中間層を破棄し、中間層を使用して最終イメージとそのコンテンツの作成方法に関する情報を提供することで実現されます。コンテナ化されたアプリケーションに必要なコンポーネントのみを保持する必要があります。より高いレベルでの実装は次のとおりです。

  • いくつかの画像を基に構築する
  • 通常通りコマンドを実行してアプリケーションをビルドします
  • 必要なアーティファクトを別のイメージにコピーする

ディストロレス

Google はコンテナ化技術、特に Docker に大きく依存してきたため、肥大化したイメージを使用することの欠点を長い間認識してきました。そこで彼らは、この問題に対する独自の解決策、つまり distroless イメージを提供しました。一般的な Linux ベース イメージ (多くのソフトウェアがバンドルされている) とは異なり、distroless でアプリケーションを Docker 化すると、最終イメージにはアプリケーションとそのランタイム依存関係のみが含まれます。パッケージ マネージャーやシェルなど、ほとんどの Linux ディストリビューションに含まれている標準ソフトウェアは除外されます。同様に、Google の distroless イメージを使用するには、次のように、前述のマルチステージ ビルドを使用する必要があります。

redis:latest ASビルドから 
引数タイムゾーン 
mkdir -p /opt/etc && \ を実行します。 
 cp -a --parents /lib/x86_64-linux-gnu/libm.so.* /opt && \ 
 cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \ 
 cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \ 
 cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \ 
 cp -a --parents /usr/local/bin/redis-server /opt && \ 
 cp -a --parents /usr/local/bin/redis-sentinel /opt && \ 
 cp /usr/share/zoneinfo/${TIME_ZONE:-UTC} /opt/etc/localtime 
 
gcr.io/distroless/base より 
コピー --from=build /opt / 
ボリューム/データ 
ワークディレクトリ /データ 
エントリポイント ["redis-server"]

redis:latest をベース イメージとして使用し、必要なバイナリ (redis-server バイナリと関連するすべての依存関係) を保持し、distroless イメージをビルドする最終イメージのベースとして使用します。opt ディレクトリの内容をイメージ ディレクトリにコピーします。

次に、イメージを再構築するだけです。

$ docker build -t redis:distroless .$ docker imagesリポジトリタグイメージID作成サイズredis distroless 7d50bd873bea 15秒前 28.2MBredis latest 1319b1eaa0b7 3日前 104MB

画像サイズが 104 MB から 28.2 MB に削減され、大幅に削減されたことがわかります。

注: Linux では、 $ ldd $(which redis-server) などの ldd ツールを使用して、指定されたバイナリ ファイルに必要な依存関係を見つけることができます。

ディストロレス イメージを使用して Docker イメージのサイズを縮小することは非常に効果的な方法ですが、明らかな欠点もあります。最終イメージにはシェル プログラムがないため、Docker コンテナーのデバッグが非常に困難になります。もちろん、これによりアプリケーション攻撃のリスクも軽減され、セキュリティも向上します。アプリケーションを Kubernetes クラスターにデプロイする場合、kubectl-debug などのツールを使用してアプリケーションのデバッグを支援できます。

アルパイン・リナックス

もう 1 つの一般的な方法は、最小限の Docker イメージを作成するのに特に適したディストリビューションである Alpine Linux に基づいてアプリケーション イメージを構築することを選択することです。 Apline Linux は、glibc の代わりに小さい musl C ライブラリを使用し、それを静的にリンクします。つまり、musl 用にコンパイルされたプログラムは再配置可能なバイナリになり、共有オブジェクトを含める必要がなくなり、イメージのサイズを大幅に削減できます。

redis:alpine イメージは約 30MB です。欠点は、musl は通常 glibc ほどパフォーマンスが良くないことです。もちろん、もう 1 つ利点があります。上記の distroless と比較すると、Alpine は基本的なシェル アクセスを提供する成熟した Linux ディストリビューションであり、Docker コンテナー アプリケーションのデバッグが容易になります。また、Redis、Nginx、MySQL など、ほぼすべての一般的なソフトウェアの Alpine バージョンも Docker Hub で見つけることができます。

GNU ギックス

最後に、Docker イメージを作成する機能を備えた多目的パッケージ管理ツールである GNU Guix を使用します。 Guix はパッケージのランタイム依存関係とビルド依存関係を区別するため、Guix でビルドされた Docker イメージには、distroless アプローチと同様に、明示的に指定されたプログラムとそのランタイム依存関係のみが含まれます。しかし、プログラムの実行時依存関係を自分で確認する必要がある (そしてもちろん Dockerfile を作成する) distroless とは異なり、Guix では、 $ guix pack -f docker redis という 1 つのコマンドを実行するだけで済みます。

上記のコマンドで作成された Redis イメージのサイズは約 70 MB で、元のイメージと比較すると大幅に削減されています。distroless および Alpine 方式で作成されたイメージよりもわずかに大きいですが、Guinx を使用すると他の利点もいくつかあります。たとえば、最終イメージに Alpine のようなデバッグ用のシェルを含める場合は、Guxi をパッケージ化するときにのみ指定する必要があります: $ guix pack -f docker redis bash 。他のソフトウェアを含める場合は、後から追加し続けることができます。

Guix の機能により、パッケージ ビルドは 100% 再利用可能であるため、CI/CD パイプラインに Guix サポートを追加して、ビルド プロセスを非常にスムーズにすることができます。

Guix はかっこいいと思う人もいるかもしれませんが、小さな Docker イメージを作成するためだけに別のツールをダウンロードしてインストールしたくないと思う人もいるでしょう。さらに、Guix は Linux でしか動作しません。多くの開発者は依然として MacOS ユーザーであるため、Guix の設定は面倒です。実は、これについては心配する必要はありません。Guix 自体も Docker Hub に Docker イメージがあるので、使い方はそれほど複雑ではありません。シンプルな $ docker run guix コマンドを使用するだけで済みます。

Guix に加えて、Nix と呼ばれるパッケージ管理ツールがあることに言及する価値があります。Guix について言及されているすべてのことは、Nix にも同様に有効であり、適用できます。

上記は、Docker イメージのサイズを最適化する一般的な方法の詳細です。Docker イメージのサイズの最適化の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Docker マルチステージビルドを使用してイメージサイズを縮小する方法
  • Dockerイメージのサイズを縮小する6つの方法

<<:  テキストの展開と折りたたみの効果を実現するJavaScript

>>:  React プロジェクトで eslint の Baidu スタイルを使用する詳細な説明

推薦する

JDBC-idea で mysql をインポートして java jar パッケージに接続する (mac)

序文1. この記事ではMySQL 8.0バージョンを使用していますバージョン5.0と比較すると、パッ...

音声キューイングシステムを実装するためのJavaScript

目次導入主な特徴エフェクト表示キーコード導入音声キューイングシステムは、銀行、レストラン、病院などの...

システムメンテナンスページにリダイレクトするように nginx を設定する

先週末、兄弟プロジェクトはより良いサービスを提供するためにサーバーを拡張する準備をしていました。兄弟...

テーブルの追加と削除の操作を実装する js

この記事の例では、テーブルを追加および削除するためのjsの具体的なコードを参考までに共有しています。...

Docker Secretの管理と使用の詳細な説明

1. Docker Secretとは1. シナリオ表示MySQL サービスなど、一部のサービスではパ...

Nginx フォワード プロキシとリバース プロキシ、および負荷分散機能の構成コード例

この記事は主に、Nginx のフォワード プロキシとリバース プロキシ、および負荷分散機能の設定コー...

mysql の認証、起動、およびサービスの起動のための一般的なコマンド

1. 4つの起動方法: 1.mysqld MySQL サーバーを起動します: ./mysqld --...

Vue要素はテーブルの追加、削除、データの変更を実装します

この記事では、テーブル内のデータを追加、削除、変更するためのvue要素の具体的なコードを参考までに共...

Nuxt.jsプロジェクトのDockerデプロイメントの実装

Docker 公式ドキュメント: https://docs.docker.com/ Docker は...

ノードを使用して静的ファイルキャッシュを実装する方法

目次キャッシュキャッシュ位置の分類キャッシュ設定ヘッダーNodeは静的ファイルキャッシュを実装する強...

docker に nacos をインストールしてデータベースを構成する詳細なチュートリアル

環境の準備 Docker環境 MySQL 5.7 (公式イメージはmysql8をサポートしていません...

Linux システムで IPv6 をサポートするように Nginx を設定する方法

1. 既存のnginxがipv6をサポートしているかどうかを確認する既存の nginx が ipv6...

フロントエンドの面接の質問の最も包括的なコレクション

HTML+CSS 1. WEB 標準と W3C の理解と知識<br /> タグを閉じ、小...

VMwareでCentOSがインターネットにアクセスできない問題を素早く解決

昨日、VMware に CentOS7 をインストールしました。Tomcat パッケージを転送するた...

jsを使用してシンプルな弾幕スクリーンシステムを実装する

この記事では、弾幕効果を実現するためのネイティブjsの具体的なコードを参考までに共有します。具体的な...