【ざっくり理解】Dockerの使い方まとめ【コンテナ運用入門】

【ざっくり理解】Docker について【初心者向け】

Dockerは便利なので本当におススメです。 Dockerコマンドに適切なオプションを追加して実行すると 簡単に隔離環境を用意できます。 Dockerfileを利用すれば、環境の共有や複製も簡単です。

ただしそれだけに、脆弱性を放置したまま使用していると、 ホストの乗っ取りや改ざんなどの攻撃に遭いかねません。 本記事では、そのようなトラブルを防ぐために、 Dockerの安全な利用方法を解説します。

まずはDockerの概要やしくみをあらためて紹介し、 セキュアなDockerイメージの扱い方と、 安全なコンテナ運用手法を取り上げます。 この機会に「強い」Docker環境を目指しましょう!  

 

【1】Dackerとは? コンテナとは?定義を振り返る

【Dockerとコンテナの基本を 総復習しよう】

Dockerへの理解を深めるには、その根底を支えるコンテナ技術を知る必要があります。 そこで突き当たるのが「コンテナとは何か?」という疑問でしょう。 本章ではDockerの設計思想やLinux技術との関係性を学びつつ、 「Docker」「コンテナ」がそれぞれ何を指していて、 どう区別すればよいのかを明らかにします。

【概要】 さまざまなクラウド環境上で、ベンダーロックインされることなくスケーラブルなアプリケーションを 構築・実行するクラウドネイティブ21と総称される技術が広まりつつあります。 CNCFは、アプリケーションをクラウドネイティブに対応させる第一歩として、「コンテナ化」を挙げています2。

アプリケーションを「コンテナ」と呼ばれる最小単位で扱うためのしくみとして、Dockerは開発されました。 今日ではLinuxサーバ上だけでなく、個人が持つPC上でも、Dockerを利用できる環境が整っています。 また、2021年5月に行われたStackOverflowの調査注3では、この1年間で開発者の55.06%がDockerを使用したと回答しました。 このようにDockerは広く利用されています。

ところで、Dockerが扱うコンテナとはいったい何を指すのでしょうか。 本章はコンテナの基本的な概念と、それを扱うDockerの役割について理解を深めます。

*1) Linux Foundation傘下の業界団体で、コンテナ関連のOSS支援や企りの時期格定などを行う CNCF(Cloud NativeComputing Foundation)は、クラウドネイティブ を次のように定義しています。
▶ DEFINITION.md

*2) CNCFが発行した「Cloud Native Trail Map」の第一段階がContainerlization(コンテナ化)です。
▶ trailmap

*3) ▶ insights.stackoverflow.com
mostpopular-technologies-tools-tech-prof

Dockerの概要

Dockerとはアプリケーションを開発・共有・実行するためのツールであり、プラットフォームです。 Dockerコンテナを使って開発したアプリケーションは、開発環境で完成された状態のまま、 さまざまな場所にデプロイ可能であり、ローカルPCやクラウドのサーバ上で実行できます。

この「コンテナ」は、私達の実社会における物流を支える「輸送コンテナ」にヒントを得て開発されました。 Dockerが登場した背景を理解すれば、Dockerコンテナの使いどころを検討するうえで役立つでしょう。

Docker登場の背景と解決したかった課題

昨今の開発では、開発の段階に応じてさまざまな環境でアプリケーションを実行します。 たとえば、開発はローカルのPC上で行い、 そこからテスト環境やステージング環境、 社内の共有環境へと移して実行することになります。 最終的にプロダクション環境ではクラウドやデータセンターで動作させることになるでしょう。

このように環境が変わったとしても、 間違いなくアプリケーションを実行できる動作環境があれば理想です。 しかし現実にはLinuxディストリビューションだけでなく、開発環境やミドルウェアの初期状態、バージョンなどが異なってきます。

動作環境の変化が前提となれば、環境ごとの差異をなくすための取り組みが必要です。 伝統的な解決方法としては、設定手順書の作成が挙げられるでしょう。

あるいは、Ansibleに代表されるような構成管理ツール(ConfigurationManagementTool)を使い、 環境をコード化(抽象化)する方法があります。

また、環境によっては、仮想マシンイメージをテンプレートのように扱い、 環境ごとの差異を生み出さなくする工夫もあります。

