コンテナの開発と運用管理を実現する「Docker」とは
はじめに
コンテナは古くからある技術ですが、広く一般に普及したのは2013年の「Docker」の登場がきっかけです。それまでのコンテナは軽量な仮想環境としてレンタルサーバーやバーチャルプライベートサーバーなどのホスティングサービスで使用されていました。しかしDockerの登場以降、コンテナは開発ツールとして普及していきます。一体Dockerの登場によって何が起きたのでしょうか。今回は、Dockerはどのようなツールなのか、また、そのメリット・デメリットについて解説します。
Dockerとは
Dockerはコンテナを簡単に扱うためのツールであり、アプケーションを開発・配布・実行をするためのプラットフォームです。Dockerはアプリケーションの動作環境をコンテナ内に構築しアプリケーションをパッケージ化します。これによりアプリケーションはインフラストラクチャから切り離され、様々な環境へ移動し同じ方法で実行できます。
DockerはLinuxカーネルの機能でコンテナの分離を実現しています。具体的にはホスト上で実行されているプロセスをカーネルの「名前空間(Namespaces)」と呼ばれる機能を使用して、分離された環境で実行しているかのように見せています。Dockerを使用するとプロセスの分離を簡単に実現できます。
以下の例では、ubuntu:22.04のコンテナでsleepコマンドを実行しています。
$ docker run --rm -d ubuntu:22.04 sleep 100 7cb93f83191b833d2a8bd57d0c8640ac626b972b3746fd050f4be9befa0b0ca8 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7cb93f83191b ubuntu:22.04 "sleep 100" 3 seconds ago Up 2 seconds kind_wing
実行中のコンテナでpsコマンドを実行すると、先に実行していたsleepコマンドとpsコマンドの2つが確認できます。
$ docker exec kind_wing ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 11:51 ? 00:00:00 sleep 100 root 7 0 0 11:52 ? 00:00:00 ps -ef
ホスト側からプロセスを確認すると、コンテナで実行しているsleepのプロセスが確認できます。
$ pgrep -a sleep 11522 sleep 100
また、sleepコマンドがコンテナ上ではPID 1で実行されている点にも注目してください。Dockerが扱うコンテナは「アプリケーションコンテナ」と呼ばれ、アプリケーション以外のプロセスが実行されていません。通常のLinuxであればSysVinitやUpstart、systemdなどのinitプロセスが実行され、システムの稼動に必要な様々なプロセスがinitプロセスによって実行されます。アプリケーションコンテナはアプリケーションのプロセスのみを起動するため高速に起動し、オーバーヘッドが少ないとされています。
Dockerアーキテクチャ
Dockerはクライアント・サーバ型のアーキテクチャです。Dockerクライアントは「Dockerデーモン」と「RESTful API」を用いて通信します。Dockerの動きを図で示すと下図のようになります。それぞれのコンポーネントについて簡単に紹介します。
Dockerデーモン
DockerデーモンはDocker APIリクエストを待ち受け、イメージ・コンテナ・ボリューム・ネットワークなどのDockerオブジェクトを管理します。Dockerデーモンを実行しているホストを「Dockerホスト」と呼びます。
Dockerクライアント
DockerクライアントはDockerデーモンに命令を送るためのフロントエンドです。dockerコマンドを実行すると、DockerデーモンにDocker APIリクエストを送信します。特別な事情がない場合はDockerをインストールしたホスト上でクライアントとデーモンを使用しますが、必ずしも同じホストで動作させる必要はありません。Dockerホストの場所を環境変数でクライアントに通知することでリモートのDockerデーモンと通信できます。
Dockerレジストリ
「Dockerレジストリ」はコンテナイメージを保管します。Dockerのデフォルトのコンテナレジストリは「Docker Hub」です。名前からも分かるようにDocker HubはDocker社が運営しており、コンテナレジストリのデファクトスタンダードとなっています。
Docker Hubには「Docker Official Image」と呼ばれるDocker社が公開しているイメージや「Verified Publisher」と呼ばれるベンダーが公開しているイメージがあります。Docker Official ImageやVerified PublisherのイメージはDocker社やベンダーがセキュリティを担保しています。
Docker Hubの他にも、よく使われるレジストリとして「GitHub Container Registry(ghcr.io)」や主要なパブリッククラウドが提供しているレジストリなどがあります。また、セルフホステッド型のコンテナレジストリも存在します。
レジストリによってはイメージの取得に認証が必要な「プライベートレジストリ」と呼ばれるタイプのレジストリも存在しますので、イメージを外部に公開できない場合はプライベートレジストリを使用します。
Dockerfile
「Dockerfile」はテキストファイルであり、コンテナイメージを作成するための設計図です。Dockerfile特有のフォーマットと命令を使用し、アプリケーションの動作環境を構築するためのすべての手順を記述します。DockerはDockerfileに記述されている命令を元にコンテナイメージの作成を自動化します。
Dockerオブジェクト
Dockerを使用すると、様々なオブジェクトが作成され管理できます。ここで言うオブジェクトとはコンテナイメージであったり、コンテナやボリューム、コンテナが外部との通信に使うネットワークを指します。オブジェクトの管理はdockerコマンドを用いてdocker [オブジェクト] [サブコマンド]
のフォーマットで行います。
以下に、簡単な使用例を紹介します。
・コンテナの一覧$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f07a669741ca ubuntu:22.04 "sleep 100" 35 seconds ago Up 34 seconds busy_haslett・コンテナイメージの削除
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 22.04 9b8dec3bf938 About a minute ago 117MB $ docker image rm 9b8dec3bf938 Untagged: ubuntu:22.04 Deleted: sha256:9b8dec3bf938bc80fbe758d856e96fdfab5f56c39d44b0cff351e847bb1b01ea・すべてのオブジェクトを削除
$ docker system prune --all --force --volumes Deleted Images: untagged: docker.io/library/ubuntu:22.04 deleted: sha256:9b8dec3bf938bc80fbe758d856e96fdfab5f56c39d44b0cff351e847bb1b01ea deleted: sha256:b4b521bfcec90b11d2869e00fe1f2380c21cbfcd799ee35df8bd7ac09e6f63ea deleted: sha256:3565a89d9e81a4cb4cb2b0d947c7c11227a3f358dc216d19fc54bfd77cd5b542 deleted: sha256:37aaf24cf781dcc5b9a4f8aa5a99a40b60ae45d64dcb4f6d5a4b9e5ab7ab0894 Total reclaimed space: 29.54MB
Dockerのメリット・デメリット
Dockerはオンプレミスや仮想マシンなどに比べても、様々なメリットがある反面デメリットも存在します。ここではDockerのメリットとデメリットについて解説します。
メリット
・少ない変更で環境構築が可能
従来の構築方法はまっさらな状態のOSに必要なミドルウェア・プログラミング言語ランタイム・ライブラリなどをインストールし、アプリケーションが動作する環境を構築していました。環境構築にはそのOSを操作する作法や構築するための知識が必要になります。
一方でDockerはDocker Hubからアプリケーションの動作環境に近いイメージを選択し、変更を加えることで環境構築が完了します。Docker HubにはベースとなるOSイメージの他にミドルウェアやプログラミング言語ランタイムが既にインストールされた状態のイメージが存在します。これらのイメージを選択することで構築までの手順を少なくできます。
・アプリケーションやインフラストラクチャをコードで管理
コンテナイメージを構築するための手順はDockerfileにすべて記述されています。Dockerfileはテキストファイルであるため、バージョン管理システムと相性が良く構成のレビューや変更の追跡が容易です。環境構築に際して一切の手作業が不要になるため、どこで誰が実行しても同じイメージが作成できます。
・イメージの共有が容易
Dockerにはイメージを簡単に配布する仕組みがあります。最もポピュラーなのはコンテナレジストリを使う方法です。Dockerはレジストリにイメージをアップロード・ダウンロードする機能があり、難しい手順を踏まなくてもコンテナレジストリを利用できます。他には実行中のコンテナからtar形式のファイルに出力する方法もあります。こちらはイメージを共有するというよりコンテナを保存する目的で使用されます。
デメリット
・学習コスト
Dockerを使用するには、Docker特有の作法やDocker、コンテナについての知識が必要になります。例えばDockerコンテナは1つのコンテナで1つのアプリケーションを実行しますが、複数プロセスを起動したい場合もあるでしょう。この場合、複数のコンテナを連携して実現するのが一般的ですが、Dockerコンテナへの理解が足りないと複数のプロセスを1つのコンテナで起動する方法を模索してしまうかもしれません
Dockerfileの書き方も学ぶ必要があります。Dockerはイメージ作成時に一度実行した命令をキャッシュします。つまり、変更の少ない順にDockerfileを記述することで効率的にキャッシュを使用でき、イメージの作成が高速になります。このようにDockerとDockerfile特有の処理を理解した上でDockerfileを記述しないとイメージのサイズが肥大化したり、セキュリティリスクをイメージに埋め込むことになります。
Dockerを正しく効率的に使用するにはコンテナやOS、Docker特有の作法について理解しておきましょう。今まで実行環境の設定をしてこなかった開発者がアプリケーションの動作環境を構築に当たり、OS上に実行環境を構築するための知識が必須となるのです。
おわりに
Dockerは非常に強力に開発作業を効率化してくれます。複数人で同じDockerfileやイメージを使用することで環境の統一が可能になり、差による問題は解決されます。
Dockerは、イメージを共有するための仕組みを有しており、開発に必要な開発・配布・実行の全てを担ってくれます。コンテナの仕組みについて深く理解していなくても、ある程度の知識でDockerによりコンテナを操作できます。Dockerの学習コストは低くはありませんが、習得して損をすることはないでしょう。