TechHub

エンジニアの成長をサポートする技術情報サイト

← 記事一覧に戻る

Dockerとは?コンテナ技術の基礎と実践的な使い方

公開日: 2024年2月24日 著者: mogura
Dockerとは?コンテナ技術の基礎と実践的な使い方

疑問

Dockerとは何で、どのように使えばよいのでしょうか?コンテナ技術の基礎から、実践的な使い方まで一緒に学んでいきましょう。

導入

Dockerは、アプリケーションをコンテナとしてパッケージ化し、どこでも同じように実行できるようにする技術です。開発環境と本番環境の違いを解消し、デプロイを簡単にする強力なツールです。

本記事では、Dockerとコンテナ技術の基本概念から、Dockerfileの書き方、コンテナの管理、Docker Composeの使い方まで、実践的な例とともに詳しく解説していきます。

Dockerのイメージ

解説

1. Dockerとコンテナ技術とは

Dockerは、アプリケーションをコンテナとしてパッケージ化するプラットフォームです。コンテナは、アプリケーションとその依存関係を一緒にパッケージ化し、どこでも同じように実行できるようにします。仮想マシンと比較して、軽量で高速な起動が可能です。

コンテナと仮想マシンの違い

コンテナは仮想マシンと比較して、軽量で高速な起動が可能です。ホストOSのカーネルを共有するため、リソース消費が少なく、効率的です。

コンテナと仮想マシンの主な違い:

仮想マシン(VM)
- 完全なOSをエミュレート
- リソース消費が大きい
- 起動に時間がかかる
- ホストOSから完全に分離

コンテナ
- ホストOSのカーネルを共有
- リソース消費が少ない
- 起動が高速
- 軽量で効率的

メリット
- 一貫性: 開発環境と本番環境が同じ
- 移植性: どこでも同じように実行できる
- 効率性: リソースを効率的に使用
- スケーラビリティ: 簡単にスケールアップ/ダウン

Dockerの主要コンポーネント

Dockerの主要コンポーネントには、Dockerイメージ、Dockerコンテナ、Dockerfile、Docker Hubがあります。

Dockerの主要コンポーネント:

Dockerイメージ
- アプリケーションとその依存関係を含む読み取り専用のテンプレート
- 複数のレイヤーで構成される
- 再利用可能

Dockerコンテナ
- Dockerイメージの実行インスタンス
- 読み書き可能なレイヤーが追加される
- 独立した実行環境

Dockerfile
- イメージを構築するための手順書
- 命令の集合で構成される

Docker Hub
- 公開されているDockerイメージのリポジトリ
- 公式イメージやコミュニティイメージが利用可能

2. Dockerのインストールと基本操作

Dockerのインストール方法と、基本的なコマンドの使い方を学びましょう。Docker Desktopを使用することで、Windows、macOS、Linuxで簡単にDockerを使用できます。

Dockerのインストール

Dockerは、Docker Desktopを使用することで簡単にインストールできます。Windows、macOS、Linuxで利用可能です。

Dockerのインストール方法:

Docker Desktop
- Windows、macOS、Linuxで利用可能
- GUIとCLIの両方を提供
- https://www.docker.com/products/docker-desktop からダウンロード

Linuxでのインストール

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install docker.io
sudo systemctl start docker
sudo systemctl enable docker

# インストール確認
docker --version

基本的なDockerコマンド

Dockerの基本的なコマンドには、イメージの操作(pull、images、rmi)とコンテナの操作(run、ps、stop、rm、logs)があります。

Dockerの基本的なコマンド:

イメージの操作

# イメージの一覧表示
docker images

# イメージの検索
docker search nginx

# イメージのダウンロード
docker pull nginx

# イメージの削除
docker rmi nginx


コンテナの操作
# コンテナの実行
docker run nginx

# バックグラウンドで実行
docker run -d nginx

# ポートマッピング
docker run -d -p 8080:80 nginx

