初心者向けDocker:実践的な入門ガイド

· 12分で読めます

📑 目次

Dockerは、悪名高い「私のマシンでは動く」問題を解決することで、ソフトウェア開発に革命をもたらしました。依存関係をシステムに直接インストールしてバージョンの競合に対処する代わりに、Dockerはアプリケーションが必要とするすべてを、あなたのノートパソコンから本番サーバーまで、どこでも同じように動作する隔離されたコンテナにパッケージ化します。

2026年にまだDockerを学んでいないなら、今がその時です。Dockerは、世界中で1,300万人以上の開発者に使用され、事実上すべての最新の開発ワークフローに統合されている、アプリケーションデプロイメントの事実上の標準となっています。

Dockerとは何か、なぜ気にする必要があるのか?

Dockerは、アプリケーションとそのすべての依存関係をコンテナと呼ばれる標準化されたユニットにラップするコンテナ化プラットフォームです。ソフトウェアを実行するために必要なすべてを含む、軽量でポータブルなパッケージと考えてください:コード、ランタイム、システムツール、ライブラリ、設定。

Docker以前、開発者は常に環境の不整合に直面していました。Node.js 18を搭載したMacBookではNode.jsアプリが完璧に動作するかもしれませんが、Node 16を実行している同僚のWindowsマシンではクラッシュする可能性があります。さらに悪いことに、システムライブラリの微妙な違いのために、開発環境では動作するのに本番環境では不可解に失敗することもあります。

Dockerは、一貫性のある再現可能な環境を作成することで、これらの頭痛の種を排除します。アプリケーションをコンテナ化すると、実行場所に関係なく同じように動作することが保証されます。

Dockerを使用する主な利点

プロのヒント: Dockerは本番デプロイメントだけのものではありません。多くの開発者は、インストールでシステムを乱雑にすることなく、データベース、キャッシュレイヤー、その他のサービスをローカルで実行するために使用しています。あるプロジェクトにはPostgreSQLが必要で、別のプロジェクトにはMySQLが必要ですか?競合することなく両方をコンテナで実行できます。

重要な概念:イメージ、コンテナ、Dockerfile

Dockerコマンドとワークフローに飛び込む前に、3つの中核概念を理解することが不可欠です。

Dockerイメージ

イメージは、アプリケーションを実行するために必要なすべてを含む読み取り専用のテンプレートです。オブジェクト指向プログラミングのクラスのようなものと考えてください—それは設計図であり、実行中のインスタンスではありません。

イメージはレイヤーで構築され、各レイヤーは変更または命令を表します。このレイヤーアーキテクチャにより、Dockerは変更されたレイヤーのみをダウンロードまたは保存すればよいため、効率的なストレージと転送が可能になります。

Docker Hub(公式レジストリ)から事前構築されたイメージをプルするか、独自のカスタムイメージを構築できます。人気のあるベースイメージには、nodepythonnginxpostgresredisなどがあります。

Dockerコンテナ

コンテナは、イメージの実行中のインスタンスです—クラスからインスタンス化されたオブジェクトのようなものです。1つのイメージから複数のコンテナを生成でき、それぞれが独自の分離されたファイルシステム、ネットワーク、プロセス空間で独立して実行されます。

コンテナは設計上一時的なものです。コンテナを停止して削除すると、ボリュームを使用して永続ストレージを明示的に構成していない限り、その中に書き込まれたデータは消えます(これについては後で詳しく説明します)。

Dockerfile

Dockerfileは、Dockerイメージを構築するための命令を含むテキストファイルです。基本的に、Dockerにアプリケーション環境を段階的に組み立てる方法を指示するレシピです。

Dockerfileの各命令は、イメージに新しいレイヤーを作成します。Dockerはこれらのレイヤーをインテリジェントにキャッシュするため、イメージの再構築は変更されたレイヤーのみを処理します—これにより、後続のビルドが非常に高速になります。

Node.jsアプリケーション用の最小限のDockerfileは次のとおりです:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

各命令が何をするかを分解してみましょう:

システムへのDockerのインストール

Dockerのインストールはオペレーティングシステムによって若干異なりますが、すべての主要なプラットフォームでプロセスは簡単です。

macOSとWindows

公式ウェブサイトからDocker Desktopをダウンロードしてインストールします。Docker Desktopには、必要なすべてが含まれています:Docker Engine、Docker CLI、Docker Compose、およびコンテナを管理するためのユーザーフレンドリーなGUI。

インストール後、Docker Desktopはバックグラウンドで実行され、設定と実行中のコンテナにすばやくアクセスするためのメニューバーアイコン(macOS)またはシステムトレイアイコン(Windows)を追加します。

Linux

Linuxでは、ディストリビューションのパッケージマネージャーを使用してDocker Engineを直接インストールします。Ubuntu/Debianの場合:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

グループメンバーシップを有効にするためにログアウトして再度ログインし、sudoなしでDockerコマンドを実行できるようにします。

インストールの確認

次を実行してDockerが正しく動作していることを確認します:

docker --version
docker run hello-world