しかし、ローカルで開発したアプリケーションをデプロイ先で確実に実行するためには、 設定ファイルの管理や運用をどうするかといった、 本来の開発とは異なる時間的なコストや手間がかかる課題がありました。

しかも、これらの課題を解決しても、確実にアプリケーションが動作する保証はなかったのです。 アプリケーションをすばやく開発してクラウドへデプロイしたいだけなのに、 本質的ではない課題に四苦八苦している。

このような開発者の苦痛を耳にしたのが、Dockerを開発したdotCloud(現Docker社)の人々でした。 dotCloudは当時、PaaS(PlatformasaService)として、 頭客のアプリケーションをクラウド上にデプロイできるサービスを提供していました。

顧客へのヒアリングで見えてきた上記の問題を解決すべく、Dockerは開発されました。Dockerが実現したのは、次の点です。

  • アプリケーションを実行するために必要なすべてを「Dockerイメージ」に入れられる
  • 「Dockerイメージ」に含むアプリケーションを、「Dockerコンテナ」として実行できる
  • 「Dockerコンテナ」は、マシン上のほかのプロセスやコンテナの影響を受けず実行できる
  • 「Dockerイメージ」は、ほかのコンピュータに移動できる

当時のLinuxカーネルに導入が目指されていたLXCを使い、 Dockerコンテナと呼ぶ単位で、 アプリケーションを簡単なコマンドで操作可能にしました。

さらに、独自に開発したDockerイメージで、 アプリケーションのパッケージ化や環境間の移動を簡単にできるようにしたのです。

アプリケーションの実行に必要なものがすべてDockerイメージに入っていますので、 環境を問わずアプリケーションを実行できるようになりました(図1)。

このDockerが初めて発表されたのは、 2013年3月に開催されたPyConUS2013のライトニングトークでした。

その後、同年8月にDockerのソースコードがGitHub上でオープンソース(ApacheLicense2.0)として公開されると、 誰もがDockerを利用できる状態となり、コンテナを活用した開発の機運が高まり始めます。

注4)「The Future of Linux Containers/
▶ 参考動画

輸送コンテナからヒントを得たDocker

輸送コンテナでは、積み荷が何であろうとも、中身を気にせず輸送できます。 しかも、世界共通のISO規格があるため、輸送手段が船、鉄道、飛行機、 トラックのように途中で変わったとしても影響がありません(図2左)。

このように輸送コンテナが普及したおかげで、 さまざまな物資を世界中へ輸送できるようになりました。

世界の経済をけん引した輸送コンテナこそ、 20世紀最大の発明の1つと言われています。

輸送コンテナで移動する物資のように、 アプリケーションをどこでもデプロイできることを目指したのがDockerです。

Dockerはコンテナの中でアプリケーションを実行します。 このDockerコンテナの基になるのが、Dockerイメージです。

Dockerイメージとは、tarアーカイブに含む複数のファイルやディレクトリを、 あたかも1つのファイルのように扱う抽象的な概念です。

この中に、ソースコード、バイナリファイル、設定ファイルやライブラリ群などを入れられます(図2右)。 すなわち、Dockerコンテナとして実行すべきものをDockerイメージにさえ入れておけば、 さまざまな環境にアプリケーションを移動できます。

ローカル環境で作成したアプリケーションも、 テスト環境やクラウドをはじめとしたさまざまな環境で実行できます。

「Build,Share,Run」のプラットフォームがDocker

Dockerイメージは、その中にアプリケーションを動かすために 最小限かつ必要なすべての依存関係を保持しています。 つまり、Dockerイメージさえあれば、 Dockerコンテナとしてソフトウェアをどこでも簡単に実行できます。 このDockerイメージを送る先がDockerHubまであり、 これがDockerエコシステムの中心に位置します。

GitHubがソースコードを共有したり、 開発体験をコラボレーションしたりするための場所であるのと同じように、 DockerHubはDockerイメージを共有したり、 コラボレーションしたりするための各種機能を提供しています。

ちなみに、Dockerは当初「Build,Ship.Run」をスローガンに掲げていました。 これは、アプリケーションを単に構築、移動、実行するプラットフォームを目指したものでした。 このスローガンは、現在では「Ship」が「Share」へと変わっています。

単純にアプリケーションのポータビリティや再現性を高めるだけでなく、 Dockerイメージを共有することによるDockerHubでの活用体験やコラボレーション、 CI/CDのしやすさを意識したものです(図3)。