# コンテナの一覧表示
docker ps

# すべてのコンテナ(停止中も含む)
docker ps -a

# コンテナの停止
docker stop <container_id>

# コンテナの削除
docker rm <container_id>

# コンテナのログ確認
docker logs <container_id>

Dockerの基本的な使い方

Dockerの基本的な使い方の例です。

# 1. Nginxイメージをダウンロード
docker pull nginx

# 2. Nginxコンテナを実行(ポート8080でアクセス可能)
docker run -d -p 8080:80 --name my-nginx nginx

# 3. コンテナの状態を確認
docker ps

# 4. コンテナのログを確認
docker logs my-nginx

# 5. コンテナ内でコマンドを実行
docker exec -it my-nginx bash

# 6. コンテナを停止
docker stop my-nginx

# 7. コンテナを削除
docker rm my-nginx

# 8. イメージを削除
docker rmi nginx

3. Dockerfileの書き方

Dockerfileは、Dockerイメージを構築するための手順書です。適切にDockerfileを書くことで、効率的でセキュアなイメージを作成できます。レイヤーキャッシュを活用し、イメージサイズを最小化することが重要です。

基本的なDockerfile

基本的なDockerfileは、FROM、WORKDIR、COPY、RUN、EXPOSE、CMDなどの命令で構成されます。

基本的なDockerfileの例:

# ベースイメージを指定
FROM node:18-alpine

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

# 依存関係ファイルをコピー
COPY package*.json ./

# 依存関係をインストール
RUN npm install

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

# ポートを公開
EXPOSE 3000

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


各命令の説明
- FROM: ベースイメージを指定
- WORKDIR: 作業ディレクトリを設定
- COPY: ファイルをコピー
- RUN: コマンドを実行
- EXPOSE: ポートを公開
- CMD: コンテナ起動時に実行するコマンド

Dockerfileのベストプラクティス

Dockerfileを書く際は、軽量なベースイメージを使用し、レイヤーキャッシュを活用し、不要なファイルを除外し、マルチステージビルドを使用することが推奨されます。

Dockerfileを書く際のベストプラクティス:

1. 軽量なベースイメージを使用

# 良い例: Alpine Linuxを使用
FROM node:18-alpine

# 悪い例: フルサイズのイメージ
FROM node:18


2. レイヤーキャッシュを活用
# 良い例: 依存関係を先にコピー
COPY package*.json ./
RUN npm install
COPY . .

# 悪い例: すべてを一度にコピー
COPY . .
RUN npm install


3. 不要なファイルを除外
# .dockerignoreファイルを作成
node_modules
.git
.env
*.log


4. マルチステージビルドを使用
# ビルドステージ
FROM node:18-alpine AS builder
WORKDIR /app
COPY . .
RUN npm run build

# 実行ステージ
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm install --production
CMD ["node", "dist/index.js"]

実践的なDockerfileの例

実践的なDockerfileの例です。

# Node.jsアプリケーション用のDockerfile

# ビルドステージ
FROM node:18-alpine AS builder

WORKDIR /app

# 依存関係ファイルをコピー
COPY package*.json ./

# 依存関係をインストール
RUN npm ci --only=production

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

# アプリケーションをビルド
RUN npm run build

# 実行ステージ
FROM node:18-alpine

WORKDIR /app

# ビルド成果物をコピー
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./

# 非rootユーザーを作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# ユーザーを変更
USER nodejs

# ポートを公開
EXPOSE 3000

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js

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

# .dockerignoreファイルの例
# node_modules
# .git
# .env
# *.log
# dist
# .dockerignore

4. Docker Composeの使い方

Docker Composeは、複数のコンテナを定義し、管理するためのツールです。docker-compose.ymlファイルを使用して、アプリケーションとその依存サービス(データベース、キャッシュなど)を一緒に管理できます。

docker-compose.ymlの書き方

docker-compose.ymlファイルを使用して、複数のコンテナを定義し、管理できます。servicesセクションで各サービスを定義します。

