はじめに
WindowsでDockerを使ってみたいけど「そもそもコンテナって何?」という状態から、コンテナがなんとなくわかるようになるまでの話です。
コンテナ、仮想化についてコンテナ技術の1つである Docker をベースにして調べたことをまとめています。
Docker のコマンドや利用方法には触れず、あくまでも「コンテナとは?」「仮想化とは?」にフォーカスしていきます。
Docker はコンテナ技術としてはメジャーで歴史も古く情報も多いですが、コンテナ = Docker というわけではありません。
コンテナが分からない状態から学ぶには Docker がとっつきやすく勉強しやすいと思いますが、他の選択肢もあることは念頭に置いておいてください。
コンテナと仮想化
コンテナとは「OS レベルの仮想化」技術のことです。コンテナについて語る前に仮想化について理解する必要があります。
仮想化とは、物理的なコンピューターリソースを論理的に分割、あるいは統合することで、複数の仮想環境を作り出す技術です。
仮想サーバ、仮想ネットワーク、仮想ストレージなど、リソースを統合・分割することで本来とは違う個数や大きさにすることができるというものです。
「1つのものを複数に見せる」「複数のものを1つに見せる」技術として紹介されることがあります。私はこの説明がしっくりきました。
仮想化技術の例
- 1台のマシン上で複数のOSを動かすことでマシンが複数あるかのように見せる
- 1つのOS上で複数の環境を構築することで、OSが複数あるかのように見せる
- 1つの物理ネットワーク上に、複数のネットワークを構築することでネットワークが複数あるかのように見せる
- 複数の物理ストレージを1つのストレージのように扱う
プログラム言語の実行環境の切り替えに用いるanaconda、nvm等の技術でも「仮想環境」という言葉が使われます。
この仮想環境も広義では仮想化技術らしいですが、今回は別のものとして考えます。
これらの中でコンテナは「OSを仮想化する」技術です。
物理マシン上の1つのOSの中で、複数の隔離された環境(コンテナ)を作ることができます。
コンテナを使うメリット
開発をするうえでコンテナが使われる理由は大きく2つあると思います。
本番環境と開発環境の差を減らすことができる
コンテナを使わずにホストマシン上で直接アプリケーションを動かすと、必ず他のアプリケーションやライブラリ、データが混在してしまい、本番環境との差分が発生します。
コンテナでは必要な言語やライブラリ、設定ファイルだけをイメージ内に閉じ込めるため、本番により近い条件下で開発を進められます。
チームでの開発環境の共有が容易になる
従来はチームメンバーごとに「○○をインストールして」「プロジェクト用フォルダを指定の場所に作成して」といった手順を個別に踏む必要があり、設定漏れやバージョン違いによるトラブルが発生する可能性がありました。
コンテナを用いれば、ソースコードに加えてコンテナ設定ファイル(Dockerfile や compose.yml)をリポジトリに含めるだけで、誰でもコマンド一発で環境を立ち上げられます。
Windows で Docker を動かす
じゃあDockerを使いましょうとなりますが、実はDockerは本来Linuxでしか動かないツールです。一般的に使われる Linux コンテナを動かすには Linux カーネルが必要です。
私は「Dockerを使うとWindows上でLinux が動くんでしょ?」と思っていたのでちょっと誤解がありました。
WindowsでLinux コンテナを使うためには、何らかの方法でWindows上でLinux カーネルを動かし、その上でDockerの機能を使ってコンテナを動かすといった手順を踏む必要があります。
Docker には Linux コンテナと Windows コンテナの2種類があります。
Windows コンテナは Windows カーネル上で動作しますが、Linux コンテナの方が一般的です。
この記事では Linux コンテナに焦点を当てて説明します。
そこで重要になってくるのがカーネルです。
カーネルとコンテナの関係
Linuxマシンでのレイヤー構成
カーネルとは
- オペレーティングシステム(OS)の中核部分
- ハードウェア(CPU、メモリ、ディスクなど)を直接制御する
- アプリケーションとハードウェアの間の橋渡し役
コンテナは、以下のようなLinuxカーネルの機能を使って動作します
- namespaces(名前空間):プロセス、ネットワーク、ファイルシステムなどを隔離する
- cgroups(コントロールグループ):CPU、メモリなどのリソースを制限・管理する
これらの機能はLinuxカーネル固有のものです。
そのため、DockerなどのLinuxコンテナ技術は、Linuxカーネルがない環境では動作できません。
なぜWindowsでLinuxカーネルが必要なのか
- Windowsカーネルには、Linuxコンテナに必要な機能(namespaces、cgroupsなど)がない
- Linuxコンテナイメージは、Linuxカーネルの機能を前提として作られている
- したがって、WindowsでLinuxコンテナを動かすにはLinuxカーネルが必要
WindowsでLinuxカーネルを動かすためのHyper-V
WindowsでLinuxカーネルを実行するには、コンテナとは別の仮想化が必要になります。
なぜ仮想化が必要なのか
1つのコンピューター上で異なるOSのカーネルを同時に動かすことは、通常はできません。
WindowsカーネルとLinuxカーネルは、同じハードウェアに対して異なる方法でアクセスしようとするため、衝突してしまいます。
ここで必要になるのがハイパーバイザーです。
ハイパーバイザーとは
ハイパーバイザーは、仮想化を実現するソフトウェアです。
「1台の物理マシン上で複数のOSを同時に動かす」ための管理者的な役割を果たします。
ハイパーバイザーの機能
- リソースの分配:CPU、メモリ、ディスクなどのハードウェアリソースを各仮想マシンに割り当て
- 隔離の実現:各仮想マシンが互いに影響しないよう完全に分離
- スケジューリング:複数の仮想マシンがハードウェアを効率的に共有できるよう調整
Windows には Hyper-V というハイパーバイザーが搭載されています(Pro, Enterprise, Education エディション)。
LinuxカーネルとWSL
ハイパーバイザーによって複数のカーネルを動かせるようになったとしても、まだ問題があります。
Linuxカーネルを用意する必要があるのです。
従来の方法(仮想マシン)
通常であれば、以下のような手順が必要でした。
- Linux OSのインストールイメージ(Ubuntu、CentOSなど)をダウンロード
- Hyper-V上で仮想マシンを作成
- Linux OSをフルインストール
- Dockerをインストール
この方法は確実ですが、以下のような問題がありました
- 重い:Linux OS全体をインストールするため数GB必要
- 遅い:起動に時間がかかる
- 複雑:Linux OSの管理が必要
これらの問題を解決する、WSL という技術があります。
WSLとは
- Windowsに統合されたLinux実行環境
- Linux OSを軽量で実行できる仕組み
- WindowsとLinuxのシームレスな連携が可能
WSLにはWSL1とWSL2がありますが、これらは内部の仕様が大きく異なります。
現在一般にWSLと言われているものは「WSL2」です
これにより、WindowsユーザーはLinux OSの詳細を知らなくても、簡単にLinuxカーネルを利用できるようになりました。
WindowsマシンでのLinuxコンテナ実行時のレイヤー構成(WSL2使用)
まとめ
最初は「Dockerを使えばなんとかなる」くらいの理解でしたが、Hyper-V や WSL などの仕組みを組み合わせてはじめて、Windows上のLinuxコンテナが動いていることを学べました。
コンテナは学習コストは高いですが、開発を快適にする技術です。これからも学び続けてうまく付き合っていけたらと思います。