*5)マルク・レビンソン著、村井章子訳、「コンテナ物語世界を変えたのは「箱」の発売だった、日経BP社、2007年
▶ nikkeibp.co.jp

*6) ▶ https://hub.docker.com/

重要なのは、Dockerはコンテナを指すのではなく、 プラットフォーム全体を指すという点です。 アプリケーションを扱う手段として、Dockerはコンテナ化を利用しています。

Docker社の手を離れ、現在に至るまで

Dockerプラットフォームの中心的な概念が、DockerコンテナとDockerイメージです。 現在、DockerEngineと呼ばれる中心的なプログラムやその周辺ライブラリは、 開発の初期からオープンソース化されていました。とはいえ、 初期の実質的なコミッターは、 Docker社の創設者兼CTOのSolomonHykes氏や、 Docker社のメンバーが中心でした。

後にDocker社は、 コンテナを管理するコアのプログラム(ランタイム)であるlibcontainerの名称をruneへと変更し、 OCI(OpenContainerInitiative)に、 このコンテナランタイムを寄贈しています。

また、コンテナの仕様に関する情報も開示したため、 開発者はDockerに限らず、用途に応じてrtやCRI-Oのように さまざまなコンテナランタイムへの代替ができ るようになりました。 さらに、Dockerプログラム全体として、 デーモンにあたる部分をDocker Engineとして、 そのコア部分をMobyという名称で完全にオープンソース化しました。

それからDocker社は、Kubernetesなどが扱うコンテナのオーケストレーションの実装にも 一時的に取り組みますが、現在は機能を分離 しています。 Docker Swarmを中心とするDocker Enterpriseのオーケストレーション対応プロダクト評は、 Mirantis社に買収されました。

2021年時点のDocker社は、再び開発者志向 にフォーカスしなおし、 Docker Engineの安定 化だけでなく、 Docker Hubの機能強化に注力しています。 また、DockerDesktopの開発によるWindowsやmacOSでも、 デスクトップ環境上での開発体験向上に取り組んでいます。

Dockerのエコシステムとアーキテクチャ

Dockerをとりまくエコシステム(図4)の中 でも重要な役割を担うのが、 Docker EngineとDocker Hubです。

Docker Engine Docker Hub

通常の開発や運用において、「Dockerを使う」という言葉が指し示すのは、 Linux上で動作するDockerEngineというデーモンで、アプリケーションを扱うことです。

このDockerEngineが、Linuxカーネルを制御し、 アプリケーションをコンテナとして扱えるようにしています。

DockerEngineを操作するコマンドラインツールもdockerという名称です。 ちなみに、リリース初期はDockerEngineとは呼ばず、 dockerという名前のバイナリが、 コマンドラインのツールであるクライアントとしても、 Linuxカーネルと通信してプロセスを制御するサーバとしても動作するものでした。

DockerEngineはDockerイメージを使ってアプリケーションを実行したり、 ほかのサーバやPCに移動できるポータビリティを確保したりします。

Dockerイメージを共有するにあたって中心的な役割を担うのが、DockerHubです。 DockerHubはdockerコマンドで操作できる、 標準のレジストリ(Dockerイメージを保管するネットワーク上のプログラム)です。 さまざまなDocker公式イメージが配布されているだけでなく、 自分で任意のイメージを公開し、世界中の人と共有できます。 なお、Dockerイメージのレジストリはローカルに自分で構築・運用することもできますが、 DockerHubはローカルではなくインターネット上に共有されるバブリック・レジストリです。

*7) Linux Foundation が監督する東京中立団体として2015年に設立されました。

Dockerのプラットフォームと関連用語

Dockerのおもな用語と、周辺のツールを説明します。

Dockerコンテナ

Linux上の特別な状態のプロセスであり、 いわゆるコンテナとして起動するアプリケーション(実体はプロセス)です。 Dockerコンテナの実行にはDockerEngineが必要です。

Dockerイメージ

Dockerコンテナを起動する際に必要となる、 ファイルシステムとメタ情報を含む抽象的な概念です。 Dockerイメージは、ISOイメージファイルのような単一のファイルではありません。 Dockerが動作するホスト上にある複数のファイルやディレクトリを、 Dockerコンテナ内からは1つのファイルシステムとして見えるように扱う、抽象的な単位です。 DockerHubまたはプライベートなリポジトリと、 DockerEngineとの間でDockerイメージの送受信が可能です。

