在容器中调试 Python
将 Docker 文件添加到 Python 项目时,会自动添加任务和启动配置,以便在容器内调试应用程序。为了适应 Python 项目的各种场景,某些应用可能需要进行额外配置。
配置容器入口点
你可以通过在 tasks.json 中设置属性来配置容器的入口点。当你首次使用 Containers: Add Docker Files to Workspace... 命令时,VS Code 会自动配置容器入口点。
示例:为 Python 模块配置入口点
{
"tasks": [
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": ["docker-build"],
"python": {
"module": "myapp"
}
}
]
}
示例:为 Python 文件配置入口点
{
"tasks": [
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": ["docker-build"],
"python": {
"args": ["runserver", "0.0.0.0:8000", "--nothreading", "--noreload"],
"file": "manage.py"
}
}
]
}
自动在浏览器中打开应用程序的入口页面
你可以选择 Containers: Python - Django 或 Containers: Python - Flask 启动配置,以自动在浏览器中打开应用的主页面。此功能默认启用,但你可以通过在 launch.json 中设置 dockerServerReadyAction 对象来显式配置此行为。
此功能取决于应用程序的以下几个方面
- 应用程序必须输出到调试控制台或 Docker 日志。
- 应用程序必须记录一条“服务器就绪 (server ready)”消息。
- 应用程序必须提供一个可浏览的页面。
以下是一个示例,演示如何根据特定的服务器消息模式,使用 dockerServerReadyAction 启动浏览器以打开 about.html 页面
{
"configurations": [
{
"name": "Containers: Python - Django",
"type": "docker",
"request": "launch",
"preLaunchTask": "docker-run: debug",
"python": {
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
"projectType": "django"
},
"dockerServerReadyAction": {
"action": "openExternally",
"pattern": "Starting development server at (https?://\\S+|[0-9]+)",
"uriFormat": "%s://:%s/about.html"
}
}
]
}
注意:在
pattern属性中找到的正则表达式仅尝试捕获类似于 "Starting development server athttps://:8000" 的记录消息。它适应 http or https 的 URL 变体、任意主机名以及任意端口。
重要的 dockerServerReadyAction 对象属性
-
action:找到匹配模式时要采取的操作。可以是debugWithChrome或openExternally。 -
pattern:如果应用程序记录的消息与上面显示的不同,请将 dockerServerReadyAction 对象的pattern属性设置为匹配该消息的 JavaScript 正则表达式。该正则表达式应包含与应用程序正在监听的端口相对应的捕获组。 -
uriFormat:默认情况下,Container Tools 扩展将打开浏览器的主页面(具体由应用程序决定)。如果你希望浏览器打开像上面示例那样的特定页面,则应将 dockerServerReadyAction 对象的uriFormat属性设置为包含两个字符串标记的格式化字符串,以指示协议和端口的替换。
如何在 Django 或 Flask 应用中启用热重载
当你为 Django 或 Flask 选择 Containers: Add Docker Files to Workspace 时,我们会为你提供配置好用于静态部署的 Dockerfile 和 tasks.json。每当你对应用代码进行更改时,都需要重新构建并重新运行容器。热重载允许你在容器继续运行的同时,直观地查看应用代码中的更改。通过以下步骤启用热重载:
对于 Django 应用
-
在 Dockerfile 中,注释掉将应用代码添加到容器的那一行。
#ADD . /app -
在
tasks.json文件的docker-run任务中,创建一个带有volumes属性的新dockerRun属性。此设置创建了从当前工作区文件夹(应用代码)到容器中/app文件夹的映射。{ "type": "docker-run", "label": "docker-run: debug", "dependsOn": [ "docker-build" ], "dockerRun": { "volumes": [ { "containerPath": "/app", "localPath": "${workspaceFolder}" } ] }, ... } -
编辑 python 属性,移除
--noreload和--nothreading。{ ... "dockerRun": { "volumes": [ { "containerPath": "/app", "localPath": "${workspaceFolder}" } ] }, "python": { "args": [ "runserver", "0.0.0.0:8000", ], "file": "manage.py" } } -
选择 Containers: Python – Django 启动配置并按下 F5 来构建和运行你的容器。
-
修改并保存任何文件。
-
刷新浏览器并验证更改是否已生效。
对于 Flask 应用
-
在 Dockerfile 中,注释掉将应用代码添加到容器的那一行。
#ADD . /app -
在
tasks.json文件的docker-run任务中,通过在env属性中添加FLASK_ENV以及添加volumes属性来编辑现有的 dockerRun 属性。此设置创建了从当前工作区文件夹(应用代码)到容器中/app文件夹的映射。{ "type": "docker-run", "label": "docker-run: debug", "dependsOn": [ "docker-build" ], "dockerRun": { "env": { "FLASK_APP": "path_to/flask_entry_point.py", "FLASK_ENV": "development" }, "volumes": [ { "containerPath": "/app", "localPath": "${workspaceFolder}" } ] }, ... } -
编辑 python 属性,移除
--no-reload和--no-debugger。{ ... "dockerRun": { "env": { "FLASK_APP": "path_to/flask_entry_point.py", "FLASK_ENV": "development" }, "volumes": [ { "containerPath": "/app", "localPath": "${workspaceFolder}" } ] }, "python": { "args": [ "run", "--host", "0.0.0.0", "--port", "5000" ], "module": "flask" } } -
选择 Containers: Python – Flask 启动配置并按下 F5 来构建和运行你的容器。
-
修改并保存任何文件。
-
刷新浏览器并验证更改是否已生效。
如何同时构建和运行容器
- 在前面提到的
tasks.json文件中,对docker-build任务存在依赖关系。该任务是tasks.json中tasks数组的一部分。例如
"tasks":
[
{
...
},
{
"label": "docker-build",
"type": "docker-build",
"dockerBuild": {
"context": "${workspaceFolder}",
"dockerfile": "${workspaceFolder}/Dockerfile",
"tag": "YOUR_IMAGE_NAME:YOUR_IMAGE_TAG"
}
}
]
提示:由于依赖关系明确指出 docker-build 是其依赖项,因此名称必须与此任务匹配。如果需要,你可以更改该名称。
-
JSON 中的
dockerBuild对象允许使用以下参数- context:构建上下文,从中调用你的 Dockerfile
- dockerfile:要执行的 Dockerfile 的路径
- tag:要构建的镜像的名称及其版本标签
-
总之,用于构建和调试 Flask 应用的 VS Code 设置可以是
-
launch.json{ "version": "0.2.0", "configurations": [ { "name": "Debug Flask App", "type": "docker", "request": "launch", "preLaunchTask": "docker-run: debug", "python": { "pathMappings": [ { "localRoot": "${workspaceFolder}", "remoteRoot": "/app" } ], "projectType": "flask" }, "dockerServerReadyAction": { "action": "openExternally", "pattern": "Running on (http?://\\S+|[0-9]+)", "uriFormat": "%s://:%s/" } } ] } -
tasks.json{ "version": "2.0.0", "tasks": [ { "type": "docker-run", "label": "docker-run: debug", "dependsOn": ["docker-build"], "dockerRun": { "containerName": "YOUR_IMAGE_NAME", "image": "YOUR_IMAGE_NAME:YOUR_IMAGE_TAG", "env": { "FLASK_APP": "path_to/flask_entry_point.py", "FLASK_ENV": "development" }, "volumes": [ { "containerPath": "/app", "localPath": "${workspaceFolder}" } ], "ports": [ { "containerPort": 5000, "hostPort": 5000 } ] }, "python": { "args": ["run", "--host", "0.0.0.0", "--port", "5000"], "module": "flask" } }, { "label": "docker-build", "type": "docker-build", "dockerBuild": { "context": "${workspaceFolder}", "dockerfile": "${workspaceFolder}/Dockerfile", "tag": "YOUR_IMAGE_NAME:YOUR_IMAGE_TAG" } } ] }
-
下一步计划
了解更多关于