Docker が Docker 内で実行できるようになりました

ドッカーミーム

Docker 0.6の(多くの)機能の1つは、コンテナの新しい「特権」モードです。 これにより、カーネル機能とデバイスアクセスに関して、ホストマシンの(ほぼ)すべての機能を備えたいくつかのコンテナを実行できます。

「特権」モードの(多くの)可能性の中で、Docker自体の中でDockerを実行できるようになりました。 まず、それを実現する方法を見ていきます。次に、内部で何が関係しているかを説明し、最後に、DockerでDockerよりもさらに強力なものを示します。

Docker-in-Docker の動作を参照してください

Docker 0.6をお持ちの場合は、次のことを行う必要があります。

docker run -privileged -t -i jpetazzo/dind

これにより、特別なDockerイメージがダウンロードされ(なぜ特別なのかは後でわかります)、新しい特権モードで実行されます。 デフォルトでは、ローカル docker デーモンを実行し、シェルにドロップします。 そのシェルで、古典的な「Docker 101」コマンドを試してみましょう。

docker run -t -i ubuntu bash

Docker を実行しているコンテナーから最も内側のコンテナーに移行するときに、コンテナー ID がどのように変化するかに注意してください。

私の dind イメージで何が特別なのですか?

ほとんど何もありません! これは、通常の Dockerfile で構築されています。 そのドッカーファイルに何が入っているか見てみましょう。

まず、いくつかのパッケージをインストールします: lxc および iptables (Dockerがそれらを必要とするため)、および(Dockerインデックスおよび ca-certificates レジストリと通信するときに、DockerはSSL証明書を検証する必要があるため)。

Dockerfile は、ボリューム /var/lib/docker である必要があることも示しています。 コンテナのファイルシステムは複数の ブランチで構成されるAUFSマウントポイントであるため、これは重要です。そして、それらのブランチは「通常の」ファイルシステムでなければなりません(つまり、 AUFS マウントポイントではありません)。 つまり、 /var/lib/dockerDocker がコンテナーを格納する場所は、AUFS ファイルシステムにすることはできません。 そのため、このパスを ボリュームにする必要があることを Docker に指示します。 ボリュームには多くの目的がありますが、このシナリオでは、ホストマシンの「通常の」ファイルシステムへのパススルーとして使用します。 入れ子になった Docker のディレクトリは /var/lib/docker 、ホスト システムのどこかに /var/lib/docker/volumes 存在します。