Dockerネットワーク

Dockerコンテナの相互通信や、 コンテナの外部との通信時に利用するLANのような内部ネットワークを、 Dockerネットワークと呼びます。

Dockerコンテナ内から認識できる、ネットワークインターフェースやルーティングの情報は、 ホスト上から隔離されています。 詳細は第2章で後述します。

Dockerボリューム

コンテナ問や、コンテナとホストの間で、 ファイルやディレクトリを共有できる場所です。 DockerコンテナやDockerイメージのファイルシステムとは独立しています。 詳細は第2章で後述します。

DockerEngine

Dockerのサーバ機能を担うプログラムやライブラリ科(dockerd、containerd、rune)で構成されます。 dockerdはCLIからの命令を受け付けるAPIエンドポイントを持ちます。 また、containerdは内部でのAPI処理を行い、runcのようなコンテナランタイムに委ねます。 runcはデフォルトのコンテナランタイムで、Linuxカーネルの機能を利用します。 このときDockerEngineは、DockerHubのようなレジストリから、ローカルにDockerイメージをダウンロードし、Dockerコンテナとして実行します。 通常、DockerEngineがデーモンとして起動していないと、dockerコマンドを実行しても操作できません。

DockerCLI

dockerrundockerbuildadockerから始まるコマンド群で構成されるCLIツールです。 DockerEngineに対してコンテナやイメージを操作する命令を送信します。

DockerHub

Dockerイメージを共有・配布したり、コラボレーションしたりするためのインターネット上のレジストリです。 公式イメージも配布されているほか、自分のイメージを公開する機能もあります。 GitHubやBitbucketと連携したイメージの自動構築機能も提供しています。

DockerCompose

DockerCLIの1つです。 複数のDockerコンテナアプリケーションや、Dockerネットワーク、 Dockerボリュームをプロジェクトと呼ぶ単位で管理します。 また、YAML形式のファイル単位でプロジェクトを管理できます。

DockerDesktop

WindowsteltmacOSETDockerEngineやDockerComposeに 専用のデスクトップ・アプリケーションを加えてパッケージ化したものです。 開発用のPC上でDockerを簡単に利用できるよう、 各OSの仮想化機能を使い、 開発者は仮想的なLinuxの環境を意識する必要がありません。 通常のOS環境でDockerをシームレスに利用するためのツールです。 2021年9月から提供ポリシーが変更となり、 大規模事業者での利用は有償化されています(移行期間は2022年1月末まで)。

DockerToolbox

DockerComposeをパッケージ化したアプリケーションです。 VirtualBoxと連携し、 DockerEngineを軽量Linux(TinyCoreLinux)上の仮想マシンで動かしています。 DockerDesktopが登場するまでに開発は終了しており、現在は非推奨です。

PlaywithDocker(PWD)

無料でDockerをインターネット上で利用可能なサンドボックス環境です。 サーバの稼働時間に時間制限があったり、 データの保存ができなかったりといった制約もありますが、 コンテナ外部のインターネットと通信が疎通しているため、 Dockerの勉強には最適です。 利用にはDockerHubのアカウントが必要です。

Dockerコンテナとは何なのか?

Dockerを理解するうえで欠かせないのは「コンテナ」と「Docker」に対する適切な区別です。 とくに、「コンテナとは何か」という定義や、 「Dockerコンテナ」と「Dockerイメージ」の関係性についての理解は欠かせません。 これまで説明したとおり、Dockerとはアプリケーションをコンテナとして扱うためのツールであり、 プラットフォーム全体を指します。 Dockerコンテナとは、仮想化技術ではありません。 OCIが定めるコンテナ標準に則り、Linux上のプロセスを特別な状態で実行できるようにする技術です。

特別な状態とは、 Dockerでは「isolate」(隔離) と呼ばれるものです。 隔離とは、 プロセスのPID だけでなく、 アプリケーション全体を動かすた めのファイルシステムやネットワークも含みま す。 複数の技術を組み合わせて「Dockerコンテ ナ」として実行できるようにしています(図5)。

*8) https://www.docker.com/play-with-docker

コンテナとは、