基本的なdocker-compose.ymlの例:

version: '3.8'

services:
  # Webアプリケーション
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
    depends_on:
      - db
      - redis
    volumes:
      - ./logs:/app/logs

  # データベース
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # Redis
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

Docker Composeのコマンド

Docker Composeの基本的なコマンドには、up、down、logs、build、restart、psなどがあります。

Docker Composeの基本的なコマンド:

# サービスを起動
docker-compose up

# バックグラウンドで起動
docker-compose up -d

# サービスを停止
docker-compose stop

# サービスを停止して削除
docker-compose down

# ログを確認
docker-compose logs

# 特定のサービスのログ
docker-compose logs web

# サービスを再ビルド
docker-compose build

# サービスを再起動
docker-compose restart

# サービスの状態を確認
docker-compose ps

実践的なdocker-compose.ymlの例

実践的なdocker-compose.ymlの例です。

# docker-compose.yml
version: '3.8'

services:
  # フロントエンド
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://backend:5000
    depends_on:
      - backend
    volumes:
      - ./frontend:/app
      - /app/node_modules

  # バックエンド
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    volumes:
      - ./backend:/app
      - /app/node_modules

  # データベース
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  # Redis
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  # Nginx(リバースプロキシ)
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - frontend
      - backend

volumes:
  postgres_data:
  redis_data:

# 使用例
# docker-compose up -d
# docker-compose logs -f
# docker-compose down

5. ボリュームとデータの永続化

Dockerコンテナは、デフォルトではデータが永続化されません。コンテナを削除すると、データも失われます。ボリュームを使用することで、データを永続化し、コンテナ間でデータを共有できます。

ボリュームの種類

Dockerのボリュームには、名前付きボリューム、バインドマウント、tmpfsマウントがあります。用途に応じて適切な方法を選択します。

Dockerのボリュームの種類:

名前付きボリューム

# ボリュームを作成
docker volume create mydata

# ボリュームを使用してコンテナを実行
docker run -v mydata:/data nginx

# ボリュームの一覧表示
docker volume ls

# ボリュームの詳細確認
docker volume inspect mydata


バインドマウント
# ホストのディレクトリをマウント
docker run -v /host/path:/container/path nginx

# 相対パスも使用可能
docker run -v ./data:/data nginx


tmpfsマウント
# メモリ上にマウント(一時的なデータ用)
docker run --tmpfs /tmp nginx

Docker Composeでのボリューム

Docker Composeでは、volumesセクションで名前付きボリュームを定義し、servicesセクションで使用します。

Docker Composeでボリュームを使用する例:

version: '3.8'

services:
  db:
    image: postgres:15-alpine
    volumes:
      # 名前付きボリューム
      - postgres_data:/var/lib/postgresql/data
      # バインドマウント(設定ファイル)
      - ./postgres.conf:/etc/postgresql/postgresql.conf
    
  app:
    build: .
    volumes:
      # 開発時のホットリロード用
      - ./src:/app/src
      # ログファイル
      - ./logs:/app/logs

volumes:
  postgres_data:

ボリュームの使用例

ボリュームを使用する実践的な例です。

# 1. 名前付きボリュームの作成と使用

# ボリュームを作成
docker volume create db_data

# ボリュームを使用してPostgreSQLコンテナを実行
docker run -d \
  --name postgres \
  -v db_data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=password \
  postgres:15-alpine

# 2. バインドマウントの使用(開発時)

# ホストのディレクトリをマウント
docker run -d \
  --name app \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/logs:/app/logs \
  myapp

# 3. Docker Composeでのボリューム

# docker-compose.yml
version: '3.8'

services:
  db:
    image: postgres:15-alpine
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    
  app:
    build: .
    volumes:
      - ./src:/app/src:ro  # 読み取り専用
      - app_logs:/app/logs

volumes:
  db_data:
  app_logs:

# 4. ボリュームのバックアップ

