1.2 Dockerのアーキテクチャ完全解説|CLI・デーモン・containerd・Docker Hub の全体像

【第1章】Dockerとは何か

docker run nginx を打つと何が起きるのか?」——この問いに答えられるかどうかが、Dockerを”使える人”から”わかっている人”への分かれ目です。

本記事では Docker Client・Docker Daemon・containerd・runc・Docker Hub の5つのコンポーネントを図解し、コマンド1行がコンテナ起動に至るまでの全フローをシミュレータで体感してもらいます。1-5 で学んだ名前空間・cgroupsがどこで使われるかも繋がります。


目次

  1. Docker の全体像:3つの主要コンポーネント
  2. Docker Client — CLI と REST API
  3. Docker Daemon(dockerd)— 司令塔
  4. containerd と runc — 実行を担う内部ランタイム
  5. docker run のフローを追う
  6. Docker Hub とレジストリ
  7. イメージ名の完全な形式
  8. daemon.json で Daemon を設定する(上級者向け)
  9. まとめ

1. Docker の全体像:3つの主要コンポーネント

Docker のアーキテクチャは大きく3つのコンポーネントで構成されています。

コンポーネント 主な役割 場所
Docker Client docker CLI や Docker Compose。ユーザーの操作を REST API に変換して Daemon に送る ユーザーの端末・CI環境
Docker Host Docker Daemon(dockerd)が動くサーバー。コンテナ・イメージ・ネットワーク・ボリュームを管理 ローカルPC または リモートサーバー
Registry Dockerイメージを保存・配布するサービス。デフォルトは Docker Hub クラウド(Docker Hub、ECR、GHCRなど)またはオンプレ
Docker Client
docker CLI
docker compose
REST API →
Docker Host
Docker Daemon(dockerd)
コンテナ管理
ネットワーク
イメージ管理
ボリューム管理
↓ gRPC
containerd → runc → Container 🚀
↕ Registry API(HTTPS)
Docker Hub(registry-1.docker.io)

Client と Host は同じマシンにあることも(ローカル開発)、ネットワーク越しに別のサーバーにあることも(リモートデプロイ)あります。


2. Docker Client — CLI と REST API

ユーザーが直接操作するのは Docker Client です。docker rundocker psdocker build などのコマンドはすべてクライアントです。

REST API を介した通信

Docker Client は Docker Engine API(REST API)を通じて Docker Daemon に指示を送ります。普段コマンドで操作していても、内部ではHTTPリクエストが流れています。

  docker ps     →  GET  /v1.47/containers/json
  docker run    →  POST /v1.47/containers/create
                   POST /v1.47/containers/{id}/start
  docker pull   →  POST /v1.47/images/create?fromImage=nginx&tag=latest
  docker images →  GET  /v1.47/images/json
  docker stop   →  POST /v1.47/containers/{id}/stop
💡 API バージョン
Docker Engine API は /v{バージョン}/ でバージョン管理されています。docker version を実行すると Client と Server それぞれの API バージョンを確認できます。後方互換性があるため、古いクライアントでも新しいデーモンに接続できます。

通信経路

接続先 プロトコル 用途
unix:///var/run/docker.sock Unix ドメインソケット デフォルト。同一ホスト上のデーモンに接続
tcp://hostname:2376 TCP + TLS リモートの Docker Daemon に接続(TLS必須)
npipe:////./pipe/docker_engine Windows 名前付きパイプ Windows ホストでのデフォルト
# API バージョンを確認する
docker version
# → Client:  API version: 1.47
# → Server:  API version: 1.47  (minimum: 1.24)

# curl で直接 API を叩く(Linux)
curl --unix-socket /var/run/docker.sock http://localhost/v1.47/containers/json
# → 実行中コンテナの JSON 一覧が返る

