PythonアプリケーションのDocker環境上でvirtualenvを有効化する
Docker環境上でvirtualenvを使う際の有効化についてのメモ。
今回使ったアプリケーションでは、Docker環境上でvirtualenvを使用するとライブラリのインポートが上手くいったのでvirtualenvを使用しました。 そもそもDocker環境上でvirtualenvを使う必要があるのか?という話はありますが、軽く調べたところ必要であるという意見も必要ないという意見もあったので、また別の機会に色々実験して調べてみたいと思います。
NGパターン
まずは自分が初めに失敗したNGパターンから。
virtualenv環境をイメージ作成時に有効にするだけだとコンテナ起動時は無効の状態になるので、virtualenv環境で起動したいときは、RUNだけでなくCMDでもactivateを適用して有効化する必要がある。
# activate RUN virtualenv env && . env/bin/activate && pip install -r requirements.txt # deactivate CMD ./dev_app.sh
また、次のようにRUNを複数に分けてしまうとactivateが次のRUNで引き継がれないので、virtualenv環境で行いたい処理は && で続けて書く必要がある。
# activate RUN virtualenv env && . env/bin/activate # deactivate RUN pip install -r requirements.txt # activate CMD . env/bin/activate && ./dev_app.sh
OKパターン
このようにすれば、有効化されたvirtualenv環境にライブラリをインストールでき、Dockerコンテナ上のvirtualenv環境でアプリケーションを起動できる。
# activate RUN virtualenv env && . env/bin/activate && pip install -r requirements.txt # activate CMD . env/bin/activate && ./dev_app.sh
ちなみに上記の例はUbuntuのOSを例にしており、sourceコマンドは使えないので代わりに" . "を使用している。
GAEのローカル開発サーバー起動時にプロンプトを無効化する
DockerでGAEのローカル開発サーバーをdev_appserverで起動する際、下記のような入力が必要な場合にエラーが発生してしまうので、このようなプロンプトを無効化したい。
For the latest release notes, please visit: https://dl.google.com/dl/cloudsdk/release/RELEASE_NOTES Do you want to continue (Y/n)?
調べたこと
gcloudコマンドには--quietフラグがあるようだ。
Disable all interactive prompts when running gcloud commands. If input is required, defaults will be used, or an error will be raised. Overrides the default core/disable_prompts property value for this command invocation. This is equivalent to setting the environment variable CLOUDSDK_CORE_DISABLE_PROMPTS to 1.
https://cloud.google.com/sdk/gcloud/reference
だが、dev_appserver.py --quiet は機能しない。
解決方法
環境変数 CLOUDSDK_CORE_DISABLE_PROMPTS を定義する方法だと無効化できた。
export CLOUDSDK_CORE_DISABLE_PROMPTS=1
Python2+GAEスタンダートのローカル開発サーバーで IOError: [Errno 13] file not accessible: '/dev/null'
Python2+GAEのローカル開発サーバーをdev_appserver.pyで起動しようとしたところ、下記のエラーがでた。
File "/usr/lib/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/python/runtime/stubs.py", line 303, in __init__
raise IOError(errno.EACCES, 'file not accessible', filename)
IOError: [Errno 13] file not accessible: '/dev/null'
原因
結論から言うと、App Engine Python 2.7 ランタイムで使用できる組み込みライブラリを、それ以外のライブラリを保存するプロジェクト内のディレクトリ(lib/)に入れてしまっていたことが原因だった。
App Engine Python 2.7 ランタイムに組み込まれているライブラリ
App Engine Python 2.7ランタイムに組み込まれているライブラリは、 app.yaml 内の libraries で指定するだけで使用できる。
app.yaml
libraries: - name: ssl version: latest - name: PIL version: latest
ローカル開発用サーバーで使用する前にローカルにインストールする必要があるライブラリ
ただし、App Engine Python 2.7ランタイムで使用できる組み込みライブラリの中でも、ローカル開発用サーバーで使用する前にローカルにインストールする必要があるライブラリもあるので、その場合は下記のようにローカルにインストールする。
pip install -r test_requirements.txt
App Engine Python 2.7 ランタイムに組み込まれていないライブラリ
上記以外のライブラリは、プロジェクト配下のディレクトリ(例:lib/)にインストールする必要がある。
pip install -t lib -r requirements.txt
逆に、App Engine Python 2.7 ランタイムに組み込まれているライブラリはプロジェクト配下のディレクトリ(例:lib/)に入れてはいけない。
GAEスタンダート環境のローカル開発サーバーをDockerで動かすときのDockerfileの置き場
DockerでPython+GAEスタンダートの開発環境を構築していた時に、下記のようなエラーに遭遇した。
File "/usr/lib/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/application_configuration.py", line 180, in __init__ When there is a Dockerfile in the current directory, the only supported runtime is runtime: custom. Please switch to runtime: custom. The devappserver does not actually use your Dockerfile, so please use either the --runtime flag to specify the runtime you want or use the --custom_entrypoint flag to describe how to start your application.
app.yamlのruntimeをpython27にしていたので、もしかしてcustomでしかできない??
と思って色々調べたりしていたが全然出てこない。
原因
今回はGAEスタンダード環境だが、フレキシブル環境のドキュメントにこう記載があった。
Dockerfile と app.yaml を同じディレクトリに置いていたので、おそらくフレキシブル環境と認識されてしまうのが原因かと思われる。
解決方法
Dockerfileをapp.yamlと同じ階層のココに置いていたが、
app - src - app.yaml - Dockerfile
1階層下に移動してみたら解決した。
app
- docker
- Dockerfile
- src
- app.yaml
結論
GAEスタンダート環境のローカル開発サーバーをDockerで動かす場合は、Dockerfile を app.yaml と同じカレントディレクトリに置いてはいけない。
(よく見たらエラー文ほぼそのままだった。。。)
Dockerで上の階層はCOPYできないので、ビルドコンテキストを上の階層にする
ディレクトリ構成がこういう場合のCOPYとビルドコンテキストについて。
app
- docker
- Dockerfile
- src
※ ビルドコンテキストとは、docker buildコマンドを実行したときのカレントディレクトリのこと
NGパターン
下記のように、Dockerfileがあるディレクトリで実行して上の階層をCOPYしようとするとエラーになる。
Dockerfile
COPY ../
ビルドコマンド
cd app/docker docker build -t [イメージ名:タグ] .
エラー
COPY failed: Forbidden path outside the build context: ../
OKパターン
上の階層はCOPYできないため、このようにCOPYしたいディレクトリで実行しDockerfileのパスを指定すれば正しく動作する。
Dockerfile
COPY .
ビルドコマンドの場合
cd app docker build -t [イメージ名:タグ] -f docker/Dockerfile .
docker-compose.yamlの場合
build: context: ./ dockerfile: ./docker/Dockerfile
DockerfileのCMD、docker-compose.yamlのcommandに、複数コマンドを複数行で書く
dockerコンテナを起動するときのコマンドを、複数コマンドまたは複数行で書く書き方のメモ。
複数コマンドを複数行で書く
Dockerfile
CMD sh -c “hogehogehoge && fugafugafuga && \
piyopiyopiyopiyopiyopiyopiyopiyopiyo"
docker-compose.yaml
Command: >
sh -c "hogehogehoge && fugafugafuga &&
piyopiyopiyopiyopiyopiyopiyopiyopiyo"