Docker環境を操作するコマンドを楽にしたいならMakefileを作っておくと楽
- 毎回
docker compose up -d
とうつのが面倒臭い人むけ。
1. dockerコンテナの立ち上げ(docker compose up -dやdocker compose down)をmakeで実行する
-
Makefile
という名前で以下の内容を記述し、保存する。
.PHONY: build \
up \
down
# Dockerイメージのビルド
build:
docker compose build
# コンテナを起動
up:
docker compose up -d
# コンテナの停止と削除
down:
docker compose down
-
コンテナを起動してみる
-
make up
とターミナルで打つと以下のようになる。
$ make up docker compose up -d Compose now can delegate build to bake for better performances Just set COMPOSE_BAKE=true [+] Building 17.9s (10/10) FINISHED docker:rancher-desktop => [python-dev internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 259B 0.0s => [python-dev internal] load metadata for docker.io/library/python:3.11-slim 2.7s => [python-dev internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [python-dev 1/4] FROM docker.io/library/python:3.11-slim@sha256:82c07f2f6e35255b92eb16f38dbd22679d5e8fb523064138d7c6468e7bf0c15b 0.0s => [python-dev internal] load build context 0.0s => => transferring context: 74B 0.0s => CACHED [python-dev 2/4] WORKDIR /workspace 0.0s => CACHED [python-dev 3/4] COPY requirements.txt requirements.txt 0.0s => [python-dev 4/4] RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir -r requirements.txt 14.9s => [python-dev] exporting to image 0.3s => => exporting layers 0.3s => => writing image sha256:05674b8126330613f7d28a8b315a4538e1f21a7e67275a53fcf84d02c42b3436 0.0s => => naming to docker.io/library/env-setting-learning-python-dev 0.0s => [python-dev] resolving provenance for metadata file 0.0s [+] Running 3/3 ✔ python-dev Built 0.0s ✔ Network env-setting-learning_default Created 0.1s ✔ Container env-setting Started
-
-
上記のログの中で、最初に
docker compose up -d
と表示されるのを避けたいのであれば、@
をつける。- Makefileを以下のようにする。
.PHONY: build \ up \ down # Dockerイメージのビルド build: @ docker compose build # @マークを最初につける # コンテナを起動 up: @ docker compose up -d # コンテナの停止と削除 down: @ docker compose down
2. Makefileで他ファイルに定義されている内容を読みにいく
-
今回作るもの:
-
make shell
というコマンドで動くものを定義してみる。
-
-
注意点:
- 基本的に他のファイルの中身を見にいく時は、
.env
にその内容を記述しておくのが、GOOD
- 基本的に他のファイルの中身を見にいく時は、
-
.env
ファイルを用意する。TEST_ENV_VAL=hello
-
Makefileを以下のようにする
include .env # 追加 export # 追加 .PHONY: build \ up \ down \ shell # 追加 shell: # 追加 @ echo "$(TEST_ENV_VAL)" # Dockerイメージのビルド build: @ docker compose build # コンテナを起動 up: @ docker compose up -d # コンテナの停止と削除 down: @ docker compose down
-
ターミナルで
make shell
してみる$ make shell hello
3. コンテナ名を自動で取得させる(Makefileで他ファイルの中身を見にいく方法)
-
2.同様に、
.env
コンテナの名前を書く。TEST_ENV_VAL=hello CONTAINER_NAME=env-setting
-
コンテナの名前が必要なので、docker-compose.yamlを編集する
services: python-dev: # サービス名 (任意) build: . # Dockerfileがあるディレクトリ (カレントディレクトリ) container_name: ${CONTAINER_NAME} # .envファイルを読んで、コンテナ名を設定する working_dir: /workspace # コンテナ内での作業ディレクトリを指定 volumes: - ./src:/workspace tty: true restart: always # コンテナが停止した場合に常に再起動する
-
Makefileを編集する
include .env export .PHONY: build \ up \ down \ shell shell: @ echo "$(TEST_ENV_VAL)" @ docker exec -it "$(CONTAINER_NAME)" /bin/bash # Dockerイメージのビルド build: @ docker compose build # コンテナを起動 up: @ docker compose up -d # コンテナの停止と削除 down: @ docker compose down
実行結果
(今回利用しているDockerfileは、workspaceをWORKING_DIRとしているので、以下のようになる)
% make shell
hello
root@xxxx:/workspace#
- コンテナの中に入っていることがわかる。
4. make shellコマンドで、docker compose upとdocker execの両方を実施できるようにする
-
Makefile
を編集するinclude .env export .PHONY: build \ up \ down \ shell # Dockerイメージのビルド build: @ docker compose build # コンテナを起動 up: @ docker compose up -d # コンテナの停止と削除 down: @ docker compose down shell: @ echo "$(TEST_ENV_VAL)" @ $(MAKE) up @ docker exec -it "$(CONTAINER_NAME)" /bin/bash
-
$(MAKE) up
とすることで、Makefileの中で定義したup
を実行できる - 実行結果
% make shell hello [+] Running 2/2 ✔ Network env-setting-learning_default Created 0.1s ✔ Container env-setting Started 0.2s root@a987c008deda:/workspace#
- Dockerの起動と、コンテナの内部に自動で入れるようになった。
-
最終的に作成したファイル
以下の5ファイルを同じ階層に置いておく。
.
├── Dockerfile
├── docker-compose.yaml
├── requirements.txt
├── Makefile
└── .env
Dockerfile
FROM python:3.11-slim
WORKDIR /workspace
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
docker-compose.yaml
services:
python-dev: # サービス名 (任意)
build: . # Dockerfileがあるディレクトリ (カレントディレクトリ)
container_name: ${CONTAINER_NAME}
working_dir: /workspace # コンテナ内での作業ディレクトリを指定
volumes:
- ./src:/workspace
tty: true
restart: always # コンテナが停止した場合に常に再起動する
requirements.txt
pandas
.env
TEST_ENV_VAL=hello
CONTAINER_NAME=env-setting
Makefile
include .env
export
.PHONY: build \
up \
down \
shell
# Dockerイメージのビルド
build:
@ docker compose build
# コンテナを起動
up:
@ docker compose up -d
# コンテナの停止と削除
down:
@ docker compose down
shell:
@ echo "$(TEST_ENV_VAL)"
@ $(MAKE) up
@ docker exec -it "$(CONTAINER_NAME)" /bin/bash
より高度な使い方:Poetryが使えるDockerコンテナを作成し、それをMakefileから実行させる
以下の4ファイルを同じ階層に置く。ターミナルからmake shell
と打てば、Dockerコンテナが立ち上がりかつそのコンテナの中に入れる。
poetryはすでにインストールされているので、自分でプロジェクトを作成すれば、poetry環境下でpython開発を行える。
.
├── Dockerfile
├── docker-compose.yaml
├── Makefile
└── .env
Dockerfile
FROM python:3.11-slim
# ビルドする時だけに利用する変数
# つまり、コンテナ内で環境変数として使えるわけではない
ARG POETRY_VERSION
ARG POETRY_HOME
ARG USER_UID
ARG USERNAME
# 必要なパッケージをインストール(curl等)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Poetryのインストール
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN curl -sSL https://install.python-poetry.org/ | python3 - --version ${POETRY_VERSION} && \
ln -s ${POETRY_HOME}/bin/poetry /usr/local/bin/poetry
# コンテナで作成したファイルやフォルダのパーミッションとホストマシンのパーミッションを揃えるための
# 設定を行う
RUN useradd --uid ${USER_UID} -m ${USERNAME}
USER $USERNAME
WORKDIR /home/${USERNAME}/
docker-compose.yaml
services:
python-dev: # サービス名 (任意)
build:
context: . # Dockerfileがあるディレクトリ (カレントディレクトリ)
dockerfile: Dockerfile
args:
POETRY_VERSION: ${POETRY_VERSION}
POETRY_HOME: ${POETRY_HOME}
USER_UID: ${USER_UID}
USERNAME: ${USERNAME}
container_name: ${CONTAINER_NAME}
volumes:
- type: bind
source: ./src
target: /home/${USERNAME}
working_dir: /home/${USERNAME} # /home/${USERNAME} をworking_dirにしておかないと、リモートでVSCode接続したときに、ホスト側のWORKDIRを見つけられない..
tty: true
restart: always # コンテナが停止した場合に常に再起動する
.env
CONTAINER_NAME=env-setting
POETRY_VERSION=2.1.2
POETRY_HOME=/opt/poetry
Makefile
include .env
export
.PHONY: build \
up \
down \
shell \
write_uid_onto_env
# Dockerイメージのビルド
build:
@ docker compose build
# コンテナを起動
up:
@ docker compose up -d
# コンテナの停止と削除
down:
@ docker compose down
# ホストマシンのUIDを.envに書き込む
# 一時ファイルに避難させておかないと、USER_UIDやUSERNAMEがずっと追記され続けてしまうので、
# このような実装とした。
write_uid_onto_env:
@ TEMP_FILE=$$(mktemp); \
grep -v "^USER_UID=" .env | grep -v "^USERNAME=" > $$TEMP_FILE; \
echo "USER_UID=$(shell id -u $(shell whoami))" >> $$TEMP_FILE; \
echo "USERNAME=$$USER" >> $$TEMP_FILE; \
mv $$TEMP_FILE .env
shell:
@ $(MAKE) write_uid_onto_env
@ $(MAKE) build
@ $(MAKE) up
@ docker exec -it "$(CONTAINER_NAME)" /bin/bash
まとめ
- Makefileの定義の仕方や操作方法を学ぶために、Dockerコンテナを立ち上げることを実施した。
- 追加して、poetryを実行できる環境を作るためのMakefileやDockerファイルなどをおまけで追加しt