そしてもちろん、DockerfileはDockerバイナリと ヘルパースクリプトをイメージに挿入します。 ヘルパースクリプトは3つのことを扱います。

  1. これにより、cgroup 擬似ファイルシステムが適切にマウントされます (Docker (より正確には lxc-start) がそれらを必要とするためです。
  2. 親プロセスからリークされた可能性のある無関係なファイル記述子を閉じます。 これは厳密には必要ではありませんが、そうしないと奇妙な副作用に気付くかもしれません。だから私はあなたのためにそれを世話しました。
  3. コマンドラインオプションで環境変数 -e PORT=... を指定した PORT かどうかをチェックします。その場合、Docker デーモンはフォアグラウンドで起動し、指定された TCP ポートで API 要求をリッスンします。 変数を指定し PORT なかった場合は、バックグラウンドで Docker が起動し、対話型シェルが表示されます。

次のセクションでは、この PORT 環境変数 が非常に 役立つと思う理由を説明します。

サービスとしてのドッカー

Docker-in-Docker を試してみたいだけの場合は、上記のようにイメージを対話形式で開始するだけです。 ここで、サービスとしての Docker を提供するとしましょう。ここではサービスとしてのコンテナについて話しているのではなく、Dockerインスタンス全体について話しているのです。 まあ、誰かが自分のプライベートDockerインスタンスを望むたびに、これを実行するだけです:

docker run -privileged -d -p 1234 -e PORT=1234 jpetazzo/dind

docker inspect 次に、を使用して、そのコンテナーに割り当てられたパブリック ポートを取得し、ユーザーに提供します。彼らは、Dockerクライアントをあなたが与えたIPアドレスとポートにポイントすることで、この「プライベートDocker」上にコンテナを作成できます。 (同様の例については、 サービスとしての Memcached を参照してください)。

ただし、プライベートDockerインスタンスは特権モードで実行されるため、ホストに簡単にエスカレートできるため、おそらくこれは望ましくありません。 本当にこのようなものを実行して公開したい場合は、LXCテンプレートファイルを微調整して、Dockerインスタンスで使用できる機能とデバイスを制限する必要があります。 将来的には、Docker ではきめ細かなアクセス許可管理が可能になります。しかし今のところ、「ロックダウン」と「特権」を切り替える機能は素晴らしい第一歩だと思います。

Docker-in-Docker-in-Docker-in...

ソニーDSC

Docker-in-Docker-in-Dockerを実行できますか?はい。 特権コンテナー内にいる場合は、いつでももう 1 つのレベルをネストできます。

docker run -t -i -privileged jpetazzo/dind

そして、結果のコンテナで、プロセス、 アドリブを繰り返すことができます。

また、ネストされたDockerコンテナを終了すると、これが起こります(ルートプロンプトに注意してください)。

root@975423921ac5:/# 終了
root@6b2ae8bf2f10:/# 終了
root@419a67dfdf27:/# 終了
root@bc9f450caf22:/# 終了
jpetazzo@tarrasque:~/Work/DOTCLOUD/dind$

その時点で、回転するコマを回転させながら、スピーカーでハンス・ジマーの 夢が崩壊 しているのを😀爆破する必要があります

それは動作しません!

さまざまな環境でDocker-in-Dockerをテストしているときに、2つの考えられる問題が見つかりました。

LXC ツールは、デバイスコントロールグループが独自の階層にない場合、ネストされたコンテナを起動できないようです。 の内容 /proc/1/cgroupを確認してください:それ自体でラインに立っている場合 devices は、問題ありません。 別のコントロールグループが同じ行にある場合、Docker-in-Docker は機能しません。 ラッパー スクリプトはこの状況を検出し、警告を発行します。 この問題を回避するには、実行中のすべてのコンテナーを停止し、すべてのコントロール グループをアンマウントして、それぞれ独自の階層に 1 つずつ再マウントする必要があります。

また、AppArmor を使用する場合は、入れ子になったコンテナーをサポートするための特別なポリシーが必要です。 Docker-in-Docker が機能しない場合は、カーネル ログ ( と dmesg) を確認し、AppArmor に関連するメッセージが表示された場合は、次のように制限のないモードで Docker を起動できます。

docker run -privileged -lxc-conf="aa_profile=unconfined" -t -i dind

私をあなたのリポジトリに連れて行ってください

Dockerfile、ラッパー、およびいくつかの追加のドキュメントは、私のgithubリポジトリで入手できます。 https://github.com/jpetazzo/dind

 

ジェローム・ペタッツォーニについて

サム

JérômeはdotCloudのシニアエンジニアであり、運用、サポート、エバンジェリストの職務をローテーションし、「マスターヨーダ」のニックネームを獲得しています。 前世では、EC2が 単なる飛行機の名前だった頃に大規模なXenホスティングを構築および運用し、フランスの地下鉄を介したファイバー相互接続の展開を監督し、ファイバーインフラストラクチャを視覚化するための特殊なGISを構築し、会議センターなどの帯域幅に制約のある環境での大規模なコンピューターシステムのコマンドー展開に特化しました。 彼はdotCloudを動かすサーバーを気にかけ、ユーザーがプラットフォームに慣れるのを助け、記事、チュートリアル、サンプルアプリケーションでdotCloudを使用する多くの方法を文書化しています。 彼はまた、dotCloudにほぼすべてのものをデプロイした熱心なdotCloudパワーユーザーでもあり、Githubリポジトリで彼の多くのカスタムサービスの1つを探してください。

ツイッターでジェロームとつながりましょう! @jpetazzo