Dockerとは コンテナとは、 Linuxカーネルが提供するプ ロセスの隔離「機能」です。 Linuxカーネル内 部の機能を用いているので、 Dockerを使わな くても今日の「コンテナ」のようにプロセスを 扱えます。 コンテナは、 プロセスを「隔離」さ れた特別な状態として起動します(詳細は 「Dockerを支えるLinuxカーネル機能の紹介」 節で後述)。

コンテナの実装にはさまざまな種類や歴史的 な経緯があり、 1979年にUNIXで実装された chroot システムコールに由来しています。 chrootは、プロセスから見えるファイルシステ ムを制限します。 その後、2000年にはFree BSD 4.0でchroot を拡張したjailコマンドが導 入されます。 2004年にはSolaris 10でSolaris コンテナ(後のSolarisゾーン)がリリースされ ました。 そして、Linuxでも2008年にLinux コンテナ(LXC)としてLinux kernel 2.6.24が登場します。 初期のDockerは、このLXCをデ フォルトのバックエンドとして採用していまし た。

Dockerは、これらコンテナの状態を操作し、 管理するために、DockerコンテナやDockerイ メージといった「実装」を行っています。

たとえば、次のような機能が該当します。

  • docker コマンドでコンテナを操作する
  • DockerfileでDocker イメージを構築する
  • Docker Hubを通してイメージを共有する

つまり、汎用的な「コンテナ」と呼ばれるものを、 Dockerでは「アプリケーション」として隔離し、 アプリケーションが実際に必要とするファイルやディレクトリを、 Dockerイメージ と呼ばれる単位でひとまとめに扱えるようにしたのが、 「Docker コンテナ」です。

コンテナという名前が付いていますが、 SolarisコンテナやLXCの概念とは異なります。

Dockerコンテナはほかのコンテナ技術とは (OCI準拠のものを除き)互換性がないため、 注意が必要です。

アプリケーションコンテナとシステムコンテナ

「Cloud Native Infrastructure」注3の分類では、コンテナには2つの区分があります。

*9) Justin Garrison, Kris Nova, Cloud Native Infrastructure,O'Reilly Media, Inc., 2017

アプリケーションコンテナ

DockerやKubernetesのような、クラウドネイティブなアプリケーション開発・運用を意図したものです。 アプリケーションをすばやく開発・デプロイしたり、 マイクロサービスのような味結合のシステムをクラウド上でスケールアップ/スケールダウンしたりするために用いられます。 このための考え方が、「1つのコンテナに1つの機能を持たせる」というものですまい。

数十台~数百台以上ものノードを持つクラスタ上で、それらインフラを意識することなく、 クラウドネイティブなアプリケーション開発・運用を行うために適しているのがこのアプリケーションコンテナという考え方です。

システムコンテナ

通常のサーバのように、init以下のプロセスツリーで、 複数のアプリケーションが1つのコンテナの中で扱えることを意図しています。

前述のとおり、Dockerは仮想化技術ではありません。 確かに、Dockerを仮想サーバのように、 あえてシステムコンテナ的な利用もできないわけではありません。 しかし、結果的にアプリケーションがスケールできなかったり、 扱いづらくなったり、さらに通常のサーバと同じような運用ができなくなったりするため、 現実的ではありません。

また、Dockerはアプリケーションコンテナとしての実行を意図して開発されています。 技術的にはシステムコンテナのような利用も可能ですが、 仮想サーバとは考え方やしくみが違うため、 かえって環境構築や運用に手間がかかったり、 意図せぬセキュリティリスクを生みかねません。 あくまでもDockerはLinuxカーネルの機能を使い、 システムから一部の機能を目隠しして動かしているようなものです。 また、DockerコンテナやDockerイメージの運用は、 通常のサーバと表面的には同じように感じられるかもしれませんが、 そもそもの運用フローが異なりますので、 Dockerを熟知していない段階で通常のサーバ上でアプリケーションを動かすのと同じようにセットアップするのは危険と言えるでしょう。

Dockerが登場した直後は、 このような思い違いによる導入時・導入後のトラブルが散見されました。 用途や目的に応じて、技術を選択すべきです。

*10)1つのコンテナに1つのプロセスと解されていることもありますが、正には1つのコンテナに1つの機能です。

DockerとホストOSの関係

