「自分のパソコンでは動いたのに、本番環境では動かない」——そんな悩みを解消するために生まれたのがDockerです。この記事では、Dockerの基本概念から構成要素・作成手順・レイヤーの仕組みまでをゼロから丁寧に解説します。これからDockerを学び始めるエンジニアや、なんとなく使っていて仕組みをきちんと理解したい方に最適な内容です。
Dockerとは?まずは全体像を掴もう
Dockerとは、アプリケーションを「コンテナ」という軽量な実行環境にまとめて動かすためのプラットフォームです。名前の由来はコンテナを船で運ぶ港湾労働者(Docker)から来ており、アプリを「コンテナ」に詰めてどこでも同じ状態で運べるというコンセプトを表しています。
従来の仮想マシン(VM)と比べると、DockerコンテナはホストOSのカーネルを共有するため起動が速く、消費リソースが少ないのが最大の特徴です。

| 比較項目 | 仮想マシン(VM) | Docker |
|---|---|---|
| OS | ゲストOSが必要 | ホストOSのカーネルを共有 |
| 起動時間 | 分単位 | 秒単位 |
| リソース消費 | 大きい | 小さい |
| 分離レベル | 強い(カーネルレベル) | プロセスレベル |
Dockerの構成要素
Dockerを理解するうえで欠かせない3つのコアコンセプトがあります。「イメージ・コンテナ・レジストリ」です。

- Registry:Docker Hubなどのイメージ保存庫。
docker pullでイメージを取得する - Image:読み取り専用のテンプレート。Dockerfileからビルドして作成する
- Container:イメージを実行した状態。1つのイメージから複数起動できる
例え:イメージ=クッキーの型、コンテナ=焼き上がったクッキー、レジストリ=型のカタログ(Docker Hub)。ひとつの型から何個でも同じクッキーが焼けます。
クライアント・サーバーモデル
Dockerのアーキテクチャはクライアント・サーバーモデルを採用しています。端末で叩く docker コマンドがクライアント、実際の処理を担う dockerd(Dockerデーモン)がサーバーです。

図解のポイントをまとめると——
① あなたが打つコマンド(docker CLI)=クライアントdocker run nginx などのコマンドは、あくまで「指示書」を送るだけです。実際にコンテナを起動する処理はしません。
② dockerd(Dockerデーモン)=サーバー
バックグラウンドで常時動いているプロセスです。CLI からの指示を REST API 経由で受け取り、コンテナの起動・停止・イメージ管理・ネットワーク設定など、すべての実処理を担います。
③ CLI と Daemon は同じPC上にある(普段は)
ローカル開発では同じマシン上で動いていますが、実はネットワーク越しに別マシンの Daemon に接続することも可能です(DOCKER_HOST 環境変数で切り替えられます)。これがクライアント・サーバー分離の恩恵です。
④ Docker Hub とのやり取りは必ず Daemon 経由docker pull と打っても、CLI が直接 Docker Hub にアクセスするのではなく、Daemon が代わりに通信してイメージを取得します。
Dockerの作成手順(ステップバイステップ)
- Dockerのインストール:公式サイトからDocker Desktop(Mac/Windows)またはDocker Engine(Linux)をインストールします。インストール後、
docker --versionでバージョンが表示されれば成功です。 - Dockerfileの作成:コンテナの設計図となるテキストファイルです。「どのOSをベースにするか」「何をインストールするか」「何を起動するか」を記述します。
- Imageのビルド(docker build):Dockerfileを元にイメージを作成します。
docker build -t myapp:1.0 .のようにタグを付けてビルドします。 - コンテナの起動(docker run):ビルドしたイメージからコンテナを起動します。
-pでポートのマッピング、-dでバックグラウンド実行が指定できます。
以下はNode.jsアプリを例にしたDockerfileのサンプルです。
# ベースイメージの指定(Node.js 20 LTS)
FROM node:20-alpine
# 作業ディレクトリを設定
WORKDIR /app
# 依存関係ファイルをコピーしてインストール
COPY package*.json ./
RUN npm install --production
# アプリのソースをコピー
COPY . .
# コンテナが使用するポートを宣言
EXPOSE 3000
# コンテナ起動時に実行するコマンド
CMD ["node", "index.js"]ビルドと起動のコマンドは以下の通りです。
# イメージをビルド(-t でタグ名指定、. はカレントディレクトリ)
$ docker build -t myapp:1.0 .
# コンテナを起動(-d バックグラウンド、-p ポートマッピング)
$ docker run -d -p 3000:3000 myapp:1.0
# 動いているコンテナを確認
$ docker psdocker run は内部的に docker create(コンテナ作成)と docker start(コンテナ起動)を組み合わせた便利コマンドです。
Dockerのレイヤーとは
Dockerイメージは、積み重ねられた「レイヤー(層)」で構成されています。Dockerfileの各コマンド命令(FROM・RUN・COPY など)が、それぞれ1つのレイヤーを生成します。
ケーキで例えると、レイヤーはスポンジ生地の層です。一番下がベース(小麦粉+卵)、その上にクリーム、さらにフルーツ……と積み重なります。変更があった層より上だけを焼き直す(再ビルドする)イメージです。
| レイヤー | 命令 | 内容 |
|---|---|---|
| 最上位 | CMD / ENTRYPOINT | コンテナ起動時の命令(読み書き可能なコンテナレイヤー) |
| ↑ | COPY / ADD | アプリのソースコードや設定ファイル |
| ↑ | RUN(依存関係) | npm install / apt-get install など |
| ↑ | RUN(環境設定) | WORKDIRの設定や環境変数など |
| 最下位 | FROM(ベース) | ubuntu, alpine, node など |
レイヤーの最大のメリットは「キャッシュ」です。変更のないレイヤーは再利用されるため、2回目以降のビルドは劇的に速くなります。ベストプラクティスとして、変更頻度の低い命令(パッケージインストール)を先に書き、変更頻度の高い命令(ソースコードのコピー)を後に書くようにしましょう。
⚠️ レイヤー最適化のコツ:RUN 命令は可能な限り1つにまとめましょう。
例:RUN apt-get update && apt-get install -y curl git && rm -rf /var/lib/apt/lists/*
ホストから見たDockerはプロセスである
Dockerコンテナは「独立した仮想サーバー」のように見えますが、ホストOS側から見ると実は「ただのプロセス」です。仮想マシン(VM)は専用のOSカーネルを持ちますが、Dockerコンテナはホストのカーネルをそのまま共有します。
「namespace」(名前空間)と「cgroup」(コントロールグループ)というLinuxの機能によって、プロセスが隔離されているように見えているだけです。

$ ps aux | grep docker
USER PID %CPU %MEM COMMAND
root 1234 0.1 0.5 node index.js ← Container A の正体
root 5678 0.3 1.2 nginx: master ← Container B の正体
root 9012 0.0 0.8 python app.py ← Container C の正体| Linuxの仕組み | 役割 |
|---|---|
| namespace(名前空間) | PID・ネットワーク・ファイルシステム・ユーザーなどを隔離。コンテナ内から外が見えないようにする「壁」 |
| cgroup(コントロールグループ) | CPU・メモリ・I/Oなどのリソース使用量を制限する「枠」 |
この仕組みのおかげで、コンテナはVMと違ってホストのカーネルを共有でき、起動が秒単位(VMは分単位)で済むのです。
知っておくべきその他の重要知識
① Volumeとバインドマウント
コンテナは停止・削除するとデータが消えます。データを永続化するにはVolumeを使います。
# ボリュームを作成してコンテナにマウント
$ docker volume create mydata
$ docker run -v mydata:/data myapp:1.0上記コマンドにより mydata(論理名) はホストOS上に作成されますが、場所は /home/yourname/mydata のような任意のパスではなく、Dockerが管理する専用ディレクトリ(/var/lib/docker/volumes/mydata/_data)に自動で作られます。/data はコンテナ内に作成されます。そしてこの2つが橋でつながれた状態になります。

② Docker Compose(複数コンテナの管理)
Webサーバー・データベース・キャッシュなど、実際のアプリは複数のコンテナで構成されます。docker-compose.yml に定義を書けば、docker compose up 一発で全部起動できます。
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
volumes:
pgdata:③ .dockerignoreでビルドを高速化
.gitignore と同様に、ビルドコンテキストから除外するファイルを指定します。
node_modules
.git
.env
*.log
dist
coverage④ マルチステージビルド
ビルド環境と実行環境を分けることで、本番イメージを最小限のサイズに抑えられます。GoやJavaなど、コンパイルが必要な言語で特に効果的です。
参考リソース
| カテゴリ | リソース名 | URL |
|---|---|---|
| 公式ドキュメント | Docker 公式ドキュメント | https://docs.docker.com |
| 入門チュートリアル | Docker Getting Started | https://docs.docker.com/get-started |
| イメージ検索 | Docker Hub | https://hub.docker.com |
| セキュリティ | Docker Security Best Practices | https://docs.docker.com/engine/security/ |
| Compose | Compose ファイルリファレンス | https://docs.docker.com/compose/compose-file/ |


コメント