🫠
[Docker]外部データの注入は都度で、コンテナ内で生成したデータは必要なときに引っ張ってきたい
PythonのFireを使ったCLIを作ろうとしていて、外部との共有もあったのでDockerを使おうとしていた。
外部データは都度変化するので、コンテナ生成時にbindマウントし、volumeにマウントされたデータはどうにかこうにかしてローカルに持ってきたい。GUIはやだ
コマンド一発よろ。って感じで任されたので、解決策をメモる。
imageをビルドする
dockerのイメージ名をcli_image
で指定。
docker build -f . -t cli_image --rm .
containerを作成
-
--name
でcli_container
でコンテナ名を指定 -
--mount
でホストマシンの./data
ディレクトリを対象に、コンテナ上の/src/data
ディレクトリにマウントする -
-v
でcli-volを作成し、コンテナ上の/src/output
にマウントする。このマウント先が後にホスト上に保存するときに必要 - 後はコンテナ止めたらコンテナを随時削除する
--rm
docker run -it --name cli_container --mount type=bind,source=$(realpath ./data),target=/src/data -v cli-vol:/src/output --rm cli
コンテナ内のvolumeのコンテンツをホストに保存
- 先ほど作成した
cli-vol
volumeをcontainer-vol
volumeにマウントしする - ホストカレントディレクトリをマウントし、コンテナ内の
container-vol
をホストのcontainer-vol
ディレクトリにコピー
docker run --rm -v cli-vol:/container-vol -v `pwd`/:$(realpath ./) cli_image sh -c 'cp -r /container-vol $(realpath ./)'
サンプルコードを用意した。
簡単な説明をしておくと、data/
ディレクトリが外部データの保存先。
コンテナを立ち上げて、python main.py hello
でコンテナ内でファイルを生成。
container-vol
がコンテナコンテンツの保存先。
ファイル構造
.
├── Dockerfile
├── Makefile
├── container-vol
│ └── test.txt
├── data
│ └── a.txt
├── main.py
└── requirements.txt
main.py
import fire
import os
class Main:
def __init__(self) -> None:
pass
def hello(self):
output_directory = 'output/'
os.makedirs(output_directory, exist_ok=True)
with open(os.path.join(output_directory, 'test.txt'), 'w') as file:
file.write('Hello')
if __name__ == "__main__":
fire.Fire(Main)
Dockerfile
FROM python:3.11
WORKDIR /src
COPY . .
RUN python -m pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
CMD ["bash"]
追記
volumeからというより、コンテナからデータを引っ張ってくるだけならdocker cp
で問題ない。
たったこれだけで良いんだ
コンテナ名
:コンテナのファイルの出力先
出力先
docker cp cli_container:/src/output $(realpath ./)
Discussion