Dockerは見かけ上の機能から仮想化技術と比較されることも多いのですが、 これまで見てきたとおり、 解決したい課題や使いどころは異なります。 Dockerがコンテナを扱えるのは、 仮想化技術によるものではなく、 Linuxカーネルの機能や、 さまざまな技術の組み合わせによるものです。

Dockerを支えるLinuxカーネル機能の紹介

Linux上でのコンテナ実装には、 いくつかの種類があります。 Dockerの場合は、 Dockerコンテナとして隔てられた環境内でアプリケーションを実行するために、 namespace,cgroup、 capabilityといった、 いくつかのLinuxカーネル機能を使います。

通常、 Linux上で起動するプロセスとは、 ホスト上のすべてのプロセスが見え、 権限を持つファイルやディレクトリに対してアクセス可能なものです。 これをLinuxカーネルの機能を使うことで、 Dockerを通して起動するプロセスしか存在しないプロセス空間を作成できます。 さらに、 そのプロセス空間が、 特定のホスト上のディレクトリでchrootを行ったかのように起動します。 結果として、 いわゆる「コンテナ」と呼ぶプロセス空間やファイルシステムだけでなく、 ネットワークなども隔離した、 特別なプロセスが実行できます。 この特別なプロセスを

「Dockerコンテナ」と呼びます。 また、 Dockerコンテナから見えるファイルシステムを構成するのが、 Dockerイメージと呼ぶ抽象的なファイルシステムです。 そのファイルシステムとホスト上のファイルやディレクトリの実体と結び付けるのがaufsドライバです。

ここからは、 コンテナを支える代表的なLinuxカーネルの機能を見ていきます。

namespace(名前空間、

ネームスペース) Dockerコンテナで、 アプリケーションがisolate(隔離)された状態を作り出すのに欠かせない要素が、 namespaceです。 Dockerは次のnamespaceを操作します。

  • PID名前空間:実行中のプロセスが存在するプロセス空間を分離
  • Mount名前空間:chrootやjailのように、マウントした一部のディレクトリ以下しかアクセスできないように分離
  • UTS(UnixTimesharingSystem)名前空間:コンテナ内のホスト名、ドメイン名を分離
  • IPC名前空間;ホスト上のプロセス間通信(SystemVIPC、POSIXメッセージキューシステム)を制御することで、メモリ空問へのアクセスを分離」
  • User名前空間:UID/GIDがホスト上のものと対応しないように分離・Network名前空間:ネットワークを分離

cgroup(コントロールグループ、シーグループ)

cgroupは、 初期はcontrolgroupと呼ばれていました。 2007年のLinux2.6.24のドキュメントは11では「amechanismforaggregating/partitioningsetsoftasks,andalltheirfuturechildren,intohierarchicalgroupswithspecializedbehaviorあり、 今のコンテナの概念の元祖となる定義がなされています。

*11)▶ kernel.org
v1/cgroups.txt

cgroupの機能を使うと、 たとえば次のようなことができます。

  • 名前空間を分離する
  • 同じ名前空間内に存在するプロセスが、同じシステム上の制限を継承できるようにする

なお、 後者は特別な権限(capability、 後述)を持つプロセスをコンテナ内でのPID1として扱うことで実現されます。

cgroupの機能が活きるのは、 システム上のCPU、 メモリ、 ディスクI/Oのリソース制限です。

capability(ケーパビリティ)

Dockerコンテナに特権を与えたり、 制限したりといった制御を行うのがcapabilityの割り当てです。 dockerrunのデフォルトで、 あらかじめ決められたcapabilityが与えられます(オプションを付けると、 privilegedコンテナと呼ぶ、 rootと同等の権限を持つ状態でも起動できます)。 おもな権限はDockerのドキュメントをご覧ください。

コンテナの実行時、 デフォルトで適用できるcapabilityの特権には複数の種類があります。 必要に応じて、 それらの権限を与えないこともでき、 dockerrun実行時のオプションで指定します。 詳細はコマンドリファレンスのドキュメントは12をご覧ください。

aufsドライバ

Dockerコンテナの隔離されたプロセス空間から見えるファイルシステムは、 Dockerのストレージドライバを通して擬似的に作られています。 実体としては、ホスト上にばらけている複数のディレクトリやファイルを、 1つのファイルシステムとして見せる技術であり、 UnionFileSystem(UFS)13ファイルシステムを実装するためのものです。 Dockerの開発当初は、これらを実現するバックエンドとしてaufsやDevicemaperがありました。 現在では、よりパフォーマンスが高いoverlay2fsドライバが標準です。

