Docker Containers ガイド#

このガイドは、Docker と Docker Compose の基本知識がある方向けに、実際のプロジェクト開発で Containers をどのように使うかを説明しています。

前提知識

  • Docker と Docker Compose の基本的な理解

  • docker compose run などの基本コマンド

  • ターミナルでのファイル操作

はじめに:何ができるのか?#

Haniwers では、Docker Containers を使用して以下のことが可能です:

  • テスト環境の隔離: ホスト環境に影響なくテスト実行

  • 環境の統一: 開発者全員が同じ環境でテスト実行

  • 依存関係の管理: Poetry でビルドされた完全な環境

  • 複数のワークフロー: CLI テスト、ドキュメント生成、ユニットテスト

ディレクトリ構成#

haniwers/
├── compose.yaml                    ← プロジェクトルートのプロキシ
├── containers/
│   ├── compose.yaml               ← containers/ からのアクセス用
│   ├── .dockerignore              ← ビルド時の除外設定
│   ├── dev/
│   │   ├── Dockerfile             ← 開発・テスト用イメージ定義
│   │   ├── compose.yaml           ← 実際のサービス定義
│   │   └── README.md
│   ├── python3/
│   │   └── compose.yaml           ← PyPI パッケージ検証用
│   └── raspi/
│       └── Dockerfile             ← Raspberry Pi デプロイ用
└── (その他のプロジェクトファイル)

クイックスタート#

最初の一度:イメージをビルド#

# プロジェクトルートで実行
docker compose build base

このコマンドで、haniwers:latest イメージが作成されます(初回は数分かかります)。

テストを実行#

# プロジェクトルートで実行
docker compose run --rm test

コンテナ内で pytest が実行され、すべてのテストが走ります。

CLI をテスト#

# Haniwers v0 のヘルプを表示
docker compose run --rm cli haniwers-v0 --help

# Haniwers v1 のポート一覧を表示
docker compose run --rm cli haniwers-v1 port list

ドキュメントを生成#

# ドキュメント生成
docker compose run --rm docs

実際の使用パターン#

パターン1: テストを実行してから開発#

新機能を開発する前に、テストが通ることを確認:

# 1. イメージが最新か確認
docker compose build base

# 2. テスト実行
docker compose run --rm test

# 3. テスト結果を確認
# → エラーが出た場合は修正

パターン2: コンテナ内で対話的にテスト#

デバッグのため、コンテナ内で bash シェルを使用:

# コンテナ内で bash を起動
docker compose run --rm test bash

# コンテナ内で実行:
[container] # poetry run pytest tests/v1/unit/helpers/ -v
[container] # poetry run haniwers-v1 version --env
[container] # exit

利点: ホスト環境に影響を与えずにコマンドを試行できます。

パターン3: ホストの変更をすぐにテスト#

ソースコードを編集してから、コンテナでテスト:

# ホストでファイルを編集
vim src/haniwers/v1/helpers/parser.py

# コンテナでテスト実行
docker compose run --rm test tests/v1/unit/helpers/test_parser.py -v

# → コンテナは自動でホストの最新コードを読み込みます

なぜ? compose.yaml で以下のようにマウントしているため:

volumes:
  - ../../src/haniwers:/workspace/haniwers  # ホストのコードをマウント
  - ../../tests:/workspace/tests            # テストをマウント

パターン4: 特定のテストだけを実行#

# 1つのテストファイルだけ実行
docker compose run --rm test tests/v1/unit/daq/device/test_connect.py

# 1つのテストクラスだけ実行
docker compose run --rm test tests/v1/unit/daq/device/test_connect.py::TestConnect

# 1つのテストメソッドだけ実行
docker compose run --rm test tests/v1/unit/daq/device/test_connect.py::TestConnect::test_connect_success

パターン5: ドキュメントを確認#

# ドキュメント生成
docker compose run --rm docs

# ブラウザで確認
# http://localhost:8000

よくある課題と解決方法#

課題1: イメージが古い#

新しい依存関係を追加した場合、イメージを再ビルド:

# イメージをクリーンビルド
docker compose build base --no-cache

課題2: コンテナ内で permission denied#

# エラー例:permission denied: /workspace/...

# 解決方法:コンテナ内で bash を実行して確認
docker compose run --rm test bash
[container] # ls -la /workspace/

課題3: ボリュームマウントが動作しない(macOS)#

Docker Desktop の設定を確認:

  1. PreferencesResourcesFile Sharing

  2. プロジェクトのディレクトリが追加されているか確認

  3. 必要に応じて追加

課題4: コンテナが起動しない#

# エラーログを確認
docker compose config   # 設定を確認
docker compose logs     # ログを表示

各サービスの詳細#