# リモートデーモンを使う(DOCKER_HOST 環境変数)
export DOCKER_HOST=tcp://remote-server:2376
docker ps  # → リモートデーモンに接続
⚠️ docker.sock のマウントに注意
コンテナに -v /var/run/docker.sock:/var/run/docker.sock でソケットをマウントすると、そのコンテナは Docker Daemon を完全制御できます。実質的にホストrootと同等の権限になるため、信頼できるコンテナ以外には決してマウントしないでください(第8章・セキュリティで詳しく解説)。

3. Docker Daemon(dockerd)— 司令塔

Docker Daemondockerd)は Docker Host の中心にいる常駐プロセスです。Client からの REST API リクエストを受け取り、以下のすべてを管理します。

  • コンテナ:作成・起動・停止・削除・ログ取得
  • イメージ:ビルド(BuildKit経由)・ローカルキャッシュ・pull/push
  • ネットワーク:bridge/host/overlay などのネットワーク管理
  • ボリューム:Named Volume のライフサイクル管理

コンテナの実際の作成と実行は、自分では行わず containerd に委任します(次セクション)。

# daemon が動いているか確認
systemctl status docker        # Linux(systemd)
docker info                    # すべての環境

# daemon のログを見る(Linux)
journalctl -u docker -n 50

# docker info の主要な出力項目
# → Server Version: 27.3.1
# → Storage Driver: overlay2
# → Cgroup Driver: systemd
# → containerd version: v1.7.x
# → runc version: v1.1.x

4. containerd と runc — 実行を担う内部ランタイム

dockerd は「管理」に集中し、実際のコンテナ実行は 2段階のランタイムに委任しています。これはモノリシックな構成では Kubernetes などの他のオーケストレーターと統合できないため、Docker 1.11(2016年)で分離されました。

dockerd(高レベル:API・ネットワーク・ボリューム・BuildKit)
↓ gRPC(/var/run/containerd/containerd.sock)
containerd(中レベル:イメージ管理・スナップショット・ライフサイクル)
↓ OCI Runtime Spec(exec + config.json)
runc(低レベル:clone() → overlayfs → cgroup → exec())
Container プロセス(PID 1: nginx など)
コンポーネント 規格 主な責務 特記事項
containerd CRI(Container Runtime Interface) イメージの取得・アンパック・スナップショット管理・コンテナのライフサイクル Kubernetes でも直接採用。CNCF 卒業プロジェクト
runc OCI Runtime Specification clone() で名前空間生成・OverlayFS マウント・cgroup 設定・exec() でプロセス起動 OCI の参照実装。1-5 で学んだ仕組みはすべてここで実行される
💡 runc は起動後に消える
runc はコンテナを作成した後、プロセスとして残りません。「起動補助係」として一時的に動き、コンテナのプロセスを生み出したら終了します。実行中のコンテナを管理し続けているのは containerd です。
# containerd の状態を確認
systemctl status containerd

# containerd が管理するコンテナを直接確認(Docker経由でなくcontainerd CLIで)
ctr --namespace moby containers list   # Docker が使う namespace は "moby"

# runc のバージョン確認
runc --version
# → runc version 1.1.x
# → spec: 1.0.2-dev
# → go: go1.x
# → libseccomp: x.x.x

5. docker run のフローを追う

ここまで学んだコンポーネントが、docker run nginx というコマンドでどう連携するか見てみましょう。

シミュレータで確認したフローをテキストで整理すると次のようになります。

  ① docker run nginx
        ↓
  ② docker CLI → POST /v1.47/containers/create(REST API)
                  POST /v1.47/containers/{id}/start
        ↓
  ③ dockerd
       ・ローカルイメージキャッシュを確認
       ・nginx が存在しない → Docker Hub へ pull
         (GET /v2/library/nginx/manifests/latest → manifest 取得)
         (GET /v2/library/nginx/blobs/{digest} × Nレイヤー → ダウンロード)
       ・containerd に gRPC で CreateContainer + StartTask を送信
        ↓
  ④ containerd
       ・スナップショット(OverlayFS 用)を準備
       ・OCI spec(config.json)を生成して runc に渡す
        ↓
  ⑤ runc
       ・clone() で名前空間グループ生成(pid/net/mnt/uts/ipc)
       ・OverlayFS を MNT 名前空間内にマウント
       ・cgroup を /sys/fs/cgroup/ 以下に設定
       ・exec() → nginx 起動
        ↓
  ⑥ Container 🚀
       ・PID 1: nginx(コンテナ名前空間内から)
       ・ホストから見ると PID 3842 程度の1プロセス