*12) ▶ docs.docker.com
runtime-privilege-and-linux-capabilities *13)あるディレクトリ階層の上にほかのディレクトリを重ね合わせることで、1つの仮想的なディレクトリ (ファ イルシステム)として扱えるしくみのこと。

chrootでコンテナのしくみを学ぶ

コンテナの概要を学んだあとは、 Linux環境上でコンテナ状態のプロセスを起動してみましょう。 Dockerコンテナの理解を深めるには、 chrootコマンドで雰囲気をつかむのが近道です。 chrootは、厳密にはdockerrunの挙動とは異なりますが、 コンテナの基本原理の理解に役立ちます。

では、Dockerを使わずに、 chrootを使ってPID名前空間とMount名前空間の隔離を試しましょう。 ここではAlpineLinuxという容量の小さなLinuxディストリビューションを使います。 まずユーザーのホームディレクトリ上でtarアーカイプを取得・展開したあと、 AlpineLinux用のディレクトリをファイルシステムのイルート)とし、 プロセス/bin/shを起動します(図6)。

sudochrootを実行したあと、 シェルのブロンプトが/#に変わります。 pwdコマンドとcatコマンドで、 Linuxディストリビューションの情報を確認してみましょう(図7)。

このように、chrootコマンドは、 指定したプロセス(今回は/bin/sh)がアクセスできるディレクトリを制限して起動できます。 ちなみにこのchrootのしくみは、 インターネット用に公開しているサービス(DNS、メール、Web)のセキュリティ対策向上を意図して導入が進んだという歴史があります。


▼図6 Alpine Linuxのインストールとchroot の実行
$ wget https://dl-cdn.alpinelinux.org/ alpine/latest-stable/releases/x86_64/12 alpine-ninirootfs-3.14.2-x86_64.tar.gz $ nkdir alpine && cd alpine $ tar xvfz ../alpine-minirootfs3.14.2-x86_64.tar.gz. $ sudo chroot /home/1-1-2/alpine /bin/sh

chrootによる隔離はあくまでも簡単な例です。 Dockerの場合は、 chrootで隔離できるPID名前空間やMount名前空間以外にもさまざまな離対象があります。 さらに、 Docker独自の実装としてDockerネットワークやDockerボリュームも利用できます。 また、 chrootの場合は実行に必要なファイルシステムを自分で準備する必要がありましたが、 Dockerの場合はDockerイメージと呼ぶ単位で扱えます。 このようなしくみのため、 コンテナとして実行するにはdockerコマンドを実行するだけで済みます。 このような実装になったのは、 Dockerが技術ありきではなく、 開発者がクラウド上へすばやく、 かつ確実にアプリケーションをデプロイする課題を解決したいという動機から開発が始まったからです。

まとめ

本章ではDockerの根底を支えるコンテナの概念について復習しました。 Dockerは輸送コンテナから着想を得て、 アプリケーションをさまざまなインフラ上で、 どこでも同じように移動・実行できることを目指して開発されました。 Dockerを支えるコンテナという概念は、 複数のLinux上の技術を組み合わせて実現されています。 そしてDockerは、 ビルド前のコンテナをDockerイメージという形で扱えるようにしたことで、 DockerEngineが動作する環境上でDockerコンテナを実行可能にしました。

このようにしてDockerコンテナ化したアプリケーションは、 動作環境が変わったとしても、 どこでも開発時の環境と同様に実行できるため、 開発効率や開発体験の向上に役立ちます。


▼図7 chroot後の操作
1 # pwd
/ # cat /etc/alpine-release 3.14.2 1 # cat /etc/issue Welcone to Alpine Linux 3.14 Kernel \r on an m (11)

>>【ざっくり理解】Dackerコンテナとは?【定義】

【2】効率的な開発環境を実現するしくみ

Dockerの裏側 ~コンテナとイメージを理解する

>>【ざっくり理解】Dockerのコンテナとイメージ

【3】作ってそのまま放置していませんか?

攻撃に強いコンテナイメージの 作り方/使い方

>>【作り方】攻撃に強いDockerコンテナイメージ

【4】コンテナ環境への音威を知り、 適切な設定を施そう

Dockerを安全に運用する

>>【環境構築】Dockerを安全に運用する方法