base(ビルド)#

  • 用途: イメージビルド専用

  • 自動起動: なし(手動でビルド)

  • 実行例: docker compose build base

test(テスト実行)#

# 基本的なテスト実行
docker compose run --rm test

# 特定のテストスイート実行
docker compose run --rm test tests/v1/unit/

# カバレッジ付きテスト
docker compose run --rm test pytest --cov=haniwers

# 対話的なデバッグ
docker compose run --rm test bash

マウント:

  • src/haniwers//workspace/haniwers

  • tests//workspace/tests

  • data//workspace/data

cli(CLI テスト・シリアルポート)#

# Haniwers v0 のヘルプを表示
docker compose run --rm cli haniwers-v0 --help

# Haniwers v1 のシリアルポート一覧を表示
docker compose run --rm cli haniwers-v1 port list

# Haniwers v1 のポートテスト
docker compose run --rm cli haniwers-v1 port test /dev/ttyUSB0

# バージョン確認
docker compose run --rm cli haniwers-v0 version

# 対話的にコマンドを実行
docker compose run --rm cli bash
[container] # haniwers-v1 daq --help
[container] # exit

マウント:

  • sandbox//workspace/sandbox

  • /dev//dev/(シリアルポートアクセス有効)

特徴:

  • poetry run が自動的に実行される(entrypoint)

  • ホストのシリアルポート(/dev/ttyUSB* など)にアクセス可能

  • privileged: true でUSBデバイスアクセス権限を確保

dev(開発環境)#

# 開発環境で情報表示
docker compose run --rm dev

# コンテナ内で実行される内容:
# poetry run haniwers version --env

マウント:

  • src/haniwers//workspace/haniwers

  • sandbox//workspace/sandbox

docs(ドキュメント生成)#

# ドキュメント生成
docker compose run --rm docs

# 生成されたファイル:
# docs/_build/dirhtml/ に HTML が生成されます

マウント:

  • src/haniwers//workspace/haniwers

  • docs//workspace/docs

Dockerfile について#

containers/dev/Dockerfile はマルチステージビルドを使用:

# Stage 1: Builder
FROM python:3.11-slim AS builder
RUN pip install poetry
# → Poetry で依存関係をインストール

# Stage 2: Runtime
FROM python:3.11-slim AS runtime
# → Builder の結果をコピー
# → ホストのコードをコピー

なぜ? イメージサイズを小さくしつつ、開発に必要なツールを含める

実践的なワークフロー例#

新機能を追加する場合#

# 1. 現在のテストが通ることを確認
docker compose run --rm test

# 2. 新しいコード/テストを作成(ホストのエディタで編集)
vim src/haniwers/v1/helpers/parser.py
vim tests/v1/unit/helpers/test_parser.py

# 3. 新しいテストだけ実行してみる
docker compose run --rm test tests/v1/unit/helpers/test_parser.py -v

# 4. すべてのテストが通ることを確認
docker compose run --rm test

# 5. コード品質をチェック
docker compose run --rm test bash
[container] # poetry run ruff format .
[container] # exit

# 6. コミット
git add ...
git commit -m "feat: add new feature"

テストがデバッグできない場合#

# 1. コンテナ内で bash を起動
docker compose run --rm test bash

# 2. コンテナ内で対話的にテスト
[container] # cd /workspace
[container] # poetry run pytest tests/... -v -s --pdb

# 3. デバッガーで問題を調査
# → exit で終了

CI/CD パイプラインでも同じ環境を使用#

# .gitlab-ci.yml で使用
image: python:3.11-slim

script:
  - poetry install
  - poetry run pytest

重要: ホストでの開発と CI/CD パイプラインで同じテスト環境を使用することで、「ローカルでは通るが CI では失敗」という問題を回避できます。

トラブルシューティング#

Q: コンテナ内のファイルがホストに反映されない#

A: コンテナ内で生成されたファイルは、マウントされているディレクトリにのみホストに反映されます。

# マウント設定の例
volumes:
  - ../../data:/workspace/data  # ホストの data/ にマウント

data/ に生成されたファイルはホストで見えます。/root/ などマウント外に生成されたファイルは見えません。

Q: poetry.lock が最新でない#

A: Dockerfile で依存関係がインストールされた時点の poetry.lock が使用されます。更新する場合:

# ホストで poetry.lock を更新
poetry update

# イメージをクリーンビルド
docker compose build base --no-cache

# テスト実行
docker compose run --rm test

Q: Python バージョンを変更したい#

A: Dockerfile を編集:

# FROM python:3.11-slim  ← 3.11 を 3.12 に変更
FROM python:3.12-slim

# イメージをリビルド
docker compose build base --no-cache

参考資料#

次のステップ#