Red Hat Training

A Red Hat training course is available for OpenShift Online

2.2. コンテナーイメージについての一般的なガイドライン

以下のガイドラインは、イメージが OpenShift Online で使用されるかどうかにかかわらず、コンテナーイメージの作成時に一般的に適用されます。

イメージの再利用

可能な場合は、FROM ステートメントを使用し、適切なアップストリームイメージをベースとしてイメージを設定することを推奨します。これにより、依存関係を直接更新する必要なく、イメージが更新時にアップストリームイメージからセキュリティー修正を簡単に取得できるようになります。

さらに、FROM 命令 (例: rhel:rhel7) のタグを使用して、お使いのイメージがどのバージョンのイメージをベースとしているかを明確にします。アップストリームイメージの latest バージョンを使用すると互換性に影響のある変更が組み込まれる可能性があるため、latest 以外のタグを使用することができます。

タグ内の互換性の維持

独自のイメージにタグを付ける場合には、タグ内で後方互換性が維持されるようにすることを推奨します。たとえば、foo という名前のイメージがあり、現時点でバージョン 1.0 が含まれている場合には、タグに foo:v1 を指定します。イメージの更新時には、元のイメージとの互換性がある限り、新しいイメージに foo:v1 のタグを付けることができ、このタグのダウンストリームのコンシューマーは、互換性に関する影響を被ることなく更新を取得できるようになります。

互換性のない更新を後にリリースした場合には、foo:v2 などの新しいタグに切り替える必要があります。これにより、ダウンストリームのコンシューマーはいつでも新しいバージョンに移行できますが、意図せずにこの互換性のない新規イメージによる影響を受けることはありません。foo:latest を使用するダウンストリームコンシューマーには、互換性のない変更が導入されるリスクがあります。

複数プロセスの回避

データベースや SSHD など複数のサービスを 1 つのコンテナー内で起動しないようにしてください。コンテナーは軽量で、複数のプロセスをオーケストレーションするために簡単にリンクできるので、複数プロセスの実行は不要です。OpenShift Online では、関連のあるイメージを 1 つの Pod にグループ化して、簡単に共存させ、共同管理することができます。

この共存により、コンテナーがネットワークの namespace とストレージを通信用に共有できるようになります。また、イメージの更新頻度が低く、個別に更新されるので、更新による中断の可能性が低くなります。シグナル処理のフローは、生成されたプロセスへのルーティングシグナルを管理する必要がないため、単一プロセスの場合により明確になります。

ラッパースクリプトでの exec の使用

詳細は、Project Atomic ドキュメントの「Always exec in Wrapper Scripts」セクションを参照してください。

また、コンテナー内で実行すると、プロセスは PID 1 として実行される点に留意してください。つまり、主なプロセスが中断された場合には、コンテナー全体が停止され、PID 1 プロセスから起動した子プロセスが終了します。

その他の影響については、Docker and the PID 1 zombie reaping problem のブログ記事を参照してください。また、PID 1 および init システムの詳細については、Demystifying the init system (PID 1) のブログ記事も参照してください。

一時ファイルの消去

ビルドプロセスで作成される一時ファイルはすべて削除する必要があります。これには、ADD コマンドで追加したファイルも含まれます。たとえば、yum install の操作を実行してから、yum clean コマンドを実行することを強く推奨します。

yum キャッシュがイメージレイヤーに残らないように、以下のように RUN ステートメントを作成します。

RUN yum -y install mypackage && yum -y install myotherpackage && yum clean all -y

以下のように記述した場合には注意してください。

RUN yum -y install mypackage
RUN yum -y install myotherpackage && yum clean all -y

上記のように記述すると、最初の yum 呼び出しにより、対象のレイヤーに追加のファイルが残り、yum clean 操作を後に実行してもこれらのファイルは削除できません。これらの追加ファイルは最終イメージでは確認できませんが、下位レイヤーには存在します。

現在の Docker ビルドプロセスでは、前のレイヤーで何かが削除された場合でも、後のレイヤーでコマンドを実行してイメージが使用する容量を縮小できません。ただし、これについては今後変更される可能性はあります。後のレイヤーでファイルが表示されていなくても rm コマンドを実行したとしても、ダウンロードするイメージの全体のサイズを縮小することになりません。そのため、yum clean の場合のように、可能な場合は後にレイヤーに書き込まれないように、ファイルの作成に使用したのと同じコマンドでファイルを削除することが最も適切と言えます。