VMとの決定的な違いは、③〜⑤がすべて ミリ秒〜数百ミリ秒で完了する点です。カーネル起動は存在せず、プロセスを分岐させるだけです。


6. Docker Hub とレジストリ

レジストリ(Registry)は Dockerイメージを保存・配布するサービスです。Git で言えば GitHub に相当します。

Dockerのデフォルトレジストリは Docker Hubregistry-1.docker.io)です。docker pull ubuntu と書くだけで Docker Hub から取得されるのは、レジストリを省略したときのデフォルトが Docker Hub だからです。

Registry API(OCI Distribution Specification)

レジストリとクライアントの通信は OCI Distribution Specification(旧: Docker Registry HTTP API v2)で標準化されています。

  docker pull nginx の内部通信(HTTPS)

  ① GET  https://registry-1.docker.io/v2/
         → 200 OK(API バージョン確認)

  ② GET  https://registry-1.docker.io/v2/library/nginx/manifests/latest
         Accept: application/vnd.docker.distribution.manifest.v2+json
         → マニフェスト(イメージのレイヤー構成情報)

  ③ GET  https://registry-1.docker.io/v2/library/nginx/blobs/{digest}
         → 各レイヤーの tar.gz をダウンロード(すでにあればスキップ)

  ④ ローカルの OverlayFS に展開 → docker images で見えるようになる

Docker Hub のプランとレート制限

プラン pull レート制限 プライベートリポジトリ
未認証(anonymous) 100回 / 6時間 / IPアドレス 不可
無料(personal) 200回 / 6時間 / アカウント 1リポジトリ
Pro / Team 以上 無制限 無制限
⚠️ CI/CD 環境での pull 制限に注意
GitHub Actions などのCI環境では複数のジョブが同じIPからpullするため、レート制限に引っかかりやすくなります。docker login で認証してから pull する、または GitHub Container Registry(GHCR)を使うことで回避できます。

主要なレジストリ

レジストリ 提供元 主な用途
Docker Hub Docker Inc. 公式イメージ・OSS公開イメージ。デフォルト
GHCR(ghcr.io) GitHub GitHub Actions と連携した自動ビルド・プッシュ
ECR(*.dkr.ecr.*.amazonaws.com) AWS AWS環境でのプライベートレジストリ
Artifact Registry(*.pkg.dev) Google Cloud GKEとの統合。旧GCR後継
ACR(*.azurecr.io) Azure AKSとの統合
Harbor CNCF(OSS) オンプレミス・プライベートレジストリ。脆弱性スキャン機能付き
# Docker Hub にログイン(~/.docker/config.json に認証情報を保存)
docker login

# GitHub Container Registry にログイン
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# ログインしているレジストリを確認
cat ~/.docker/config.json | jq .auths

7. イメージ名の完全な形式

Docker のイメージ名には省略できる部分がいくつかあります。省略したときのデフォルト値を理解しておくと、どのレジストリからどのイメージが取得されるかがわかります。

  完全形式:  [レジストリ[:ポート]/][ネームスペース/]リポジトリ名[:タグ][@ダイジェスト]

  nginx
  └→ registry-1.docker.io / library / nginx : latest

  ubuntu:22.04
  └→ registry-1.docker.io / library / ubuntu : 22.04

  myorg/myapp:v1.0
  └→ registry-1.docker.io / myorg / myapp : v1.0

  ghcr.io/owner/myapp:sha-abc123
  └→ ghcr.io / owner / myapp : sha-abc123

  myregistry.example.com:5000/team/api:production
  └→ myregistry.example.com:5000 / team / api : production

  nginx@sha256:1234abcd...
  └→ タグの代わりにダイジェスト(イミュータブルな参照)で固定
省略した場合のデフォルト
レジストリ registry-1.docker.io(Docker Hub)
ネームスペース(公式イメージのみ) library
タグ latest
⚠️ :latest タグは「最新」を保証しない
latest タグはイメージ作成者が任意に付けるタグに過ぎません。docker pull nginx以前 pull したキャッシュがあればそちらを使う ため、最新版ではない可能性があります。本番環境では バージョンタグかダイジェストで固定することを強く推奨します(第7章で詳しく解説)。
# 明示的にタグを指定する(推奨)
docker pull nginx:1.27-alpine

# ダイジェストで不変参照(最も安全)
docker pull nginx@sha256:67682bda769fae1ccf5183192b8daf37b64cae99c6c33302b07c9cbaef755
12

# イメージのダイジェストを確認
docker images --digests nginx
# → nginx  1.27-alpine  sha256:67682...  ...

8. daemon.json で Daemon を設定する(上級者向け)

Docker Daemon の動作は /etc/docker/daemon.json(Linux)で設定できます。変更後は systemctl restart docker が必要です。

// /etc/docker/daemon.json の例
{
  "data-root": "/mnt/docker-data",      // イメージ・コンテナの保存先(デフォルト: /var/lib/docker)
  "log-driver": "json-file",            // ログドライバ(デフォルト)
  "log-opts": {
    "max-size": "10m",                  // ログファイルの最大サイズ
    "max-file": "3"                     // 保持するローテーションファイル数
  },
  "storage-driver": "overlay2",         // ストレージドライバ(デフォルト)
  "registry-mirrors": [                 // Docker Hub のミラー(プル高速化)
    "https://mirror.example.com"
  ],
  "insecure-registries": [              // TLSなしで許可するレジストリ(開発用途のみ)
    "localhost:5000"
  ],
  "live-restore": true,                 // daemon 再起動時もコンテナを維持
  "default-runtime": "runc"            // デフォルトランタイム
}
設定ファイルのパス OS / 環境
/etc/docker/daemon.json Linux
%ProgramData%\docker\config\daemon.json Windows
Docker Desktop → Settings → Docker Engine Mac / Windows(Docker Desktop)

9. まとめ

Docker のアーキテクチャは 責務の分離で設計されています。CLI・Daemon・containerd・runc の4層がそれぞれの役割に集中することで、Kubernetes などの他システムとの統合もしやすくなっています。

コンポーネント 役割 通信
docker CLI ユーザー操作を REST API に変換して送信 REST(Unix socket / TCP+TLS)
dockerd 管理全般(イメージ・コンテナ・ネットワーク・ボリューム) REST(受信側)/ gRPC(containerd へ)
containerd イメージ取得・スナップショット・コンテナライフサイクル gRPC(受信)/ OCI(runc へ)
runc 実際にコンテナを作る(clone + overlayfs + cgroup + exec) OCI Runtime Spec(起動後に終了)
Registry イメージの保存・配布 OCI Distribution Spec(HTTPS)
✅ 次のステップ
1-3 では Docker のインストールと初期設定を行います。WSL2・Docker Desktop・Linux(apt/yum)それぞれの方法と、docker info で正しくセットアップされたことを確認する手順を解説します。今回学んだ各コンポーネントのバージョンがここで実際に確認できます。

参考リンク


Dockerの基礎を動画で体系的に学びませんか?

実務で使う基礎だけを3時間に凝縮。環境構築から丁寧に解説しています。

Udemy Docker入門講座 クーポン割引で講座を見る →

コメント

タイトルとURLをコピーしました