-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docker版/Dockerfileの扱いを考える #482
Comments
現状のdocker/Dockerfileについて整理します。 まず僕が勝手に思っていたdockerの役割ですが、「ビルド環境の提供」と「成果物の提供」が主だと思っていました。 これに関して、時間がたつに連れいろいろわかってきました。 docker周りを作っていただいたのは @aoirint さんなのですが、相談せずに独断で判断し、混乱させてしまって申し訳ありませんでした。 |
docker版を開発環境として使えそうかという視点で調べてみました。 現状のDockerfileを見てみた感じ、エンジンをpythonを起動するコマンドは gosu user /opt/python/bin/python3 run.py となります。 開発環境用に別のdockerfileを用意しても良いかもですが、まあ |
Dockerfileを見直してみた感じ、ライセンス情報を生成する部分や、VOICEVOX RESOURCEを取得する部分、onnxruntimeを持ってくる部分などがActionsとDockerfileの2箇所に同じ処理が書かれている形なのがなんとかできると嬉しいのかなと思いました。 ちなみにPyInstaller化により、今まではWindowsのAction・MacのAction・LinuxのDockerfileの3箇所に書かれていたのが2箇所まで減ったので管理しやすくなりました。(thx @y-chan !) 統一する方法はいろいろありそうですが、例えばビルド用シェルスクリプトを用意してaction内とdockerfile内両方から参照するのが良いのかなと思っています。 |
DockerイメージのRustコア対応を進めたいので、あまりまとまっていないですが書いておきます...。 要点: バイナリを同梱する方式のDockerfileだけメンテナンスするようにするのもいいかも
意図的に、Dockerコンテナだけでエンジンの開発を完結できる構成にしていました。 あまり覚えていないですが、いくつか意図があった気がします。
実際にはほとんど使われておらず、このリポジトリでこの状態をメンテナンスするモチベーションがなさそうなので、ビルドの一本化でビルド過程をメンテナンスしやすくする方が重要だと思いました。
サンドボックス化された環境はIDE/言語サーバと相性が悪そうで、結局ローカル環境(venv)にライブラリをインストールしないと補完が効かないので、コードが書きにくいなと思いました。 この観点で、ローカルで開発用にDockerイメージをビルドできる状態を維持することをあきらめて、配布用のバイナリを同梱する方式のDockerfileに切り替えるのもありかもしれないと思えてきました...。その場合は、リポジトリのルートにおくよりも、.githubディレクトリの中とか、dockerディレクトリの中とかにおいて、ファイル名を ソースコードを同梱する方式の場合、(キャッシュがあれば)バイナリビルドしないので、動かせる状態になるまでが速いのが利点だと思いますが、いまプレビュービルドでやっているような、プルリクエスト・新規の変更の動作検証で使うことを考えると、DockerだけでなくいろいろなOSで検証しそうなので、あまり重要ではなさそうかもです。
Dockerコンテナの中にshellで入ってコマンドを打つ使い方を考えていますか? ただ、FastAPIのホットリロード機能を使えないのはいまいちかもですね...(Makefileもソースコードをマウントしていないので、ソースコードを変更するたびにビルドが必要)。 わたしは汎用のDockerイメージ(例えば、Python + ONNX Runtimeだけが入っているようなベースイメージ用のイメージを考えています)を作ることはあまりなくて、プロジェクトごとにDockerイメージ(Dockerfile)を作って開発しています...(富豪的?)。代わりに、マルチステージ機能を使っています。 例でいうと、Pythonのバージョン、ONNX Runtimeのバージョンをベースイメージ側で管理すると、たくさんタグを定義したり、バージョンごとにコマンドを変えたりして、汎用性を高める必要が出てきて大変なので、プロジェクト側で制御したい感じです。そういうベースイメージを誰かがメンテナンスしてくれていて、用途に合っていれば使うかもです(例えば、 容量やビルド時間より、環境の定義をリポジトリに載せて、再現できるようにすることを重視している感じです。もちろん、単体でみたときに容量もビルド時間も減らしたいですが...。
シェルスクリプトがうまく共通化できればよさそうですが、統一はなかなか難しそうかも・・・ |
VSCodeとかなら、Dockerコンテナを起動するとこからコンテナ上で作業するとこまでサポートしてくれる公式extensionがあったりしますね!
そうです!
なるほどです! |
こちら、本格的に進められればと考えています。 いろいろまとめつつ提案すると、こんな感じでしょうか。
まあ、とりあえず2をやって、余力あれば3かなと思いました! |
もしよければまた @aoirint さんのお力を借りたいのですが、おまかせできたりしませんか・・・・・・・? 👀 このタスクはたぶんActions周り・docker周りと、あとlinux周りの知識が必要だろうなと感じてます。 もしよければぜひお願いしたいです 🙇♂️ |
ちょっと個人的に色々試してみたことで得られた知見を書いておきます
ちなみにビルド時の依存は
とりあえずこんな感じでしょうか? あとファイルアクセスや権限周りも怪しい気がするのですが自分はその辺りのベストプラクティスが見つけられませんでした。 |
ENTRYPOINTについて
補足としてどういう挙動になるかという説明を書いておくと、以下のような形になると思います(実際にはPythonに ENTRYPOINT命令DockerfileENTRYPOINT [ "gosu", "user", "python", "run.py" ]
CMD [] 実行例# 実行例1. 実行されるコマンド: `gosu user python run.py`
docker run --rm voicevox/voicevox_engine:latest
# 実行例2. 実行されるコマンド: `gosu user python run.py --help`
docker run --rm voicevox/voicevox_engine:latest --help
# 実行例3. 実行されるコマンド: `gosu user python run.py gosu user python run.py`(エラー)
docker run --rm voicevox/voicevox_engine:latest gosu user python run.py CMD命令DockerfileENTRYPOINT []
CMD [ "gosu", "user", "python", "run.py" ] 実行例# 実行例1. 実行されるコマンド: `gosu user python run.py`
docker run --rm voicevox/voicevox_engine:latest
# 実行例2. 実行されるコマンド: `--help`(エラー)
docker run --rm voicevox/voicevox_engine:latest --help
# 実行例3. 実行されるコマンド: `gosu user python run.py`
docker run --rm voicevox/voicevox_engine:latest gosu user python run.py コメント考えたことを参考として書いておきます。 使いやすさの面では、 なお実際の変更内容としては、 いまの 互換性の維持を重視するのであれば、現状引数でしか変更できない設定について、対応する環境変数を追加して、環境変数で設定を変更できる範囲を広げるという方法もあると思います。こちらの方法の場合、引数と環境変数の優先度について考える必要が出る可能性があって、こちらはこちらで互換性に影響するかもしれません。 メリット・デメリットについて
VOICEVOX ENGINEでは、実行ファイルの名前はDockerイメージの名前と同じ 一方で、ENTRYPOINTで指定したコマンドではない他のコマンドを実行することは複雑になります。イメージ内に存在するコマンドを実行したつもりでも、上記ENTRYPOINT命令の実行例3のように、意図しないコマンドに変換されて実行に失敗するようになります。 ただし、Dockerfileで また、上記ENTRYPOINT命令の実行例3の場合に、 Dockerイメージ開発の方向性について
このIssueで言及のある開発用途のDockerイメージ #482 (comment) という観点では、build_utilディレクトリ以下のスクリプトも実行できることが望ましいと思います。 しかしヒホさんの言及 #482 (comment) のように、開発用途のDockerイメージについて考えるより、一般ユーザ向けのDockerイメージで、バイナリと同様に Dockerイメージ 互換性についてCMDを明示して変更しているユーザに対しては破壊的変更なので、変更時には、互換性を維持できるか、維持するかの検討と、ユーザ向けの告知は必要だと思います。 さらに踏み込むと、こういった、Dockerイメージでどういったインタフェースをユーザに提供することを保証するか、保証しないかという点について、自動テストで確認するようにできないかなと思っています。自動テストが実装されているPythonコードと違って、どこを変更しても構わないか分からないので、Dockerfileを変更しにくい状態になっていそう、という課題を感じています。 |
Dockerイメージ内のファイルアクセスや権限周りについて
Dockerイメージのビルド時や実行時の範囲でいうと、gosuや一般ユーザを使っている理由については、以前言及していた ( #96 (comment), #105 (comment) ) ことはあるんですが、当時とは状況や考え、理解が変わっている部分もあると思います。gosu周り以外でも、気になった点があれば教えてほしいと思います。 Pythonプロセスを一般ユーザで実行した方がいいという考えは変わっていませんが、過去に議論したことがある点も含めて、いまのDockerイメージにはいろいろと課題があると思っています。参考として・整理のため:
Dockerの新しい機能で、以下のようにしてイメージサイズを増やさずに、ビルド間で指定ディレクトリのキャッシュを共有できるようになっています。 RUN --mount=type=cache,uid=1000,gid=1000,target=/home/user/.cache/pip <<EOF
set -eu
gosu user /opt/python/bin/pip install -r ./requirements.txt
EOF
以下のようにして、Dockerイメージビルド時に gosu user /opt/python/bin/python -m compileall /opt/voicevox_engine |
#322 の実現について
VOICEVOX ENGINEのarm64版Dockerイメージは提供されている #639 と思うので、arm64版PyInstallerバイナリを提供するということになると思います。 QEMUによるCPUエミュレーションはDockerであっても、そうでない仮想環境であってもビルド時間が長くなると思うので、できればPyInstallerに、x64環境でarm64ビルドを可能にする、クロスコンパイル機能があればいいなとは思っています。 その前にarm64環境では、python-soundfileライブラリがlibsndfileを同梱していないため、libsndfileの事前インストールが必要という課題 #839 があって、私がpython-soundfile側にPRを出して解決するというところで、申し訳ないんですが、手が止まっていると思います。こちらについては今後進めていければと思っています。 |
実行用イメージの依存関係について
指摘の通りで、依存を減らしていけるといいと思います。 Pythonライブラリのインストール時にgccやmakeを使ったビルドを要求される場合に対応するため、 注意が必要そうな点としては、Pythonバージョンやパッケージバージョンを変更した場合にも動作し続けるかどうかで、 |
ダウンロードファイルのキャッシュについて
この点については、許容してもいいと思っていますが、ビルド時間を短くするために、なにかいい方法があるかもしれません。 GitHub Actionsでの実行については、ベースイメージに更新がない場合、masterブランチのビルドキャッシュが利用されます。ベースイメージに更新がある場合、masterブランチのビルドキャッシュは破棄されて、ベースイメージの更新・OSパッケージの更新をリリースに反映することができるようになっていると思っています。 ローカル環境での実行については、ベースイメージを更新しない限りはローカルのDockerイメージのビルドキャッシュが使われると思います。 ベースイメージを更新しても、基本的にはダウンロード成果物の内容が変わるわけではないので、確かにキャッシュを利用したい気はします。ダウンロードロジックやダウンロードに使ったプログラムに問題があることがわかった場合、キャッシュを捨てるのが難しくなるという懸念はあると思います。 実装方法としては、ダウンロード成果物を詰めたスクラッチイメージをビルドしてタグを打ち、VOICEVOXでメンテナンスするような形が思いつきます。 キャッシュ周りについては他に、リリース時にビルドがうまくいかなかったとき、バージョン番号を再利用する運用することがある関係で、DockerイメージのキャッシュはURL文字列ベースの比較になってしまうので、キャッシュがうまく動いているか不安にはなります。 エンジンのDockerイメージでリリース時にビルドキャッシュを保存しないようにしている理由は、VOICEVOX ENGINEは現状マイナーバージョンごとにブランチを切っていて、マイナーバージョンごとにキャッシュを分離する仕組みを実装するのが難しくて、保留になっているという認識です。 他に、ダウンロードファイルのハッシュ値をARGに持って、期待されたファイルがダウンロードされているか検証するような変更はできるかもしれません。 |
@sabonerune
に関しては、バーボイスボックスリソースの方が圧倒的に容量がでかいので現状の優先度的には低そうに感じました。
これは盲点でした。後のコメントにまとめて書きますが、個人的には変更に賛成です! |
@aoirint 色々ありがとうございます、勉強になりました!!
run.pyまでENTRYPOINTに含める形で良さそうに思いました!
難しいところですが、まあ案内すればOKな範疇に思いました!
個人的にはこうかなぁと。
--
個人的にはむしろ動かない方が良い気がしました!
CUDA imageとpython imageでディストリが違うのは盲点でした! ただその代わりarm64が超課題になります。。。。。
と思ったらarm64のことを検討してくださってました!! 確かにビルドするためにarm64のDocker環境必要そうだなと感じました。。。 や~~~~~~~~Docker環境でのビルドを考えるとなかなかの大改革が必要そうですねぇ。。。 ちょっとジャストアイディアですが、もしかしたら参考になるかもと思ったのでアイデアメモまで。
|
↑でちょこっと言及した 一言でいうと万能ではないなという印象でした。 ビルドするツールではなく |
内容
ドキュメントでは
Docker イメージ
の提供のみが案内されています。https://github.com/VOICEVOX/voicevox_engine/tree/211c48ef85eb0ccf4fcf2b2daa4a51dbace1464b#docker-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8
でも実際はDockerfileを使ってビルドや開発環境の構築もできます。
このisuseはdocker版やDockerfileが何を提供するかを明確にするissueです。
Pros 良くなる点
docker版の扱い方が決まってメンテナンス性が上がる。
Cons 悪くなる点
実現方法
現状を整理して意見を集める。
The text was updated successfully, but these errors were encountered: