自分の中の要求整理
最適解というより、勉強としてこうしてみたいという要望
- なるべくさぼりたい
- development, productionなど環境を分けられるようにしたい
- poetoryかpipenvでmodule管理したい
- まっさらな状態からスタートしたい(すでにコードがあって、それをdockerにするではない)
- apiのロジックを書いたときにコンテナの再起動を不要にしたい(開発環境では)
Dockerfileとdocker-composeの準備
この記事が似た考えだったので、これをベースに進める。
最終的な成果物は末尾に記載。
マルチステージビルド
dockerのビルドを複数の ステージ
に分けて実行できる機能で、別ステージのビルド結果を参照できるようになり、容量が抑えられる(らしい)。
参考
この機能を使って、initail, development, productionに分け
initialでは初期の環境構築、developmentでは開発時の、productionでリリース時のビルドのみに集中する。
initial
apt-getで必要なツールのインストールとpoetory のインストールをしている。
$ docker-compose -f docker-compose.initial.yml build
でビルドできる。
develop
poetoryによるパッケージのインストールを実施する。
COPY poetry.lock pyproject.toml ./
とあり、
どうも、poetory関連のファイルをcopyしている(正確にはdevelopmentではなくdevelopment-baseで) 。
だが、まっさらな状態ではそれらのファイルは存在しないはずでちゃんと動かなそう。
実際に、$ docker-compose -f docker-compose.development.yml build
でビルドを実行すると下記のエラー。
Building app
[+] Building 1.6s (9/11)
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/tiangolo/uvicorn-gunicorn-fastapi:python3.9 1.5s
=> [python-base 1/1] FROM docker.io/tiangolo/uvicorn-gunicorn-fastapi:python3.9@sha256:d0ffdbeffb4e713782dd776b1b46311cb94952f4d00098330c393b0b81ca2881 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [initial 1/3] RUN apt-get update && apt-get install --no-install-recommends -y curl build-essential git cmake 0.0s
=> CACHED [initial 2/3] RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python 0.0s
=> CACHED [initial 3/3] WORKDIR /opt/pysetup 0.0s
=> ERROR [development-base 1/1] COPY poetry.lock pyproject.toml ./ 0.0s
------
> [development-base 1/1] COPY poetry.lock pyproject.toml ./:
------
failed to compute cache key: "/pyproject.toml" not found: not found
ERROR: Service 'app' failed to build : Build failed
ファイルがないので当然のエラー。
調査
initialのタイミングで poetory init
でpyproject.tomlを生成し、それがホストにも同期されればよいのでは?と考え
volumeでマウントした状態で RUN poetry init --no-interaction
してみた※が、pyproject.tomlは生成されなかった。
これは、
ここにあるように、マウントしていてもDockerfile内で実行されたものは後からホストマシンのディレクトリが上書きしてしまうからと考えられる。
※ 手順
- Dockerileで、
FROM initial as development-base
の前に、 poetory init --no-interaction
を挿入する
- docker-compose.initial.ymlで、volumeの設定をする。(下記をservices.app以下に配置)
暫定対応
仕方がないので、コンテナに入り、手動で poetory init
した。
コンテナには、
$ docker-compose -f docker-compose.initial.yml run app bash
で入ることができる。
production
ちゃんと確認していないので飛ばす。
開発時にいちいちコンテナを再起動しなくて済むように
Docker イメージ制作者が `start-reload.sh' というのを用意してくれている。
docker-compose.development.ymlで service.app配下に下記のcommandを挿入することで、実現できる
command: /bin/bash /start-reload.sh
その他
開発時に80番ポートは嫌だったので8080ポートに変更した。
docker-compose.development.yml の portsを8080:80にすればよい。
終わりに
fastapiをとりあえず動かせる状態から、開発進めはじめるための環境構築をした。
やり始めるといろいろあると思うが、ひとまずは準備できたと思う。