また、単一の RUN ステートメントで複数のコマンドを実行すると、イメージのレイヤー数が減り、ダウンロードと実行時間が短縮されます。

適切な順序での命令の指定

Docker は Dockerfile を読み取り、トップダウンで命令を実行します。命令が正常に実行されると、同じイメージが次回ビルドされるときや、別のイメージがビルドされる時に再利用することができるレイヤーが作成されます。Dockerfile の上部にほとんど変更されない命令を配置することは非常に重要です。こうすることで、上位レイヤーで加えられた変更によってキャッシュが無効にならないので、同じイメージの次回のビルドをすばやく実行できます。

たとえば、反復するファイルをインストールするための ADD コマンドと、パッケージを yum install する RUN コマンドが含まれる Dockerfile で作業を行う場合には、ADD コマンドを最後に配置することが最善の方法です。

FROM foo
RUN yum -y install mypackage && yum clean all -y
ADD myfile /test/myfile

これにより、myfile を編集して、 docker build を返すたびに、システムは yum コマンドのキャッシュされたレイヤーを再利用し、ADD 操作に対してのみ新規レイヤーを生成します。

以下のように Dockerfile を記述した場合:

FROM foo
ADD myfile /test/myfile
RUN yum -y install mypackage && yum clean all -y

次に、myfile を変更して、docker build を再実行するたびに、ADD 操作は RUN 階層キャッシュを無効にするので、yum 操作も再実行する必要があります。

重要なポートへのマーキング

詳細は、『Project Atomic ドキュメント』の「Always EXPOSE Important Ports」のセクションを参照してください。

環境変数の設定

ENV 命令で環境変数を設定することが適切です。一例として、プロジェクトのバージョンを設定することなどが挙げられます。これにより、Dockerfile を確認せずにバージョンを簡単に見つけ出すことができます。別の例としては、JAVA_HOME など、別のプロセスで使用可能なシステムでパスを公開する場合などです。

デフォルトパスワードの回避

デフォルトのパスワードは設定しないことが最善の策です。イメージを拡張して、デフォルトのパスワードを削除または変更するのを忘れることが多くあります。これは、実稼働環境で使用するユーザーに誰でも知っているパスワードが割り当てられると、セキュリティーの問題に発展する可能性があります。パスワードは、環境変数を使用して設定できるようにする必要があります。詳細は、設定での環境変数の使用についてのトピックを参照してください。

デフォルトのパスワードを設定することにした場合には、コンテナーの起動時に適切な警告メッセージが表示されるようにしてください。メッセージはデフォルトパスワードの値をユーザーに通知し、環境変数の設定など、パスワードの変更方法を説明するものである必要があります。

SSHD の回避

イメージでの SSHD の実行を回避するようにしてください。ローカルホストで実行中のコンテナーにアクセスするには、docker exec コマンドを使用できます。または、oc exec コマンドまたは oc rsh コマンドを使用して OpenShift Online クラスターで実行されているコンテナーにアクセスできます。イメージを使用して SSHD をインストール、実行すると、攻撃の経路が増え、セキュリティー修正が必要になります。

永続データ向けのボリュームの使用

イメージは、永続データ用に Docker ボリューム を使用する必要があります。こうすることで、OpenShift Online により、コンテナーを実行するノードにネットワークストレージがマウントされ、コンテナーが新しいノードに移動した場合に、ストレージはそのノードに再度割り当てられます。永続ストレージのすべての要件に対応するようにボリュームを使用することで、コンテナーが再起動されたり、移動されたりしても、コンテンツは保存されます。イメージがコンテナー内の任意の場所にデータを書き込む場合には、コンテンツは保存されない可能性があります。

コンテナーが破棄された後も保存する必要のあるデータはすべて、ボリュームに書き込む必要があります。Docker 1.5 では、コンテナーに readonly フラグが使用され、これにより、コンテナーの一時ストレージにデータが記述されないようにすることができます。イメージをこの機能に基づいて設計すると、この機能を後に利用することがより簡単になります。

さらに、Dockerfile でボリュームを明示的に定義すると、イメージの利用者がイメージの実行時に定義する必要のあるボリュームがどれかを簡単に理解できるようになります。

OpenShift Online でのボリュームの使用方法についての詳細は、Kubernetes ドキュメントを参照してください。

注記

永続ボリュームでも、イメージの各インスタンスには独自のボリュームがあり、ファイルシステムはインスタンス間で共有されません。つまり、ボリュームを使用してクラスターの状態を共有できません。

外部のガイドライン

他のガイドラインについては、以下の資料を参照してください。