「docker run nginx を打つと何が起きるのか?」——この問いに答えられるかどうかが、Dockerを”使える人”から”わかっている人”への分かれ目です。
本記事では Docker Client・Docker Daemon・containerd・runc・Docker Hub の5つのコンポーネントを図解し、コマンド1行がコンテナ起動に至るまでの全フローをシミュレータで体感してもらいます。1-5 で学んだ名前空間・cgroupsがどこで使われるかも繋がります。
目次
- Docker の全体像:3つの主要コンポーネント
- Docker Client — CLI と REST API
- Docker Daemon(dockerd)— 司令塔
- containerd と runc — 実行を担う内部ランタイム
- docker run のフローを追う
- Docker Hub とレジストリ
- イメージ名の完全な形式
- daemon.json で Daemon を設定する(上級者向け)
- まとめ
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 compose
Client と Host は同じマシンにあることも(ローカル開発)、ネットワーク越しに別のサーバーにあることも(リモートデプロイ)あります。

2. Docker Client — CLI と REST API
ユーザーが直接操作するのは Docker Client です。docker run・docker ps・docker 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
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 # → リモートデーモンに接続
コンテナに
-v /var/run/docker.sock:/var/run/docker.sock でソケットをマウントすると、そのコンテナは Docker Daemon を完全制御できます。実質的にホストrootと同等の権限になるため、信頼できるコンテナ以外には決してマウントしないでください(第8章・セキュリティで詳しく解説)。3. Docker Daemon(dockerd)— 司令塔
Docker Daemon(dockerd)は 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年)で分離されました。
| コンポーネント | 規格 | 主な責務 | 特記事項 |
|---|---|---|---|
| containerd | CRI(Container Runtime Interface) | イメージの取得・アンパック・スナップショット管理・コンテナのライフサイクル | Kubernetes でも直接採用。CNCF 卒業プロジェクト |
| runc | OCI Runtime Specification | clone() で名前空間生成・OverlayFS マウント・cgroup 設定・exec() でプロセス起動 |
OCI の参照実装。1-5 で学んだ仕組みはすべてここで実行される |
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 Hub(registry-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 以上 | 無制限 | 無制限 |
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 Engine API リファレンス(公式) — REST API の全エンドポイントを確認できる Swagger ドキュメント
- containerd 公式サイト — CNCF 卒業プロジェクト。Kubernetes でも採用されているランタイム
- opencontainers/runc(GitHub) — OCI 準拠の参照コンテナランタイム実装
- Docker Hub(公式) — 公式・コミュニティ製イメージの検索と取得
- OCI Distribution Specification(GitHub) — レジストリ API の業界標準仕様



コメント