# ボリュームの内容をバックアップ
docker run --rm \
  -v db_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/db_backup.tar.gz /data

# 5. ボリュームのリストア

docker run --rm \
  -v db_data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/db_backup.tar.gz -C /

6. ネットワークとコンテナ間通信

Dockerネットワークを使用することで、コンテナ間で通信できます。デフォルトのブリッジネットワークやカスタムネットワークを使用することで、コンテナを論理的にグループ化し、セキュアに通信できます。

Dockerネットワークの種類

Dockerネットワークには、ブリッジネットワーク、ホストネットワーク、noneネットワークがあります。用途に応じて適切なネットワークを選択します。

Dockerネットワークの種類:

ブリッジネットワーク

# デフォルトのブリッジネットワーク
# 同じネットワーク上のコンテナは名前で通信可能

docker network create mynetwork

docker run -d --name app1 --network mynetwork nginx
docker run -d --name app2 --network mynetwork nginx

# app2からapp1にアクセス可能
# curl http://app1


ホストネットワーク
# ホストのネットワークを直接使用
# パフォーマンスが良いが、セキュリティリスクあり

docker run --network host nginx


noneネットワーク
# ネットワークを無効化
# 完全に分離された環境

docker run --network none nginx

Docker Composeでのネットワーク

Docker Composeでは、デフォルトでネットワークが作成され、サービス名で通信できます。カスタムネットワークも定義できます。

Docker Composeでは、デフォルトでネットワークが作成されます:

version: '3.8'

services:
  web:
    build: .
    # 同じネットワーク上のサービスは名前で通信可能
    # http://db:5432 でデータベースにアクセス可能
  
  db:
    image: postgres:15-alpine
    # webサービスから db:5432 でアクセス可能

# カスタムネットワークの定義
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

services:
  web:
    networks:
      - frontend
  
  api:
    networks:
      - frontend
      - backend
  
  db:
    networks:
      - backend

ネットワークの使用例

Dockerネットワークを使用する実践的な例です。

# 1. カスタムネットワークの作成

docker network create mynetwork

# 2. ネットワークに接続してコンテナを実行

docker run -d --name web --network mynetwork nginx
docker run -d --name db --network mynetwork postgres:15-alpine

# 3. 既存のコンテナをネットワークに接続

docker network connect mynetwork existing_container

# 4. ネットワークの一覧表示

docker network ls

# 5. ネットワークの詳細確認

docker network inspect mynetwork

# 6. Docker Composeでのネットワーク設定

# docker-compose.yml
version: '3.8'

services:
  frontend:
    build: ./frontend
    networks:
      - frontend
  
  backend:
    build: ./backend
    networks:
      - frontend
      - backend
    environment:
      - DATABASE_URL=postgresql://db:5432/mydb
  
  db:
    image: postgres:15-alpine
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 外部へのアクセスを制限

7. セキュリティのベストプラクティス

Dockerコンテナをセキュアに使用するためのベストプラクティスを学びましょう。非rootユーザーの使用、イメージのスキャン、シークレットの管理などが重要です。適切なセキュリティ対策を実施することで、コンテナの安全性を向上させられます。

非rootユーザーの使用

コンテナ内でrootユーザーとして実行することは避け、非rootユーザーを作成して使用します。

コンテナ内でrootユーザーとして実行することは避けます:

# Dockerfileで非rootユーザーを作成
FROM node:18-alpine

# ユーザーを作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# ユーザーを変更
USER nodejs

WORKDIR /app
COPY --chown=nodejs:nodejs . .
CMD ["node", "index.js"]

イメージのスキャン

イメージの脆弱性をスキャンすることで、セキュリティ問題を早期に発見できます。Docker ScoutやTrivyなどのツールを使用します。

イメージの脆弱性をスキャンします:

# Docker Scoutを使用(Docker Desktopに含まれる)
docker scout cves nginx

# Trivyを使用
# インストール
brew install trivy

