3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

コンテナ入門:コンテナとVMは何が違う?基本用語をおさらい

3
Posted at

はじめに

コンテナ、イメージ、Dockerfile、レジストリ。
Kubernetes(多数のコンテナの配置や運用を自動化するソフトウェア)を学ぼうとすると、前提としてこうしたDockerまわりの用語が一度に出てきます。
この記事は、Kubernetesを勉強し始める前の基礎のおさらいとして、Dockerの基本用語を整理したものです。

言葉の説明だけでなく、実際にDockerを動かしてみながら確認していきます。

ざっくりまとめ

先に、この記事で扱う用語を表にまとめます。

用語 ざっくり一言
VM(仮想マシン) OSごと丸ごと仮想化したコンピュータ。新しく作るのは数十秒〜数分
コンテナ OSは共有し、アプリと動作に必要なものだけを箱詰めして動かす技術。新しく作って動かすまで秒単位
Docker コンテナを作って動かすための代表的なソフトウェア。docker コマンドで操作する
イメージ コンテナの型。1つのイメージから何個でもコンテナを起動できる。この記事ではWebサーバーであるnginxのイメージを使う
Dockerfile イメージの設計図となるテキストファイル
レジストリ イメージの置き場。Docker Hubなど

用語どうしの関係を図にすると、次のようになります。

01-terms-map.png

まず、これらを扱う道具であるDockerから説明します。

Dockerとは

Dockerは、コンテナを作る・動かす・配るためのソフトウェアです。
コンテナの仕組み自体はLinux(OSの一種)が持つ機能ですが、それを一連のコマンドで手軽に扱えるようにしたツールとして、Dockerが広く使われています。

インストールすると、2つのものがセットで入ります。

  • Docker Engine — 常駐して、コンテナの作成・起動・停止を管理する本体
  • dockerコマンド — ターミナル(コマンドを文字で打ち込む画面)からDocker Engineに指示を出すための操作コマンド

この記事に出てくる docker rundocker build といったコマンドはすべて、VMにログインしたターミナルで打ち込むものです。

次に、実際に動かした環境です。

前提:動かした環境

  • OCI(Oracle Cloud Infrastructure。Oracleのクラウドサービス)のVM。シェイプ(CPUとメモリの構成を決める、VMの機種にあたるもの)はVM.Standard.E5.Flex 1コアOCPU、12 GBメモリー、OSはUbuntu 22.04(Linuxの一種)
  • Dockerのインストールは次の2行
sudo apt update && sudo apt install -y docker.io
sudo usermod -aG docker $USER

(1行目の apt はUbuntuにソフトウェアを追加するコマンド、sudo は管理者権限での実行です。2行目は、sudo なしで docker コマンドを実行できるようにする設定で、一度ログアウトして入り直すと反映されます。)

VMとコンテナの違い

VM(仮想マシン) は、物理サーバーの上に、ソフトウェアで仮想のコンピュータを丸ごと作る技術です。OCIで「コンピュート・インスタンス」と呼ばれているものがVMにあたります。1台のVMの中には、カーネル(CPUやメモリなどのハードウェアを管理する、OSの中核部分)を含むOS全体と、その上で動くソフトウェア一式がすべて入っています。

コンテナは、アプリケーションを、その動作に必要なライブラリや設定(依存関係)ごと箱詰めして動かす技術です。VMと違ってOSを丸ごとは持たず、カーネルはホスト(コンテナを載せている側のマシン。ここではVM)のものを共有します。コンテナの実体は、他から隔離された1つのプロセス(実行中のプログラム)です。

建物にたとえると、VMは土台から自前で建てる一戸建て、コンテナはマンションの1室です。
建物の基礎や配管にあたるカーネルは全室で共有しつつ、部屋どうしは壁で隔離されています。

(この隔離はLinuxカーネルのnamespaceとcgroupという機能で実現されていますが、この記事では深入りしません。)

構造を並べると次のようになります。

02-vm-vs-container.png

丸ごと持つか、共有するか。
この構造の違いは、新しく1つ用意して動き出すまでの時間の差になって表れます。
VMはリソースの割り当てとOS全体の起動が必要なぶん、プロセスを1つ立ち上げるだけのコンテナより時間がかかるはずです。どれくらい違うのか、実際に測ってみます。

VMの作成時間

image.png

VMの作成にかかった時間は、OCIコンソールとVMの中に残っている記録から確認できます。 まず、インスタンス詳細にある作業リクエスト(OCIが処理の受付から完了までを記録しているログ)を見ると、作成の受付が11:15:03、完了が11:15:31。 リソースの割り当てから電源投入までに28秒かかっています。

また SSHで入れるようになった時刻は、VMの中に残っている記録から確認できます。

