Docker イメージとコンテナの違いを図解で理解する

Docker を学習し始めた際、多くの方が「イメージ」と「コンテナ」という2つの概念で混乱してしまいます。これらは密接に関連していながらも、明確に異なる役割を持っているんです。
本記事では、Docker の基本となるこの2つの概念について、図解を交えながら分かりやすく解説いたします。実際のコマンド操作や具体例を通して、皆様がこれらの違いをしっかりと理解できるよう丁寧にお伝えしていきますね。
背景
Docker の登場とコンテナ技術の普及
近年の Web 開発において、Docker は欠かせない技術となりました。従来の開発環境では「私のマシンでは動くのに、本番環境では動かない」という問題が頻繁に発生していたんです。
Docker は、この環境の違いによる問題を解決するために生まれました。アプリケーションとその実行環境を一つのパッケージとして扱えるようになり、どこでも同じように動作させることが可能になったんですね。
コンテナ技術自体は Linux の機能を活用した古い技術でした。しかし、Docker がユーザーフレンドリーなツールとして登場したことで、多くの開発者が簡単にコンテナを活用できるようになったんです。
なぜイメージとコンテナが必要なのか
Docker の仕組みを理解するには、「設計図」と「実際の建物」の関係を考えると分かりやすいでしょう。
以下の図で、Docker における基本的な流れを確認してみましょう。
mermaidflowchart LR
dockerfile[Dockerfile] -->|docker build| image[Docker イメージ]
image -->|docker run| container1[コンテナ1]
image -->|docker run| container2[コンテナ2]
image -->|docker run| container3[コンテナ3]
subgraph "設計図"
dockerfile
image
end
subgraph "実際の実行環境"
container1
container2
container3
end
この図が示すように、一つの設計図(イメージ)から複数の実行環境(コンテナ)を作成できます。これにより、同じ環境を何度でも再現できるんですね。
イメージとコンテナを分離することで、以下のメリットが生まれます:
- 再利用性: 一度作成したイメージから、必要な分だけコンテナを作成可能
- 一貫性: どこで実行しても同じ動作を保証
- 効率性: イメージは読み取り専用のため、リソースを効率的に使用
- バックアップ: イメージをレジストリに保存して、チーム間で共有可能
課題
初心者が混同しやすいポイント
Docker を学び始めた方が直面する主な混乱ポイントを整理してみましょう。
最も多い誤解は「イメージとコンテナは同じもの」という認識です。実際に Docker コマンドを実行すると、両方とも ID が表示されるため、同じような存在だと感じてしまうんですね。
また、「コンテナを削除したらイメージも消える」と考える方も多くいらっしゃいます。これは逆で、コンテナが削除されてもイメージは残り続けます。
さらに、「イメージに直接変更を加える」という誤解もよく見られます。イメージは読み取り専用のテンプレートなので、直接変更することはできないんです。
従来の仮想化との違いが分からない問題
従来の仮想マシン(VM)と Docker コンテナの違いも、初心者の方には分かりにくいポイントです。
以下の図で、両者の違いを比較してみましょう。
mermaidflowchart TD
subgraph "従来の仮想マシン"
host1[ホスト OS]
hypervisor[ハイパーバイザー]
vm1[ゲスト OS 1]
vm2[ゲスト OS 2]
app1[アプリ 1]
app2[アプリ 2]
host1 --> hypervisor
hypervisor --> vm1
hypervisor --> vm2
vm1 --> app1
vm2 --> app2
end
subgraph "Docker コンテナ"
host2[ホスト OS]
docker[Docker Engine]
container1[コンテナ 1]
container2[コンテナ 2]
dockerapp1[アプリ 1]
dockerapp2[アプリ 2]
host2 --> docker
docker --> container1
docker --> container2
container1 --> dockerapp1
container2 --> dockerapp2
end
この図からも分かるように、Docker コンテナは OS レベルでの仮想化を行います。各コンテナが独自の OS を持つ必要がないため、軽量で高速な起動が可能なんです。
ここでの混乱要因は以下の通りです:
- リソース消費量: VM は OS 分のリソースが必要、コンテナは最小限
- 起動時間: VM は OS 起動時間が必要、コンテナは秒単位で起動
- 分離レベル: VM は完全分離、コンテナはプロセスレベル分離
解決策
Docker イメージとは何か
Docker イメージは、アプリケーションの実行に必要な全ての要素を含んだ読み取り専用のテンプレートです。料理で例えると「レシピ」のような存在ですね。
イメージには以下の要素が含まれています:
要素 | 説明 | 具体例 |
---|---|---|
ベース OS | 基本的な OS 環境 | Ubuntu、Alpine Linux |
ランタイム | 実行環境 | Node.js、Python、Java |
アプリケーション | 実際のコード | Web アプリ、API サーバー |
ライブラリ・依存関係 | 必要なパッケージ | npm modules、pip packages |
設定ファイル | 環境設定 | nginx.conf、.env ファイル |
イメージの作成は Dockerfile というテキストファイルで定義します。
dockerfile# ベースイメージの指定
FROM node:18-alpine
# 作業ディレクトリの設定
WORKDIR /app
# パッケージ情報のコピー
COPY package*.json ./
dockerfile# 依存関係のインストール
RUN npm ci --only=production
# アプリケーションコードのコピー
COPY . .
# 実行ユーザーの設定
USER node
dockerfile# ポートの公開設定
EXPOSE 3000
# 起動コマンドの指定
CMD ["node", "server.js"]
このように、イメージは段階的にレイヤーを積み重ねて構築されます。各 RUN
、COPY
などの命令が一つのレイヤーとなり、効率的にキャッシュされるんです。
Docker コンテナとは何か
Docker コンテナは、イメージから作成される実際の実行環境です。レシピ(イメージ)から作られた「実際の料理」のような存在ですね。
コンテナの特徴を以下の表で整理してみましょう:
特徴 | 説明 | メリット |
---|---|---|
実行可能 | プロセスとして動作 | リアルタイムでアプリが稼働 |
書き込み可能 | 一時的な変更が可能 | ログやキャッシュの保存 |
独立性 | 他のコンテナと分離 | 干渉せず安全に実行 |
一時性 | 削除すると変更は消失 | クリーンな環境の維持 |
コンテナの作成と実行は以下のコマンドで行います:
bash# イメージからコンテナを作成・実行
docker run -d --name web-server -p 8080:3000 my-app:latest
# 実行中のコンテナ一覧を表示
docker ps
bash# コンテナ内でコマンド実行
docker exec -it web-server /bin/sh
# コンテナの停止
docker stop web-server
bash# コンテナの削除
docker rm web-server
# 停止中のコンテナも含めて表示
docker ps -a
両者の関係性と役割分担
イメージとコンテナの関係は、プログラミングにおける「クラス」と「インスタンス」の関係に似ています。
以下の図で、両者の関係と役割分担を確認してみましょう:
mermaidstateDiagram-v2
[*] --> Dockerfile
Dockerfile --> DockerImage : docker build
state DockerImage {
[*] --> ReadOnly
ReadOnly --> Layers
Layers --> Template
}
DockerImage --> Container1 : docker run
DockerImage --> Container2 : docker run
DockerImage --> Container3 : docker run
state Container1 {
[*] --> Running
Running --> Modified
Modified --> Stopped
Stopped --> [*]
}
この図から、以下のような役割分担が見えてきます。
イメージの役割:
- アプリケーションの実行環境を定義
- 複数のコンテナのベースとなるテンプレート提供
- バージョン管理とレジストリでの共有
- 読み取り専用として一貫性を保証
コンテナの役割:
- 実際のアプリケーション実行
- 一時的なデータの読み書き
- ネットワーク通信の処理
- リソース(CPU、メモリ)の消費
重要なポイントは、イメージは不変でコンテナは可変という点です。コンテナで行った変更は、そのコンテナ内でのみ有効になります。
具体例
実際の Docker コマンドで見る違い
イメージとコンテナの違いを、実際のコマンド操作で確認してみましょう。
まず、イメージに関する基本的な操作から見ていきます:
bash# イメージの一覧表示
docker images
# 出力例:
# REPOSITORY TAG IMAGE ID CREATED SIZE
# nginx latest 4f380adfc10f 2 days ago 133MB
# node 18 1b9b4b9b4b9b 1 week ago 945MB
bash# イメージの詳細情報表示
docker inspect nginx:latest
# イメージのダウンロード
docker pull ubuntu:20.04
bash# イメージの削除(コンテナが実行中でないことが前提)
docker rmi nginx:latest
# 強制削除
docker rmi -f nginx:latest
次に、コンテナの操作を見てみましょう:
bash# 新しいコンテナの作成・実行
docker run -d --name my-nginx -p 8080:80 nginx:latest
# 実行中のコンテナ一覧
docker ps
bash# すべてのコンテナ一覧(停止中含む)
docker ps -a
# コンテナの詳細情報
docker inspect my-nginx
bash# コンテナの停止と削除
docker stop my-nginx
docker rm my-nginx
ここで重要な違いを確認できます。イメージを削除してもコンテナに影響はなく、コンテナを削除してもイメージは残るということです。
ファイルシステムレベルでの違い
Docker のファイルシステムは、レイヤー構造になっています。この仕組みを理解することで、イメージとコンテナの違いがより明確になるでしょう。
以下の図で、レイヤー構造を確認してみましょう:
mermaidflowchart TB
subgraph "Docker イメージ(読み取り専用レイヤー)"
layer1[Base OS Layer]
layer2[Runtime Layer]
layer3[App Dependencies Layer]
layer4[Application Layer]
layer1 --> layer2
layer2 --> layer3
layer3 --> layer4
end
subgraph "Docker コンテナ"
layer4 --> writable[書き込み可能レイヤー]
writable --> tempdata[一時ファイル・ログ・キャッシュ]
end
実際にコンテナ内でファイルを作成してみましょう:
bash# コンテナを起動してファイル作成
docker run -it --name test-container ubuntu:20.04 /bin/bash
# コンテナ内で実行
echo "Hello from container" > /tmp/test.txt
cat /tmp/test.txt
bash# コンテナを終了してホストに戻る
exit
# 同じイメージから別のコンテナを起動
docker run -it --name another-container ubuntu:20.04 /bin/bash
bash# 新しいコンテナ内で確認
cat /tmp/test.txt
# → No such file or directory(ファイルが存在しない)
この例から分かるように、コンテナで作成したファイルは、そのコンテナ内でのみ有効です。イメージ自体は変更されず、他のコンテナには影響しません。
メモリ・CPU リソースの扱い方
イメージとコンテナでは、リソースの扱い方も大きく異なります。
イメージのリソース特性:
bash# イメージのサイズ確認
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# 出力例:
# REPOSITORY TAG SIZE
# nginx latest 133MB
# node 18 945MB
# alpine latest 5.54MB
bash# イメージの詳細なサイズ情報
docker system df
# 出力例:
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 3 2 1.08GB 545MB (50%)
# Containers 2 1 1.2MB 1.2MB (100%)
コンテナのリソース管理:
bash# CPUとメモリ制限付きでコンテナ起動
docker run -d \
--name resource-limited \
--memory="512m" \
--cpus="1.5" \
nginx:latest
bash# コンテナのリソース使用状況をリアルタイム監視
docker stats
# 出力例:
# CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM %
# 1234567890ab resource-limited 0.50% 45MiB / 512MiB 8.79%
bash# コンテナの詳細なリソース情報
docker inspect resource-limited | grep -A 10 "Resources"
重要な違いのまとめ:
項目 | イメージ | コンテナ |
---|---|---|
ディスク使用量 | 固定サイズ | 変動サイズ |
メモリ | 使用しない | 実行時に消費 |
CPU | 使用しない | 実行時に消費 |
ネットワーク | 無関係 | ポートバインドあり |
コンテナは実際にプロセスとして動作するため、リアルタイムでシステムリソースを消費します。一方、イメージはディスク上の静的なファイルとして存在するだけです。
まとめ
イメージとコンテナの使い分け方針
Docker を実際のプロジェクトで活用する際の使い分け方針をまとめてみましょう。
イメージを中心に考えるべき場面:
- 新しい環境の構築や配布を行う場合
- チーム間での開発環境統一が必要な場合
- CI/CD パイプラインでの自動化を行う場合
- 本番環境へのデプロイを実行する場合
コンテナを中心に考えるべき場面:
- 実際のアプリケーション開発・デバッグ時
- ログ分析やトラブルシューティング時
- スケールアップ・スケールアウトの調整時
- 一時的な作業環境が必要な場合
実務で意識すべきポイント
実際の開発現場でイメージとコンテナを扱う際に、特に注意していただきたいポイントをお伝えします。
セキュリティ面での注意点:
- イメージには機密情報(パスワード、API キー)を含めない
- 最小限のベースイメージを使用してセキュリティリスクを削減
- 定期的なイメージの更新でセキュリティパッチを適用
パフォーマンス面での注意点:
- レイヤーキャッシュを活用した効率的な Dockerfile 作成
- 不要なファイルを含めない .dockerignore の活用
- マルチステージビルドでイメージサイズの最適化
運用面での注意点:
- 適切なタグ管理(latest タグの使用は避ける)
- コンテナの状態監視とログ管理の仕組み構築
- データの永続化が必要な場合のボリューム活用
Docker イメージとコンテナの違いを理解することで、より効率的で安全な Docker 活用が可能になります。最初は混乱することもあるかもしれませんが、実際に手を動かしながら学習を続けることで、必ず理解が深まっていくでしょう。
皆様の Docker 学習がスムーズに進むことを願っています。
関連リンク
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来