# イメージをスキャン
trivy image nginx

# Dockerfileをスキャン
trivy fs .

シークレットの管理

シークレットは、環境変数、Docker Secrets、環境変数ファイルなどで管理します。本番環境では適切な方法を選択します。

シークレット(パスワード、APIキーなど)を適切に管理します:

# docker-compose.ymlで環境変数を使用(開発環境のみ)
services:
  app:
    environment:
      - DB_PASSWORD=password

# 本番環境ではDocker Secretsを使用
services:
  app:
    secrets:
      - db_password
secrets:
  db_password:
    external: true

# または環境変数ファイルを使用
services:
  app:
    env_file:
      - .env

セキュリティのベストプラクティス

セキュアなDockerコンテナを作成する実践的な例です。

# 1. セキュアなDockerfileの例

FROM node:18-alpine

# 非rootユーザーを作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

WORKDIR /app

# 依存関係を先にコピー(レイヤーキャッシュ)
COPY --chown=nodejs:nodejs package*.json ./
RUN npm ci --only=production && npm cache clean --force

# アプリケーションコードをコピー
COPY --chown=nodejs:nodejs . .

# ユーザーを変更
USER nodejs

# 不要な権限を削除
RUN chmod -R 755 /app

# ポートを公開
EXPOSE 3000

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js

CMD ["node", "index.js"]

# 2. イメージのスキャン

# Trivyでスキャン
trivy image myapp:latest

# 3. シークレットの管理

# .envファイル(gitignoreに追加)
DB_PASSWORD=secret_password
API_KEY=secret_key

# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    env_file:
      - .env
    # または環境変数を直接指定(非推奨)
    # environment:
    #   - DB_PASSWORD=${DB_PASSWORD}

# 4. ネットワークの分離

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 外部へのアクセスを制限

8. 実践的なデプロイ例

Dockerを使用した実践的なデプロイの例を学びましょう。Webアプリケーションのコンテナ化から、本番環境へのデプロイまで、実際のプロジェクトで使用できる例を紹介します。

Node.jsアプリケーションのコンテナ化

Node.jsアプリケーションをコンテナ化するには、マルチステージビルドを使用し、軽量なイメージを作成します。

Node.jsアプリケーションをコンテナ化する例:

# Dockerfile
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

FROM node:18-alpine

WORKDIR /app

# 非rootユーザーを作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# ビルド成果物をコピー
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --chown=nodejs:nodejs package*.json ./

USER nodejs

EXPOSE 3000

CMD ["node", "dist/index.js"]

Docker Composeでの本番環境設定

本番環境では、restart: always、healthcheck、適切な環境変数の設定などが重要です。

本番環境用のdocker-compose.ymlの例:

version: '3.8'

services:
  app:
    build: .
    restart: always
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    depends_on:
      - db
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
  
  db:
    image: postgres:15-alpine
    restart: always
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

実践的なデプロイの例

Dockerを使用した実践的なデプロイの例です。

# 1. アプリケーションのビルドとプッシュ

# イメージをビルド
docker build -t myapp:latest .

# イメージにタグを付ける
docker tag myapp:latest registry.example.com/myapp:v1.0.0

# レジストリにプッシュ
docker push registry.example.com/myapp:v1.0.0

# 2. 本番環境でのデプロイ

# docker-compose.prod.yml
version: '3.8'

services:
  app:
    image: registry.example.com/myapp:v1.0.0
    restart: always
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "node", "healthcheck.js"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
  
  db:
    image: postgres:15-alpine
    restart: always
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

# 3. デプロイの実行

docker-compose -f docker-compose.prod.yml up -d

# 4. ログの確認

docker-compose -f docker-compose.prod.yml logs -f

# 5. サービスの更新

# 新しいイメージをプル
docker-compose -f docker-compose.prod.yml pull

# サービスを再起動
docker-compose -f docker-compose.prod.yml up -d

# 6. ロールバック