systemctl show ssh -p ActiveEnterTimestamp
# ActiveEnterTimestamp=Tue 2026-09-01 11:15:45 UTC

これは、SSHサービスがいつ起動完了したかを表示するコマンドです。 受付の11:15:03から数えて、作成を頼んでからログインできるようになるまで42秒でした。

(今回の環境では1分を切りましたが、かかる時間はシェイプやOSイメージ、クラウドサービスによって変わります。数分かかる環境もあります。)

コンテナの起動時間

そのVMの上で、nginx(ブラウザなどからのアクセスに応えてWebページを返す、代表的なWebサーバー)をコンテナとして起動します。
先頭の time は、後ろに書いたコマンドの実行にかかった時間を測るコマンドです。

time docker run -d -p 8080:80 --name web1 nginx

1回目の実行は8.1秒でした。
docker rm -f web1 でいったんコンテナを消し、同じコマンドをもう一度実行すると、2回目は0.2秒で終わりました。

image.png

curl は、指定した宛先にアクセスして応答を文字で表示するコマンドです。
宛先の localhost は自分自身(ここではこのVM)を指すので、curl localhost:8080 でnginxの応答が返ってくれば、Webサーバーが1つ動いたことになります。

image.png

VMの作成が42秒、コンテナの起動が0.2秒。およそ200倍の差でした。 なお、初回の docker run だけ8秒かかっていますが、この理由は後述するレジストリの節で説明します。

先ほどのコマンドで nginx と指定した部分が、次の用語であるイメージの話につながります。

イメージとコンテナの関係

docker run nginxnginx は、イメージの名前です。
イメージは、アプリケーションと依存関係をひとまとめに固めた、コンテナの型にあたるデータです。
料理にたとえると、イメージがレシピ、コンテナが実際に作った料理です。
1つのレシピから何皿でも作れるのと同じで、1つのイメージから何個でもコンテナを起動できます

同じイメージから、あと2つコンテナを立ててみます。

docker run -d -p 8081:80 --name web2 nginx
docker run -d -p 8082:80 --name web3 nginx
docker ps

image.png

1台のVMの上に、同じ型から作ったWebサーバーが3つ、それぞれ数秒で立ち上がりました。
同じ型から同じものを数秒で量産できるという性質は、後で学ぶKubernetesのスケーリング(コンテナの数を増やして負荷に対応する仕組み)の土台になります。

起動したコンテナは、次のようなコマンドで操作できます。

docker logs web1              # コンテナのログを見る
docker exec -it web1 bash     # コンテナの中に入る(exitで抜ける)
docker stop web1              # 停止する
docker rm web1                # 削除する

docker stop で停止したコンテナは、消えるわけではなく停止状態で残っていて、docker start web1 で再開できます。
完全に消すのが docker rm です。
ただ、コンテナは停止状態で取っておいて使い回すより、必要になったらイメージから新しく作り、要らなくなったら消す、という使い捨てに近い使い方が基本です。型であるイメージさえ残っていれば、同じものはいつでも数秒で作り直せるためです。
先ほど測った docker run の数秒は、まさにこの「新しく作って起動する」までの時間で、VM側の比較対象が起動時間ではなく作成時間なのも同じ理由です。

docker run に付けたオプションの意味:-d は画面を占有せず裏で動かし続けるバックグラウンド実行、-p 8080:80 はVMの8080番ポート(通信の窓口を区別する番号)へのアクセスをコンテナの80番へ転送するポート公開、--name はコンテナに付ける名前です。docker exec-it は、コンテナの中で対話的にコマンドを打つための指定です。)

ここまでは、公式に用意されたnginxイメージをそのまま使ってきました。
次は、イメージを自分で作ります。

Dockerfileとイメージのビルド

イメージの設計図にあたるテキストファイルがDockerfileです。
nginxのトップページを自分のHTMLに差し替えた、オリジナルのイメージを作ってみます。

mkdir mysite && cd mysite
echo '<h1>Hello from my container</h1>' > index.html
cat > Dockerfile <<'EOF'
FROM nginx
COPY index.html /usr/share/nginx/html/index.html
EOF

cat > Dockerfile <<'EOF' は、次の行から EOF と打つまでの内容を、Dockerfileという名前のファイルに書き込む書き方です。テキストエディタで同じ内容のファイルを作っても構いません。)

Dockerfileの中身は2行です。

  • FROM nginx — nginx公式イメージを土台にする
  • COPY index.html ... — 手元のindex.htmlをイメージの中にコピーする

このDockerfileから、docker build でイメージを作ります(この操作をビルドと呼びます)。
できたイメージを起動して、自分のHTMLが返ってくることを確認します。

docker build -t mysite:1.0 .
docker run -d -p 8083:80 mysite:1.0
curl localhost:8083

image.png

