MakefileでDockerとローカル開発コマンドを効率化・共通化する実践Tips

MakefileでDockerとローカル開発コマンドを効率化・共通化する実践Tips

2026/08/08
目次
開閉

「またコマンド履歴から 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 compose V2構文に対応)
  • 動作検証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つの実践ポイント

  1. .PHONY の宣言を忘れない test や build という名前のディレクトリやファイルがリポジトリ内に存在する場合、Makeが「該当ファイルはすでに最新です」と誤認してコマンドを実行しなくなります。タスクランナーとして使うターゲット名は、すべて .PHONY に明記しておきます。
  2. awkワンライナーによるセルフドキュメント化 ターゲットの後ろに ## コマンドの説明 とコメントを添え、それを grep と awk で抽出して整形しています。Makefileそのものが常に最新のコマンド一覧ドキュメントとして機能するため、別途READMEをメンテナンスする手間が省けます。
  3. -T オプションによるTTY無効化 (CI環境配慮) docker compose exec はデフォルトで擬似端末(TTY)を割り当てます。しかしGitHub ActionsなどのCI環境やバックグラウンドスクリプトから呼び出す場合、TTYが存在しないためエラーになることがあります。-T オプションを付けておくことで、ローカルでもCIでも同じMakefileターゲットを安全に共用できます。
  4. 変数受け渡しによる柔軟なパラメータ指定 test-one ターゲットのように $(args) を埋め込んでおくことで、make test-one args="-k test_login" のようにコマンドラインから任意の引数を注入できます。「全テストは長いので特定のテスト関数だけ実行したい」といった日々の開発で非常に重宝します。
Lowom 編集長 編集長
CAUTION Makefile最大の落とし穴:インデントはタブ文字必須
「Makefileのコマンド行(レシピ)は、スペースではなく必ず『タブ文字(Tab)』でインデントする必要があります。エディタの自動設定でスペース4つなどに置換されると『missing separator』エラーで動かなくなります。VS Codeなどの設定でMakefileではTabを維持するように注意してください」

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 が同梱されているため、シェル環境としてスムーズに動作します。
Lowom 編集長 編集長
POINT Windowsネイティブでの運用アドバイス
「自宅のWindows環境で開発する際も、WSL2上のターミナルからMakeを動かすのが一番トラブルが起きにくいです。どうしてもPowerShellネイティブで統一したい場合は、MakefileではなくTaskfile(go-task)やJustなどの現代的なタスクランナーを検討するのも良い手です」

実際に導入して変わった開発現場の空気

  1. オンボーディング(新メンバー着任)がスムーズに完了 「リポジトリを clone したら make up を叩いてください」の一言で初期構築から起動まで完了するようになり、環境構築の手順書メンテナンスに追われるストレスから解放されました。
  2. 打鍵数(タイピング量)の大幅な削減 1回あたり30〜40文字あった長いコマンドが make up や make test(8文字程度)に短縮。1日に何度も叩く作業だからこそ、タイピングの負担と手戻りミスが大幅に減りました。
  3. コマンド打ち間違い事故の防止 本番に近い検証用DBへのマイグレーションやリセットなど、手順を誤ると手痛い作業も Makefile に定型化することで、心理的負担なく安全に作業を進められるようになりました。

まとめ:シンプルな仕組みで開発に集中する

Makefileは決して古い遺物ではありません。むしろコンテナ時代において、複雑化しがちなCLI操作を人間から引き離し、思考のメモリを本来の実装に集中させるための「軽量で堅牢なインターフェース」です。

まずは、最もよく使う up や logs のコマンドを Makefile に1つ書くことから始めてみてください。日々の開発リズムが心地よく整っていく感覚を実感できるはずです。

Makefileで日常のDocker操作を効率化するとともに、肥大化しやすいストレージの定期クリーンアップ手順も合わせて押さえておくのがおすすめです。

Lowom 編集長
この記事を書いた人:Lowom 編集長 現役Webエンジニア

都内IT企業に勤める業界20年のWebエンジニア。業務効率化・自動化スクリプトや快適な開発環境の構築、厳選したツール・ガジェットの活用法など、手元で実際に検証したリアルな一次情報をお届けします。

運営者プロフィール詳細を見る