2番目のコマンドは、小さなテストイメージをプルしてコンテナで実行します。ウェルカムメッセージが表示されれば、Dockerがインストールされ、正常に機能しています。

すべての開発者が必要とする必須Dockerコマンド

いくつかのコアコマンドをマスターすれば、日常的なDockerの使用の90%をカバーできます。包括的なリファレンステーブルは次のとおりです:

コマンド 何をするか 一般的なオプション
docker build -t myapp . 現在のディレクトリのDockerfileからイメージをビルド -tはイメージに名前でタグを付けます
docker run myapp イメージからコンテナを作成して起動 -d(デタッチ)、-p(ポートマッピング)、--name
docker ps 実行中のコンテナをリスト -aはすべてのコンテナを表示(停止中を含む)
docker stop [id] 実行中のコンテナを正常に停止 コンテナIDまたは名前を使用
docker rm [id] 停止したコンテナを削除 -fは実行中のコンテナの強制削除
docker images システム上のすべてのイメージをリスト -aは中間イメージを表示
docker rmi [image] イメージを削除 -fは強制削除
docker logs [id] コンテナの出力とログを表示 -fはログ出力をリアルタイムでフォロー
docker exec -it [id] sh 実行中のコンテナ内でインタラクティブシェルを開く -itはインタラクティブターミナルを有効化
docker pull [image] レジストリからイメージをダウンロード nginx:1.25のようにタグを指定
docker compose up docker-compose.ymlで定義されたすべてのサービスを起動 -dはバックグラウンドで実行
docker compose down composeファイルからすべてのコンテナを停止して削除 -vはボリュームも削除

実用的なコマンド例

ポートマッピングと環境変数を使用してコンテナを実行:

docker run -d \
  --name my-postgres \
  -p 5432:5432 \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

これはPostgreSQLをバックグラウンドで起動し、ポート5432をホストマシンにマッピングし、データベースパスワードを設定します。

コンテナからリアルタイムログを表示:

docker logs -f my-postgres

実行中のコンテナ内でコマンドを実行:

docker exec -it my-postgres psql -U postgres

これはコンテナ内でインタラクティブなPostgreSQLシェルを開きます。

クイックヒント: 完全なコンテナIDを入力する必要はありません。Dockerは一意のプレフィックスを受け入れるため、コンテナIDがa3f8b2c1d4e5の場合、他のコンテナIDがこれらの文字で始まらない限り、docker stop a3fを使用できます。

初めてのDockerfileを書く

実際のNode.jsアプリケーション用の完全なDockerfileを構築し、各決定を説明していきましょう。

# Alpine Linux上のNode.jsの特定のバージョンを使用(イメージサイズが小さい)
FROM node:20-alpine

# 必要に応じてシステム依存関係をインストール
RUN apk add --no-cache python3 make g++

# 作業ディレクトリを設定
WORKDIR /app

# パッケージファイルを最初にコピー(より良いレイヤーキャッシュのため)
COPY package*.json ./

# 本番依存関係のみをインストール
RUN npm ci --production --silent

# アプリケーションソースコードをコピー
COPY . .

# セキュリティのために非rootユーザーを作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001 && \
    chown -R nodejs:nodejs /app

# 非rootユーザーに切り替え
USER nodejs

# アプリケーションポートを公開
EXPOSE 3000

# コンテナステータスを監視するヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s \
  CMD node healthcheck.js || exit 1

# アプリケーションを起動
CMD ["node", "server.js"]

Dockerfileのベストプラクティス

キャッシュ効率のために順序が重要です。頻繁に変更される命令(COPY . .など)をDockerfileの最後近くに配置します。こうすることで、ソースコードのみが変更された場合、Dockerは依存関係のインストールのためにキャッシュされたレイヤーを再利用できます。

.dockerignoreファイルを使用して、ビルドコンテキストから不要なファイルを除外します:

node_modules
npm-debug.log
.git
.env
*.md
.DS_Store

これにより、コンテナに必要のないファイルをDockerがコピーするのを防ぎ、ビルドが高速化され、イメージサイズが削減されます。

マルチステージビルド

コンパイル言語やビルドツールを必要とするアプリケーションの場合、マルチステージビルドを使用して最終イメージを小さく保ちます:

# ビルドステージ
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 本番ステージ
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]

最終イメージには、本番依存関係とコンパイルされたアーティファクトのみが含まれ、ビルドツールやソースコードは含まれません。

マルチコンテナアプリケーション向けDocker Compose

実際のアプリケーションが単一のサービスで構成されることはめったにありません。通常、Webアプリケーション、データベース、キャッシュ、メッセージキュー、その他のサポートサービスが必要です。Docker Composeを使用すると、単一のYAML設定ファイルを使用してマルチコンテナアプリケーションを定義および管理できます。

典型的なWebアプリケーションスタック用の完全なdocker-compose.ymlは次のとおりです:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    volumes:
      - ./logs:/app/logs
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data
    restart: unless-stopped

  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - web
    restart: unless-stopped

volumes:
  pgdata:
  redisdata:

Docker Composeの操作

すべてのサービスをバックグラウンドで起動:

dock