# 以前のバージョンに戻す
docker-compose -f docker-compose.prod.yml up -d --no-deps app

9. ベストプラクティス

Dockerを使用する際のベストプラクティスをまとめます。イメージサイズの最小化、セキュリティ、パフォーマンスなどが重要です。これらのベストプラクティスに従うことで、効率的でセキュアなコンテナを作成できます。

イメージサイズの最小化

イメージサイズを最小化するには、軽量なベースイメージを使用し、マルチステージビルドを使用し、不要なファイルを削除します。

イメージサイズを最小化する方法:

- 軽量なベースイメージを使用: Alpine Linuxなど
- マルチステージビルドを使用: ビルドツールを含めない
- 不要なファイルを削除: .dockerignoreを使用
- レイヤーを統合: RUNコマンドをまとめる
- キャッシュをクリア: npm cache cleanなど

セキュリティ

セキュリティのベストプラクティスには、非rootユーザーの使用、イメージのスキャン、シークレットの適切な管理、最小権限の原則、定期的な更新があります。

セキュリティのベストプラクティス:

- 非rootユーザーを使用: コンテナ内でrootとして実行しない
- イメージをスキャン: 脆弱性を定期的にチェック
- シークレットを適切に管理: 環境変数やSecretsを使用
- 最小権限の原則: 必要な権限のみを付与
- 定期的に更新: ベースイメージを最新に保つ

パフォーマンス

パフォーマンスのベストプラクティスには、レイヤーキャッシュの活用、.dockerignoreの使用、適切なベースイメージの選択、ヘルスチェックの実装、リソース制限の設定があります。

パフォーマンスのベストプラクティス:

- レイヤーキャッシュを活用: 変更頻度の低いレイヤーを先に
- .dockerignoreを使用: 不要なファイルを除外
- 適切なベースイメージ: 用途に応じて選択
- ヘルスチェックを実装: コンテナの状態を監視
- リソース制限を設定: CPU、メモリの制限

ベストプラクティスの実装例

Dockerのベストプラクティスを実装した例です。

# 1. 最適化されたDockerfile

# マルチステージビルドでイメージサイズを最小化
FROM node:18-alpine AS builder

WORKDIR /app

# 依存関係を先にコピー(レイヤーキャッシュ)
COPY package*.json ./
RUN npm ci && npm cache clean --force

# アプリケーションコードをコピー
COPY . .
RUN npm run build

# 実行ステージ
FROM node:18-alpine

WORKDIR /app

# 非rootユーザーを作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# ビルド成果物のみをコピー
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --chown=nodejs:nodejs package*.json ./

USER nodejs

EXPOSE 3000

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js

CMD ["node", "dist/index.js"]

# 2. .dockerignoreファイル

node_modules
npm-debug.log
.git
.gitignore
.env
*.md
.DS_Store
coverage
.vscode
.idea

# 3. docker-compose.yml(リソース制限付き)

version: '3.8'

services:
  app:
    build: .
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
    restart: always
    healthcheck:
      test: ["CMD", "node", "healthcheck.js"]
      interval: 30s
      timeout: 10s
      retries: 3

まとめ

Dockerは、アプリケーションをコンテナとしてパッケージ化し、どこでも同じように実行できるようにする強力なツールです。開発環境と本番環境の違いを解消し、デプロイを簡単にします。

Dockerfileを適切に書くことで、効率的でセキュアなイメージを作成できます。Docker Composeを使用することで、複数のコンテナを簡単に管理できます。ボリュームとネットワークを適切に使用することで、データの永続化とコンテナ間通信を実現できます。

セキュリティのベストプラクティスに従い、非rootユーザーの使用、イメージのスキャン、シークレットの適切な管理を実施することで、セキュアなコンテナを作成できます。実践的なプロジェクトでDockerを積極的に使用し、経験を積むことが上達への近道です。

CI/CDパイプラインとは?継続的インテグレーションとデプロイの基礎