最近はDocker内でLaravel(PHP)を動かして開発をしています。
Dockerならサーバーもローカルも環境構築をテキスト形式のdocker-compose.ymlを使って管理できるので、同じ環境を作りやすいのが大きいメリットですよね。
Makefile内で開発者のローカル環境にあわせて、ターゲットのDockerコンテナを切り分けられたら便利かなと思い調べてみました。
実装作業に関係ないコンテナをわざわざbuildしたりするのは、時間食うだけで無駄ですしね。
この記事では、「Makefile内でファイルの存在をチェックして挙動を変える方法」について紹介します。
やりたいこと
makeコマンドを複数に分けるのも1つの方法かもしれませんが、できればコマンドは減らしたいです。
作戦としては Makefile内で、不要かもしれないコンテナの元となるディレクトリが存在するかチェックして動作を変えます。
ファイルの存在の有無によって、makeコマンドのターゲットで docker-compose.yml を動的に変わるようにしてみました。
ディレクトリが存在しないときはエラーにせず何もしないようにして、存在すればdocker buildや起動をします。
ディレクトリとファイルの構成
主要なディレクトリとファイルの関係はこの様になっています。
コンテナ app_02 を使うには app_01 が必須なので、app_02 のコンテナ操作は app_01 ディレクトリ内の Makefile でまとめています。
コンテナ app_02 の設定は「docker-compose-app02.yml」だけに記述されています。
サンプルMakefile
サンプルMakefileではapp_02が存在したら、追加でdocker-compose-app02.ymlを使います。
app_02ディレクトリが存在しなければ、デフォルトとしてdocker-compose.ymlだけを使うようになります。
PROJECT_DIR=/project APP_02_PATH=$(shell pwd)/../app_02/ APP_02_PATH_RELATIVE="../app_02/" checkFileName=Dockerfile app02FileExists="$(shell ls ${APP_02_PATH_RELATIVE} | grep ${checkFileName})" # ディレクトリが存在チェックしてコンテナ操作ターゲットを変える ifeq ("$(shell echo ${app02FileExists})" , "$(shell echo ${checkFileName})") app02-docker-compose-yml= -f docker-compose-app02.yml else app02-docker-compose-yml= endif DOCKER_COMPOSE_COMMAND=docker-compose -p app_01 $(app02-docker-compose-yml) .PHONY: build build: DOCKER_BUILDKIT=1 docker build -t app_01_app:latest -f Dockerfile . ifeq ("$(shell echo ${app02FileExists})" , "$(shell echo ${checkFileName})") @echo "#### RUN BUILD ####" cd $(APP_02_PATH) && DOCKER_BUILDKIT=1 docker build -t app_02_app:latest -f Dockerfile . else @echo "#### NOT RUN BUILD ####" endif .PHONY: rebuild rebuild: DOCKER_BUILDKIT=1 docker build --no-cache=true -t app_01_app:latest -f Dockerfile . ifeq ("$(shell echo ${app02FileExists})" , "$(shell echo ${checkFileName})") @echo "#### RUN CARE REBUILD ####" cd $(APP_02_PATH) && DOCKER_BUILDKIT=1 docker build --no-cache=true -t app_02_app:latest -f Dockerfile . else @echo "#### NOT RUN CARE REBUILD ####" endif .PHONY: up up: $(DOCKER_COMPOSE_COMMAND) up -d .PHONY: down down: $(DOCKER_COMPOSE_COMMAND) down .PHONY: bash bash: $(DOCKER_COMPOSE_COMMAND) exec -w $(PROJECT_DIR) app bash -l
サンプルMakefileについて
最初に ls と grep コマンドでapp_02ディレクトリのファイルを取得します。
app02FileExists="$(shell ls ${APP_02_PATH_RELATIVE} | grep ${checkFileName})"
ファイルの存在でディレクトリの存在チェックに使っています。
ディレクトリの存在確認なので、ファイルじゃなくても問題ないです。
気づいているかもしれませんが、普通のlsコマンドにgrepしているので複数のファイルがヒットするかもしれません。
その後に ifeq でファイル名が一致するかチェックすることで別のディレクトリが存在するか確認しています。
ifeq ("$(shell echo ${app02FileExists})" , "$(shell echo ${checkFileName})")
ifeq内で変数にYAMLファイルを読み込むオプションを変数にセットして docker-composeコマンドにくっつけます。
DOCKER_COMPOSE_COMMAND=docker-compose -p app_01 $(app02-docker-compose-yml)
「$(app02-docker-compose-yml)」は、空文字か「-f ファイル名」になります。
docker buildは ifeq内 で存在するときだけ app_02コンテナを build するようにします。
ifeq ("$(shell echo ${app02FileExists})" , "$(shell echo ${checkFileName})") @echo "#### RUN BUILD ####" cd $(APP_02_PATH) && DOCKER_BUILDKIT=1 docker build -t app_02_app:latest -f Dockerfile . else @echo "#### NOT RUN BUILD ####" endif
ファイルが存在するときだけ、app_02に移動してdocker buildを実行します。
終わりに。
これでローカルの環境にあわせて、コンテナ操作できるようになりました。
まぁ本来なら同じチーム内のみんな同じ環境にするのがベストだと思います。
Docker環境 は vagrant環境 などよりもディスク容量を喰わなくなりました。
それでも場合によっては、ディスク容量がキツくなったり、コンテナの操作に時間がかかったりしてしまうデメリットがあります。
不要なコンテナを作らないようにしておけば、少しは幸せになれるかもしれません。
コメント