-t mysite:1.0mysite がイメージ名、:1.0タグと呼ばれるバージョン識別子です。
イメージは、FROMで指定した土台の上に変更を1段ずつ重ねた、差分の積み重ね(レイヤー)として作られています。

docker images を実行すると、土台にしたnginxと、今作ったmysiteが手元に並んでいるのを確認できます。

image.png

作ったイメージは、今はこのVMの中にしかありません。
別のマシンでも同じイメージを使えるようにするには、イメージの置き場が必要です。

レジストリ

レジストリは、イメージを保管・配布するための置き場です。
スマートフォンにとってのApp Storeのような位置づけで、公開されているイメージを取得(pull)したり、自分のイメージを登録(push)したりできます。

代表的なレジストリがDocker Hubです。
最初に docker run nginx を実行したとき、裏ではDocker Hubからnginx公式イメージがpullされていました。 初回のコンテナ起動に8秒かかったのは、このダウンロードが走っていたためです。 2回目以降はイメージが手元にあるので、0.2秒で起動しています。

イメージの指定は 名前:タグ の形で書きます。
例えば nginx:1.27 は「nginxイメージのバージョン1.27」を指し、タグを省略した nginx は最新版を指す nginx:latest として扱われます。

(OCIにもContainer Registry(OCIR)というレジストリサービスがあり、自分で作ったイメージの置き場として使えます。別途、OCIRへpushしてみた手順記事を書きますのでそちらも参考にしてください。)

基本コマンド早見表

ここまでに出てきたコマンドを一覧にします。

コマンド 何をするか
docker run イメージからコンテナを起動する
docker ps 起動中のコンテナ一覧を見る(-a で停止中も含む)
docker logs <名前> コンテナのログを表示する
docker exec -it <名前> bash 起動中のコンテナの中に入る
docker stop / docker rm コンテナを停止する/削除する
docker build -t <名前:タグ> . Dockerfileからイメージを作る
docker images 手元にあるイメージの一覧を見る
docker pull / docker push レジストリからイメージを取得する/レジストリへ登録する

表のコマンドはすべて docker コマンドですが、コンテナを実際に動かしているソフトウェアは別にあります。

コンテナランタイム

最初に説明したとおり、docker コマンドはDocker Engineへ指示を出す窓口です。
このDocker Engineの内部では、containerdというコンテナランタイム(コンテナの起動・停止を実際に行うソフトウェア)がコンテナを動かしています。
この区別はKubernetesで効いてきます。
Kubernetesは docker コマンドやDocker Engineを介さず、containerdを直接使ってコンテナを動かすため、Kubernetesが管理するマシンに docker コマンドが入っていなくてもコンテナは動きます。

Kubernetesの用語との対応

最後に、今回の用語がKubernetesではどう呼ばれるかの対応です。

Dockerまわりの用語 Kubernetesでの対応
コンテナ Pod(1個以上のコンテナをまとめた実行単位)の中で動く
VM Node(Podを動かすワーカーのマシン)として使われる
イメージ/レジストリ/タグ そのまま同じ仕組みを使う

イメージとレジストリの仕組みは、Kubernetesでもそのまま使われます。
変わるのは管理の単位で、コンテナはPodという入れ物に包まれ、VMはNodeという名前で、クラスタ(複数のマシンを束ねて1つのシステムとして扱うまとまり)の働き手になります。

まとめ

  • VMはOSごと丸ごとの仮想コンピュータで、作成からログインできるまで実測42秒。コンテナはカーネルを共有した隔離プロセスで、作成して起動するまで実測0.2秒(初回はイメージのダウンロード込みで8秒)
  • イメージは型、コンテナは実体。1つのイメージから何個でもコンテナを起動できる
  • Dockerfileはイメージの設計図、レジストリ(Docker Hubなど)はイメージの置き場
  • Kubernetesでは、コンテナはPodに包まれ、VMはNodeと呼ばれる

今回、1台のVMの上でコンテナを1秒足らずで増やせることは確認できました。 一方で、そのVM自体のCPUやメモリが足りなくなったときは、VM(Node)そのものを増やすことになります。 実測では、VMの作成(42秒)はコンテナの起動(0.2秒)の約200倍。さらにKubernetesの世界では、作ったVMがノードとしてクラスタに参加して使えるようになるまでの処理が上乗せされます。 この、時間のかかるVMをいつ・何台増やすかという自動化が、ノードスケーリングと呼ばれる領域です。

次回は、Kubernetes側の最小限の用語(Pod・Deployment・Node)を整理し、OCI上でKubernetesを動かすサービスであるOKE(Oracle Kubernetes Engine)を使って、Podがリソース不足で起動できなくなる場面(Pending)を実際に作ってみます。 少しでも参考になれば嬉しいです。

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?