Stack Overflow の開発者調査(2023年版)によれば、Dockerはプロフェッショナル開発者の約52%が業務で利用しており、コンテナ技術の中で最もシェアを持つツールとなっている。かつては「本番環境でしか動かない」という問題が開発現場で頻発していたが、Dockerの普及によってその状況は大きく変わった。本記事ではDockerの仕組みをゼロから丁寧に解説し、実務で即座に使えるdocker-compose構成例までを一気通貫で紹介する。
コンテナとは何か:仮想マシンとの違い
Dockerを理解する前提として、「コンテナ」という概念を掴むことが重要だ。コンテナを一言で表すなら「アプリケーションとその依存関係をひとつの箱に詰めたもの」である。引っ越し業者が家財道具を統一規格のコンテナに詰めて輸送するように、Dockerもアプリをどの環境でも同じように動かせる形で梱包する。
仮想マシン(VM)とコンテナは混同されがちだが、アーキテクチャが根本的に異なる。VMはハイパーバイザー上にOSごと仮想化するのに対し、コンテナはホストOSのカーネルを共有しながらプロセスレベルで分離する。
| 比較項目 | 仮想マシン(VM) | Dockerコンテナ |
|---|---|---|
| 起動時間 | 数分かかることが多い | 数秒以内 |
| イメージサイズ | GB単位が一般的 | MB単位が多い |
| OSの占有 | ゲストOSを丸ごと持つ | ホストOSカーネルを共有 |
| リソース消費 | CPUとメモリを多く消費 | 軽量で効率的 |
| 隔離レベル | 強い(ハードウェアレベル) | プロセスレベル |
| 用途の主軸 | インフラ全体の仮想化 | アプリの実行環境の統一 |
この違いによって、Dockerコンテナは開発・テスト・本番の環境差異を吸収しながら、VMより少ないオーバーヘッドで動作する。
Dockerの基本概念:イメージ・コンテナ・レジストリ
Dockerを使いこなすには、3つの中核概念を整理しておく必要がある。イメージ、コンテナ、レジストリだ。料理に例えるなら、イメージはレシピ、コンテナはそのレシピから作られた料理、レジストリはレシピ集が並ぶ本棚にあたる。
| 概念 | 説明 | 具体例 |
|---|---|---|
| イメージ(Image) | コンテナの設計図。読み取り専用のテンプレート | ubuntu:22.04、node:20-alpine |
| コンテナ(Container) | イメージから生成された実行インスタンス | 起動中のWebサーバー、DBプロセス |
| レジストリ(Registry) | イメージを保存・共有するリポジトリ | Docker Hub、GitHub Container Registry |
| Dockerfile | イメージをビルドするための命令書 | アプリのビルド手順を記述したテキストファイル |
| レイヤー(Layer) | イメージを構成する差分ファイルシステム | 変更分だけキャッシュされる仕組み |
| ボリューム(Volume) | コンテナ外でデータを永続化する領域 | DBのデータ、アップロードファイル |
イメージはレイヤー構造になっており、変更があった部分だけが差分として保存される。これにより、イメージの転送コストが大幅に削減される。
インストール方法:OS別の手順概要
Docker Desktop(macOS・Windows向け)とDocker Engine(Linux向け)の2種類が主な導入形態だ。開発用途ではDocker Desktopが便利で、GUIとCLIの両方を提供している。
| OS | 推奨インストール形態 | 主な手順の概要 |
|---|---|---|
| macOS(Apple Silicon含む) | Docker Desktop for Mac | 公式サイトからdmgファイルをダウンロードしてインストール。ARM対応版が提供されている |
| Windows 10/11 | Docker Desktop for Windows | WSL2バックエンドを有効化した上でインストーラーを実行する |
| Ubuntu / Debian | Docker Engine(CLIのみ) | aptリポジトリを追加後、docker-ceパッケージをインストールする |
| RHEL / Amazon Linux | Docker Engine または Podman | yumリポジトリ経由でインストール。RHELではPodmanが代替として推奨される場合もある |
| CI環境(GitHub Actions等) | 事前インストール済みランナー | ubuntu-latestランナーにはDockerが標準搭載されている |
インストール後、docker --version を実行してバージョンが表示されれば正常に導入されている。docker run hello-world でサンプルコンテナを起動し、動作を確認するのが定番の初期確認手順だ。
基本コマンド一覧:目的別リファレンス
Dockerの日常的な操作は数十種類のコマンドで構成されるが、最初に覚えるべきコマンドは限られている。目的ごとに整理すると、迷わず使えるようになる。
| 目的 | コマンド(操作の概要) | 補足 |
|---|---|---|
| イメージのダウンロード | docker pull [イメージ名:タグ] | Docker Hubからイメージを取得する |
| コンテナの起動 | docker run [オプション] [イメージ名] | -d でバックグラウンド起動、-p でポートマッピング |
| 実行中コンテナ一覧 | docker ps | -a を付けると停止中も含めて表示 |
| コンテナの停止 | docker stop [コンテナID or 名前] | グレースフルシャットダウンを試みる |
| コンテナの削除 | docker rm [コンテナID or 名前] | 停止後に削除する。-f で強制削除 |
| イメージ一覧 | docker images | ローカルに保存されたイメージを表示 |
| イメージの削除 | docker rmi [イメージID] | 使っていないイメージを整理する際に使用 |
| ログ確認 | docker logs [コンテナID or 名前] | -f を付けるとリアルタイムで追跡 |
| コンテナ内でコマンド実行 | docker exec -it [コンテナID] bash | -it で対話的ターミナルを開く |
| イメージのビルド | docker build -t [名前:タグ] [パス] | Dockerfileからイメージを生成する |
これらを組み合わせることで、イメージの取得から起動・デバッグ・後片付けまでの一連の操作をカバーできる。
Dockerfile の書き方:命令一覧と役割
DockerfileはDockerイメージをどのように構築するかを記述したテキストファイルだ。上から順番に命令が実行され、各命令が1つのレイヤーを作成する。
| 命令 | 役割 | 記述例(自然言語) |
|---|---|---|
| FROM | ベースイメージを指定する | node:20-alpine を基盤として使用する |
| WORKDIR | コンテナ内の作業ディレクトリを設定する | /app をワークディレクトリに設定する |
| COPY | ホストのファイルをコンテナにコピーする | package.jsonをコンテナの/appへコピー |
| RUN | ビルド時にコマンドを実行する | npm installを実行してパッケージをインストール |
| ENV | 環境変数を設定する | NODE_ENV=productionをセット |
| EXPOSE | コンテナが使用するポートを宣言する | ポート3000を公開する意図を示す |
| CMD | コンテナ起動時のデフォルトコマンドを指定する | node server.jsを起動コマンドとして設定 |
| ENTRYPOINT | CMDより優先度が高い起動コマンドを設定する | 必ず実行したいスクリプトに使用する |
| ARG | ビルド時に渡せる変数を定義する | バージョン番号などをビルド引数で渡す |
| LABEL | イメージにメタデータを付与する | 作成者やバージョン情報を付ける |
マルチステージビルドという手法を使えば、ビルド環境と実行環境を分離し、最終的なイメージサイズを大幅に削減できる。本番用イメージの最適化を行う際に特に有効だ。
Docker Compose:複数コンテナをまとめて管理する
実際のアプリケーションはWebサーバー・DBサーバー・キャッシュサーバーなど複数のコンテナで構成されることが多い。Docker Composeはそれらを1つのYAMLファイルで定義し、まとめて起動・停止できるツールだ。
| 構成要素 | 役割 | 実務でよく使う設定例 |
|---|---|---|
| services | アプリを構成する各コンテナを定義する | web、db、redis、worker など |
| image | 使用するDockerイメージを指定する | postgres:15、redis:7-alpine |
| build | Dockerfileからビルドする場合に指定する | contextとdockerfileのパスを指定 |
| ports | ホストとコンテナのポートをマッピングする | 3000:3000(ホスト:コンテナ) |
| volumes | データの永続化やファイル共有を設定する | ./data:/var/lib/postgresql/data |
| environment | 環境変数を渡す | POSTGRES_DB、POSTGRES_USER など |
| depends_on | 起動順序の依存関係を定義する | webサービスはdbの後に起動 |
| networks | コンテナ間の通信ネットワークを設定する | 同ネットワーク内は名前で通信できる |
| restart | コンテナの自動再起動ポリシーを設定する | always、unless-stopped、on-failure |
典型的なNext.js + PostgreSQL + Redisの構成では、3つのservicesを定義し、depends_onでdbとredisが起動してからwebが立ち上がるよう制御する。docker compose up -d 一発でローカル開発環境全体が起動する状態を作れる。
実務でのユースケース:現場で使われるDocker活用パターン
Dockerが現場でどのように使われているかを知ることで、学習の優先順位が明確になる。
| ユースケース | 具体的な使い方 | 得られるメリット |
|---|---|---|
| ローカル開発環境の統一 | 全メンバーがdocker composeで同一環境を起動 | 「自分のPCでは動く」問題が解消される |
| CI/CDパイプライン | GitHub ActionsでDockerイメージをビルド・テスト | 本番と同等の環境でテストが実行できる |
| マイクロサービス構成 | サービスごとにコンテナを分離して運用 | 独立したデプロイ・スケーリングが可能 |
| レガシーアプリの移行 | 依存関係が複雑なアプリをコンテナ化 | ホストOS汚染なしに古いランタイムを動かせる |
| 本番環境デプロイ | ECS・GKE・Cloud Runへのコンテナデプロイ | イメージ単位でロールバック・スケールが容易 |
| データベースの一時利用 | テスト用のPostgreSQLやMongoDBをコンテナで起動 | ホストにDBをインストールせず使い捨てにできる |
| セキュリティスキャン | イメージ内の脆弱性をCI工程で自動チェック | TrivyやSnoykで脆弱なパッケージを早期発見 |
特にローカル開発環境の統一とCI/CDへの活用は、チーム開発の生産性を劇的に改善するユースケースとして多くの現場で採用されている。
学習ロードマップ:段階別の習得ステップ
Dockerは概念が多く、最初は何から手をつければよいか迷いやすい。以下に段階別の学習ロードマップを示す。
| フェーズ | 学習内容 | 目安期間 | 到達目標 |
|---|---|---|---|
| 入門(Phase 1) | コンテナ・イメージの概念理解、docker runで既存イメージを動かす | 1〜2日 | hello-worldとnginxコンテナが起動できる |
| 基礎(Phase 2) | Dockerfileの書き方、自作イメージのビルドとpush | 3〜5日 | 自分のアプリをコンテナ化できる |
| 実践(Phase 3) | docker-composeで複数コンテナを管理する | 1〜2週間 | WebアプリとDBをcomposeで動かせる |
| 応用(Phase 4) | ネットワーク・ボリューム・マルチステージビルドの理解 | 2〜4週間 | 本番を意識したイメージ最適化ができる |
| 発展(Phase 5) | Kubernetes入門、ECS・GKE等のコンテナオーケストレーション | 1〜3ヶ月 | クラウド環境へのデプロイが自走できる |
Phase 3までをしっかり習得すれば、現場でのDockerによる開発環境構築やCI対応は概ねこなせるようになる。Phase 4以降はプロダクション対応を目指すエンジニア向けの領域だ。
まとめ:あなたのチームはDocker導入後に何を変えたいか
Dockerは「環境の差異」という古くからある開発現場の問題に対して、シンプルかつ強力な解を提供してきた。コンテナの概念からDockerfile・docker-composeまで、一度体系的に理解すれば、開発効率とデプロイの信頼性が大きく向上する。
一方で、Dockerを導入すれば自動的にすべての問題が解決するわけではない。チームの運用ルールや学習コスト、本番環境との整合性をどう保つかという設計判断は、それぞれの現場で問い直す必要がある。
あなたのチームでDockerを導入したとき、最初に「コンテナ化」したいのはどのアプリケーションだろうか。そして、その移行によってチームのどの課題を解消したいと考えているだろうか。