開発者のためのDocker:イメージ、コンテナ、Compose
あなたのマシンでは動作するコードも、チームメイトが実行しようとすると、依存関係の欠落、バージョン競合、難解なエラーに遭遇します。Dockerは、アプリケーションとその環境を単一のポータブルなユニットにパッケージ化することでこれを解決します。このガイドでは、Dockerの基本であるイメージ、コンテナ、Composeを学び、シンプルなWebアプリをコンテナ化する実践的な手順を紹介します。
Dockerとは?
Dockerは、アプリケーションをコンテナ内でビルド、実行、共有するためのプラットフォームです。コンテナは、ソフトウェアの実行に必要なすべて(コード、ランタイム、システムツール、ライブラリ、設定)を含む軽量でスタンドアロンな実行可能パッケージです。コンテナはアプリケーションを互いに、そしてホストシステムから隔離し、開発、テスト、本番環境での一貫性を保証します。
イメージ vs コンテナ:設計図と実行インスタンス
イメージはコンテナを定義する読み取り専用のテンプレートです。オブジェクト指向プログラミングのクラスのようなものです。コンテナはイメージの実行可能なインスタンスで、オブジェクトのようなものです。同じイメージから多数のコンテナを作成できます。
イメージはDockerfileという指示を含むテキストファイルからビルドされます。コンテナはdocker runで起動されます。
主な違い
| イメージ | コンテナ |
|---|---|
| 読み取り専用テンプレート | 実行可能インスタンス |
docker buildでビルド | docker runで起動 |
| レジストリ(例:Docker Hub)に保存 | ホスト上で実行 |
| レイヤードファイルシステム | 上に書き込み可能レイヤー |
最初のイメージをビルドする
シンプルなNode.jsアプリをコンテナ化しましょう。Dockerfileという名前のファイルを作成します:
# 公式のNode.jsランタイムを親イメージとして使用
FROM node:18-alpine
# 作業ディレクトリを設定
WORKDIR /app
# package.jsonをコピーして依存関係をインストール
COPY package*.json ./
RUN npm install
# アプリケーションの残りをコピー
COPY . .
# アプリが実行されるポートを公開
EXPOSE 3000
# アプリを実行するコマンドを定義
CMD ["node", "server.js"]
タグを付けてイメージをビルドします:
docker build -t my-node-app .
-tフラグはイメージに名前とタグを付けます。最後の.はビルドコンテキスト(現在のディレクトリ)を指定します。
コンテナを実行する
イメージからコンテナを起動します:
docker run -p 3000:3000 -d --name my-app my-node-app
-p 3000:3000:ホストのポート3000をコンテナのポート3000にマッピングします。-d:コンテナをデタッチドモード(バックグラウンド)で実行します。--name my-app:参照しやすいようにコンテナに名前を割り当てます。
実行中のコンテナを確認するにはdocker psを使用します。コンテナを停止するにはdocker stop my-appを使用します。
ボリュームでデータを管理する
コンテナは一時的です。コンテナ内のデータはコンテナが削除されると失われます。データを永続化するにはボリュームを使用します。たとえば、データベースデータを永続化するには:
docker run -v my-db-data:/var/lib/mysql -d mysql:8
これにより、コンテナの再起動や削除後も存続する名前付きボリュームmy-db-dataが作成されます。
Docker Composeでマルチコンテナアプリを簡素化する
実際のアプリケーションはしばしば複数のサービス(Webサーバー、データベース、キャッシュなど)を必要とします。Docker Composeを使用すると、単一のYAMLファイルでマルチコンテナアプリを定義して実行できます。
docker-compose.ymlを作成します:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
postgres_data:
すべてを実行するには:
docker compose up -d
ComposeはWebイメージをビルドし、データベースを起動し、共有ネットワーク上でそれらを接続します。depends_onはデータベースがWebサービスより先に起動することを保証します。
必須のDockerコマンド
docker ps -a:すべてのコンテナ(停止中を含む)を一覧表示します。docker images:イメージを一覧表示します。docker logs my-app:コンテナのログを表示します。docker exec -it my-app sh:実行中のコンテナ内でシェルを開きます。docker compose down:Composeファイルで定義されたコンテナ、ネットワーク、ボリュームを停止して削除します。
開発のベストプラクティス
- .dockerignoreを使用する:ビルドコンテキストからファイル(例:node_modules)を除外し、ビルドを高速化します。
- マルチステージビルドを活用する:本番イメージを小さく保ちます。たとえば、1つのステージでアプリをビルドし、必要なアーティファクトのみをスリムなランタイムイメージにコピーします。
- バージョンを固定する:Dockerfileで(例:
node:latestの代わりにnode:18-alpine)再現性のためにバージョンを固定します。 - 非rootユーザーとして実行する:セキュリティのために。ファイルをコピーした後に
USER nodeを追加します。
FAQ
Dockerイメージとコンテナの違いは何ですか?
イメージはアプリケーションとその環境を定義する読み取り専用のテンプレートです。コンテナはそのイメージの実行インスタンスです。同じイメージから複数のコンテナを作成できます。
Dockerでデータを永続化するにはどうすればよいですか?
ボリュームを使用します。名前付きボリューム(例:docker run -v my-vol:/data)はコンテナのファイルシステム外に保存され、コンテナの再起動や削除後も存続します。
Docker Composeはいつ使用すべきですか?
アプリケーションが一緒に実行する必要がある複数のサービス(例:Web + データベース)で構成されている場合にComposeを使用します。開発とテストのためのオーケストレーションを簡素化します。
次のプロジェクトをコンテナ化する準備はできましたか?シンプルなDockerfileを書いて最初のコンテナを実行することから始めましょう。その他の開発者ツールについては、コンテナ化されたサービスをテストする際にAPIレスポンスを検証するためのTryQuickToolBoxのJSON Formatterをチェックしてください。