MakefileでDockerとローカル開発コマンドを効率化・共通化する実践Tips
目次
開閉
「またコマンド履歴から docker compose exec web python manage.py migrate を探している……」
ターミナルを開くたびに、過去の長いコマンド履歴を Ctrl + R で検索したり、ドキュメントに書き留めたコマンド集をコピペしたりしていませんか?
Webエンジニアとして開発環境のDocker化が進む一方、実行するコマンドは年々長く複雑になりがちです。今回は、C言語のビルドツールとして歴史ある GNU Make を「ローカル開発用のタスクランナー」として再活用し、Docker Compose の運用を快適にまとめる方法をご紹介します。
[!NOTE] 動作検証環境
- GNU Make: 4.3 以上
- Docker / Docker Compose: v2.20 以上(
docker composeV2構文に対応)- 動作検証OS: macOS (Sonoma) / Ubuntu 22.04 LTS (WSL2)
なぜDocker時代の開発に「Makefile」なのか?
npm run や pnpm などのパッケージマネージャーでもタスク定義は可能です。しかし、Python、Go、Ruby、PHPなどのマルチ言語環境や、インフラ・DB操作を伴うプロジェクトでは、言語ランタイムを選ばず軽量に動く Makefile が圧倒的に扱いやすい選択肢になります。
私がチームでMakefileを本格導入したきっかけは、新しく参画したメンバーが環境構築コマンドの入力ミスでローカルDBを誤ってリセットしてしまう事故が発生したことでした。「長くて打ち間違いやすいコマンドを日常的に人間に打たせる運用自体に無理がある」と痛感したのです。
コマンド統一による開発体験の向上
Makefileをプロジェクトルートに配置することで、複雑なオプションやコンテナ名を背後に隠蔽し、どのエンジニアでも統一されたシンプルなインターフェースで操作できるようになります。
graph TD
A["エンジニアの入力"] --> B["make dev (開発サーバー起動)"]
A --> C["make test (全テスト実行)"]
A --> D["make db-reset (DB初期化)"]
B --> E["docker compose up -d --build"]
C --> F["docker compose exec app pytest --cov"]
D --> G["docker compose down -v && docker compose up -d"]実戦で使える Makefile の全貌
以下は、一般的なWebアプリケーション(Docker + Python / Node.js等)開発で今すぐ実務に導入できる実用的な Makefile です。リポジトリのルートに配置するだけで、チーム全員の開発環境が整います。
.PHONY: help build up down restart logs test test-one lint db-shell clean
# デフォルトターゲット:引数なしで make を叩いたときにヘルプを表示
.DEFAULT_GOAL := help
help: ## 利用可能なコマンド一覧と説明を表示
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
build: ## Dockerイメージのビルド
docker compose build
up: ## バックグラウンドでコンテナを起動
docker compose up -d
down: ## コンテナを停止・削除
docker compose down
restart: down up ## コンテナの再起動
logs: ## リアルタイムログの表示
docker compose logs -f --tail=100
test: ## コンテナ内でテストを実行
docker compose exec -T app pytest -v --durations=5
test-one: ## 特定のテストのみ実行 (例: make test-one args="-k test_auth")
docker compose exec -T app pytest -v $(args)
lint: ## リンターとフォーマッターの実行
docker compose exec -T app flake8 .
docker compose exec -T app black --check .
db-shell: ## データベースのCLIシェルに接続
docker compose exec db psql -U postgres -d app_development
clean: ## 一時ファイルやキャッシュの削除
find . -type d -name "__pycache__" -exec rm -r {} +
find . -type f -name "*.pyc" -delete実際にターミナルで叩いた時の出力
このMakefileを配置した状態で、ターミナルで単に make と叩くと、以下のように利用可能なターゲットと説明が一覧表示されます。
$ make
build Dockerイメージのビルド
clean 一時ファイルやキャッシュの削除
db-shell データベースのCLIシェルに接続
down コンテナを停止・削除
help 利用可能なコマンド一覧と説明を表示
lint リンターとフォーマッターの実行
logs リアルタイムログの表示
restart コンテナの再起動
test コンテナ内でテストを実行
test-one 特定のテストのみ実行 (例: make test-one args="-k test_auth")
up バックグラウンドでコンテナを起動
「どのコマンドで起動するんだっけ?」「テストのオプションは何だったっけ?」と迷った瞬間に、キーボードから make と叩くだけですぐに確認できるため、新しくチームに入ったメンバーでも迷う余地がありません。
Makefile作成時に押さえるべき4つの実践ポイント
- .PHONY の宣言を忘れない
testやbuildという名前のディレクトリやファイルがリポジトリ内に存在する場合、Makeが「該当ファイルはすでに最新です」と誤認してコマンドを実行しなくなります。タスクランナーとして使うターゲット名は、すべて.PHONYに明記しておきます。 - awkワンライナーによるセルフドキュメント化
ターゲットの後ろに
## コマンドの説明とコメントを添え、それをgrepとawkで抽出して整形しています。Makefileそのものが常に最新のコマンド一覧ドキュメントとして機能するため、別途READMEをメンテナンスする手間が省けます。 - -T オプションによるTTY無効化 (CI環境配慮)
docker compose execはデフォルトで擬似端末(TTY)を割り当てます。しかしGitHub ActionsなどのCI環境やバックグラウンドスクリプトから呼び出す場合、TTYが存在しないためエラーになることがあります。-Tオプションを付けておくことで、ローカルでもCIでも同じMakefileターゲットを安全に共用できます。 - 変数受け渡しによる柔軟なパラメータ指定
test-oneターゲットのように$(args)を埋め込んでおくことで、make test-one args="-k test_login"のようにコマンドラインから任意の引数を注入できます。「全テストは長いので特定のテスト関数だけ実行したい」といった日々の開発で非常に重宝します。
OS環境別の注意点と現場での工夫(macOS / Windows)
チーム開発では、メンバー全員が同じOSを使っているとは限りません。特にmacOSとWindowsが混在する現場では、いくつかの点に配慮が必要です。
macOS / Linux環境
macOSの場合はXcode Command Line Tools(xcode-select --install)またはHomebrew経由でGNU Makeが利用できます。Linux環境でも大半のディストリビューションで make パッケージが提供されているため、セットアップで困ることはほぼありません。
Windows環境での実践アプローチ
Windowsには標準で make コマンドが用意されていません。また、上記のMakefileでは grep、awk、find などのPOSIXシェルコマンドを使用しているため、PowerShellネイティブ環境ではそのまま実行できないターゲットがあります。
実務でWindowsノートPCを使用する際は、以下のいずれかのアプローチをおすすめします:
- WSL2(推奨): Ubuntu等のWSL2環境内で
makeを叩く。Docker DesktopのWSL2バックエンドと連動していれば最も安定し、Linuxと完全に同一の挙動が得られます。 - Git Bash: Git for Windowsに付属するGit Bashターミナルを使用する。
grepやawkが同梱されているため、シェル環境としてスムーズに動作します。
実際に導入して変わった開発現場の空気
- オンボーディング(新メンバー着任)がスムーズに完了
「リポジトリを clone したら
make upを叩いてください」の一言で初期構築から起動まで完了するようになり、環境構築の手順書メンテナンスに追われるストレスから解放されました。 - 打鍵数(タイピング量)の大幅な削減
1回あたり30〜40文字あった長いコマンドが
make upやmake test(8文字程度)に短縮。1日に何度も叩く作業だからこそ、タイピングの負担と手戻りミスが大幅に減りました。 - コマンド打ち間違い事故の防止 本番に近い検証用DBへのマイグレーションやリセットなど、手順を誤ると手痛い作業も Makefile に定型化することで、心理的負担なく安全に作業を進められるようになりました。
まとめ:シンプルな仕組みで開発に集中する
Makefileは決して古い遺物ではありません。むしろコンテナ時代において、複雑化しがちなCLI操作を人間から引き離し、思考のメモリを本来の実装に集中させるための「軽量で堅牢なインターフェース」です。
まずは、最もよく使う up や logs のコマンドを Makefile に1つ書くことから始めてみてください。日々の開発リズムが心地よく整っていく感覚を実感できるはずです。
Makefileで日常のDocker操作を効率化するとともに、肥大化しやすいストレージの定期クリーンアップ手順も合わせて押さえておくのがおすすめです。