要点
docker-composeを使ってマルチコンテナ「Nginx」「uWSGI+Django」「Postgres」を構成し、
これらをVSCodeと拡張機能のRemote-Containerを利用してビルド、コンテナ起動し、
「uWSGI+Django」コンテナ内でuwsgi --socket :8001 --module config.wsgi
を実行してデプロイして、
ブラウザからlocalhost:8001
にアクセスしてDjangoのデフォルトページを表示する、
というところまで環境を確立しました。
イメージ的にはこちらの記事の最初の方にある図で、GunicornをuWSGIに置き換えたような構成です。
https://zenn.dev/dsonoda/articles/dbe14ca8af617ed85b1f
ここまでは正常に動作しています。
次に、「uWSGI+Django」コンテナ内でのDjangoのデバッグ環境を構築しようと試みていますが、
Django内蔵サーバーで動かしたときのデバッグ方法は公式ドキュメントをはじめ色々と
情報があるものの、Nginx+uWSGIで動かしたときのデバッグ方法に関する情報が見つけられず、
自分なりに色々試したのですが、まだ確立できていません。
こうすればできるのでは、という情報がありましたらご教示いただきたくお願いします。
すでに試したこと
(開発環境とソースコードは後述の見出し「開発環境とソースコード」に記載しています)
まず、VSCodeの公式ドキュメントを読み込んだところ、いくつかデバッグ手法があるようでした。
それぞれのデバッグ手法とそれについてのコメントは下記のとおりです。
- Pythonのデバッグについて一番詳しく書いてあるが、コンテナ内でのデバッグ方法について触れられていない
https://code.visualstudio.com/docs/python/debugging
2. Djangoのデバッグについて書いてあるが、同様にコンテナ内での利用について触れられていない
https://code.visualstudio.com/docs/python/tutorial-django#_create-a-debugger-launch-profile
3. コンテナのデバッグに言及しているが、tasks.jsonを使ってビルドも含めた一連の処理を一括で行うやり方のようで、一筋縄にいかなさそうだった
https://code.visualstudio.com/docs/containers/quickstart-python#_build-run-and-debug-the-container
4. docker-composeを使ったpythonのデバッグ方法ということで、自分のニーズに一番近い情報だった
https://code.visualstudio.com/docs/containers/docker-compose#_python
上記の中で、自分のニーズに一番近い情報だった4番のやり方を実践してみることにしました。
昨年、VSCodeのpython拡張機能に取り込まれたdebugpyというデバッグ手法を使用しているみたいです。
debugpyパッケージの公式ドキュメントはこちらです。
https://github.com/microsoft/debugpy
まず、デバッガ構成ファイルlaunch.json
を下記のようにします。VSCodeの公式ドキュメントほぼそのままで、remoteRoot
のみ修正しました。
json
1{ 2 "version": "0.2.0", 3 "configurations": [ 4 { 5 "name": "Python: アタッチ", 6 "type": "python", 7 "request": "attach", 8 "connect": { 9 "host": "localhost", 10 "port": 5678 11 }, 12 "pathMappings": [ 13 { 14 "localRoot": "${workspaceFolder}", 15 "remoteRoot": "." 16 } 17 ] 18 } 19 ] 20}
次に、debugpyパッケージのインストールと起動、デバッガからの接続を待ち受ける設定をするため、docker-compose.yml
に下記を設定しました(実際には別ファイルとして作り、メインのdocker-compose.yml
を上書きする形にしています)。こちらもほぼ公式ドキュメントの丸コピーで、サービス名の変更くらいです。
yml
1# docker-compose.yml 2version: '3.8' 3 4services: 5 django: 6 command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 manage.py runserver 0.0.0.0:8000 --nothreading --noreload"] 7 ports: 8 - 8000:8000 9 - 5678:5678
しかし、このままだと、Django内蔵サーバーが起動してしまいます。uWSGIのエントリポイントはwsgi.py
ファイルとのことなので、config/wsgi.py
に変更したのが下記です(config
はDjangoのプロジェクトフォルダ)。
※一応、manage.py runserver
のパターンも確認しておこうと思い、別途、NginxとuWSGIを除いたDjango内蔵サーバーを使うコンテナを作成して上記で試しましたが、そのケースはうまくデバッガをアタッチできました。
yml
1# docker-compose.yml 2version: '3.8' 3 4services: 5 django: 6 command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 config/wsgi.py"] 7 ports: 8 - 8000:8000 9 - 5678:5678
ただ、このままではuWSGIが起動できない・・・。
そう思いつつも、とりあえず実行してみたところ下記のエラーが。
このエラーの内容について調べましたが、真の原因はわかりませんでした。
次に、debugpyのドキュメントに「スクリプトではなくモジュールも指定できる」と書いてあったので、下記のように変更しました。これなら、uwsgi
コマンドを引数ごと実行できそうで、行けそうな気がします。
yml
1# docker-compose.yml 2version: '3.8' 3 4services: 5 django: 6 command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m uwsgi --socket :8001 --module config.wsgi"] 7 ports: 8 - 8000:8000 9 - 5678:5678
しかし、F5でデバッガを実行すると下記エラーが・・・。
uwsgiの格納場所を調べたところ、/workspace/django/.venv/bin/uwsgi
にありましたので、確かに上記のパスには不一致です。uwsgiはpythonのモジュール扱いになると思ったのですが、モジュールは単にpyファイルのことを指すのでしょうか・・・。
以上のように、uwsgiを起動する場合のデバッグ方法がわからず困っています。
開発段階でuWSGIを使う人が少ないのか、ネットには情報がありませんでした(少なくとも私は見つけられませんでした)
断片的な知識の寄せ集めでこのようなことをしようとしているのでちょっと無理があったのかとも反省しつつ、同じことをやろうとしている人(やった人)はきっといると信じつつ、質問をさせていただきました。
開発環境とソースコード
開発環境
- Windows10 Pro
- WSL2 + Ubuntu20.04
- Docker Desktop for Windows 3.5.2(docker-compose 1.29.2)
- Python 3.8.10
- Django 3.2.5
- uWSGI 2.0.19.1
- Nginx 1.21.1
- PostgreSQL 13.3-1.pgdg100+1
- pipenv version 2021.5.29
- VSCode 1.59.0
VSCode拡張機能:
- Remote Development(SSH, Containers, WSLを含むパッケージ)
- Python
- Docker
※他にもありますが関係ありそうなもののみ列挙しました
ディレクトリ構成
ソースコード
前述のディレクトリ構成順に記載。
teratailの文字数制限があるので、関連がありそうなコードを優先的に載せています。
.devcontainer/docker-compose.yml
後述のdocker.compose.ymlを上書き
yml
1version: '3.8' 2services: 3 django: 4 volumes: 5 - .:/workspace:cached 6 command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m uwsgi --socket :8001 --module config.wsgi"] 7 ports: 8 - 8001:8001 9 - 5678:5678
django/.vscode/launch.json
json
1{ 2 // IntelliSense を使用して利用可能な属性を学べます。 3 4 "version": "0.2.0", 5 "configurations": [ 6 { 7 "name": "Python: アタッチ", 8 "type": "python", 9 "request": "attach", 10 "connect": { 11 "host": "localhost", 12 "port": 5678 13 }, 14 "pathMappings": [ 15 { 16 "localRoot": "${workspaceFolder}", 17 "remoteRoot": "." 18 } 19 ] 20 } 21 ] 22}
docker-setup.sh
sh
1#!/usr/bin/env bash 2 3pipenv --venv > /dev/null || pipenv install --skip-lock --dev --ignore-pipfile
docker-entrypoint.sh
sh
1#!/usr/bin/env bash 2 3# PostgreSQLの準備が整うまで待ってから実行 4if ["$DATABASE" = "postgres" 5then 6 echo "Waiting for postgres..." 7 8 while ! nc -z $DB_HOST $DB_PORT; do 9 sleep 0.1 10 done 11 12 echo "PostgreSQL started" 13fi 14 15if [ -z "${VIRTUAL_ENV}" ]; then 16 source "$(pipenv --venv)/bin/activate" 17fi 18 19python3 manage.py migrate 20 21exec "$@"
django/.devcontainer.json
json
1{ 2 "name": "django", 3 "dockerComposeFile": [ 4 "../docker-compose.yml", 5 "../.devcontainer/docker-compose.yml" 6 ], 7 "service": "django", 8 "shutdownAction": "none", 9 "forwardPorts": [ 10 80 11 ], 12 "extensions": [ 13 "donjayamanne.githistory", 14 "fabiospampinato.vscode-highlight", 15 "ckolkman.vscode-postgres", 16 "ms-python.vscode-pylance", 17 "ms-python.python", 18 "alexcvzz.vscode-sqlite", 19 "ms-azuretools.vscode-docker", 20 "eamodio.gitlens", 21 "visualstudioexptteam.vscodeintellicode", 22 ], 23 "workspaceFolder": "/workspace/django", 24}
django/Pipfile
[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] Django = "==3.2.5" psycopg2 = "*" psycopg2-binary = "*" uwsgi = "*" [dev-packages] pylint = "*" autopep8 = "*" pylint-django = "*" pillow = "*" [requires] python_version = "3.8"
.env.development
########## # setting for Django ########## # 0:not debug mode / 1: debug mode DEBUG=1 # Django unique secret key value SECRET_KEY=HIJKLMN # Host names to allow access to django apps DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] # Database process name DATABASE=postgres # database connection settings DB_ENGINE=django.db.backends.postgresql DB_NAME=app DB_USER=app DB_PASSWORD=password DB_HOST=postgres DB_PORT=5432 ########## # setting for postgres ########## POSTGRES_USER=app POSTGRES_PASSWORD=password POSTGRES_DB=app
docker-compose.yml
yml
1# Composeファイルフォーマット 2version: '3.8' 3 4services: 5 django: 6 container_name: django 7 build: 8 context: . 9 dockerfile: ./django/Dockerfile 10 command: uwsgi --socket :8001 --module config.wsgi 11 volumes: 12 - .:/workspace:cached 13 - ~/.gitconfig:/home/app/.gitconfig 14 - static_data:/workspace/django/static 15 - media_data:/workspace/django/media 16 tty: true 17 stdin_open: true 18 env_file: 19 - ./.env.development 20 depends_on: 21 - postgres 22 expose: 23 - "8001" 24 25 postgres: 26 container_name: postgres 27 image: postgres 28 ports: 29 - "5432:5432" 30 volumes: 31 - postgres_data:/var/lib/postgresql/data 32 env_file: 33 - ./.env.development 34 35 nginx: 36 container_name: nginx 37 build: 38 context: . 39 dockerfile: ./nginx/Dockerfile 40 ports: 41 - "8000:8000" 42 volumes: 43 - ./nginx/conf:/etc/nginx/conf.d 44 - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params 45 - static_data:/workspace/django/static 46 - media_data:/workspace/django/media 47 depends_on: 48 - django 49 50volumes: 51 postgres_data: 52 static_data: 53 media_data:
あなたの回答
tips
プレビュー