web-dev-qa-db-ja.com

Dockerはどのようにして異なるカーネルでディストリビューションを実行できますか?

コンテナ内のOpenSUSEなどのDebianホストでdockerを実行するにはどうすればよいですか?別々のモジュールで異なるカーネルを使用します。また、古いDebianバージョンは古いカーネルを使用しているため、カーネルバージョン3.10以降でどのように実行できますか?古いカーネルには古い組み込み関数しかありませんが、古いディストリビューションはどのようにして新機能を管理できますか?その「トリック」とは何ですか?

37
plaidshirt

コンテナ内のOpenSUSEなどのDebianホストでdockerを実行する方法

カーネルは同じであり、すべてのコンテナイメージを実行するDockerエンジンをサポートするため:ホストカーネルは3.10以上である必要がありますが、その システムコールのリスト はかなり安定しています。

Architecting Containers:Why User Space vs.Kernel Space Matters 」を参照してください:

  1. アプリケーションにはビジネスロジックが含まれていますが、システムコールに依存しています。
  2. アプリケーションがコンパイルされると、アプリケーションが使用する(つまり依存する)システムコールのセットは、バイナリに埋め込まれます(高レベル言語では、これはインタープリターまたはJVMです)。
  3. コンテナは、ユーザー空間とカーネル空間がシステムコールの共通セットを共有する必要性を抽象化しません。
  4. コンテナ化された世界では、このユーザースペースは束ねられ、ラップトップから本番サーバーまでのさまざまなホストに出荷されます。
  5. 今後数年間で、これは課題を作成します。

https://rhelblog.files.wordpress.com/2015/07/user-space-vs-kernel-space-simple-container.png?w=584&h=231

時々、新しいシステムコールが追加され、古いシステムコールは廃止されます。これは、コンテナインフラストラクチャとその中で実行されるアプリケーションのライフサイクルについて考えるときに考慮する必要があります。

なぜカーネルバージョンがDockerコンテナのUbuntuバージョンと一致しないのですか?

コンテナ内にカーネルはありません。カーネルをインストールしても、コンテナの起動時にカーネルはロードされません。コンテナのまさに目的は、新しいカーネルを実行することなくプロセスを分離することです。

35
VonC

Dockerは決して異なるカーネルを使用しません。カーネルは常にホストカーネルです。

ホストカーネルが、実行するコンテナ内のソフトウェアと「十分に互換性がある」場合、動作します。それ以外の場合はできません。

「コンテナ」は単なるプロセス構成です

理解しておくべき重要なことは、Dockerコンテナーはnot仮想マシンであることです。ソフトウェアを実行する新しい仮想コンピューターは作成されません。代わりに、Dockerは、コマンドラインからプロセスを開始するのと同じように、既存のOSでプロセスを実行するだけです。

コンテナ化されたプロセスと通常のプロセスの違いは、コンテナ化されたプロセスに課せられた制限と、その周囲の環境を見る方法の変更です。 (これらは、コンテナ化されたプロセスによって開始されたすべての子プロセスに渡されます。)典型的な制限と変更は次のとおりです。

  • ホストのルートファイルシステムを使用する代わりに、/(通常はコンテナのイメージで提供されるもの)に別のファイルシステムをマウントします。ホストファイルシステムの一部は、新しいプロセスのルートファイルシステムの下にマウントできます。 docker run -v /u/myprogram-data:/var/data/myprogramを使用して、コンテナ化されたプロセスが/var/data/myprogram/fileを読み書きするときに、ホストファイルシステムで/u/myprogram-data/fileを読み書きします。
  • コンテナ化されたプロセス用に別のプロセススペースを作成し、それ自体とその子のみを(psまたは同様のコマンドを使用して)表示できるが、ホストで実行中の他のプロセスは表示できないようにします。
  • コンテナ内のユーザーがホスト内のユーザーと異なるように、個別のユーザー名前空間を作成します。たとえば、コンテナ化されたプロセスのUID 1234は、コンテナ化されていない場合のUID 1234と同じではありません
  • 多くの場合、「仮想ルーター」とそれらとホストネットワークインターフェイス間のアドレス変換を使用して、独自のIPアドレスでネットワークインターフェイスの別のセットを作成します。 (たとえば、ホストは、ポート8080でパケットを受信すると、コンテナプロセスの仮想ネットワークインターフェイスのポート80にパケットを転送します。)

これらはすべて、カーネルに組み込まれた機能によって実行されます。適切なセットアップを行い、新しいプロセスを開始するときに適切なパラメーターを設定するプログラムを作成すれば、Dockerを使用せずに自分で行うことができます。

互換性

では、「互換性が十分」とはどういう意味ですか?それは、プログラムがカーネルに要求するもの(システムコール)と、カーネルがサポートすることを期待する機能に依存します。一部のプログラムは、物事を壊すような要求を行います。他の人はしません。たとえば、Ubuntu 18.04(カーネル4.19)または同様のホスト:

  • docker run centos:7 bashは正常に動作します。
  • docker run centos:6 bashは終了コード139で失敗します。これは、セグメンテーション違反信号で終了したことを意味します。これは、4.19カーネルがbashのビルドが実行しようとしたことをサポートしていないためです。
  • docker run centos:6 lsは正常に機能します。これは、bashがそうであったように、カーネルが処理できない要求を行っていないためです。

古いカーネル、たとえば4.9以前でdocker run centos:6 bashを試すと、正常に動作することがわかります。 (少なくとも私がテストした限りでは。)

9
Curt J. Sampson