vscode远程调试docker中的python服务
vscode远程调试docker中的python服务
环境:windows Docker Desktop , Vscode
阅读前,默认你对以下内容有基本了解:docker-compose.yml, Dockerfile, Vscode python 调试配置, flask 服务
原本想使用python pdb来调试,但是在容器环境中使用pdb,需要直接在容器终端中启动python程序,不方便 然后找到一个远程调试工具:debugpy,它将在容器中运行,等待vscode的连接(可配置等待模式),然后启动python程序。 配置好后就可以在vscode中调试容器中的python程序了。
远程调试flask服务
在docker 中调试flask服务时不要开启debug模式
例如:
if __name__ == '__main__':
# 本机访问:http://127.0.0.1:5000/
app.run(host="0.0.0.0", port=5000, debug=False)
原因是,开启debug后意味着开启了flask的重新加载机制,由于使用debugpy远程调试的某种原因,flask的重载机制触发了,这会导致Python 会创建一个新的进程来运行新的代码。但是,原来的进程还在监听 debug 调试端口,所以当新进程尝试绑定同一个端口时会报 “Address already in use” 错误。
远程调试flask服务时,Dockerfile的示例
Dockerfile
# Use the Python 3.10 image as the base image
FROM python:3.10
# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE=1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED=1
# Set the working directory to /app
WORKDIR /app
# Copy all files in the current directory to /app
COPY . /app
# Dependencies required by the installation script
RUN pip install -r requirements.txt -i https://mirrors.cloud.tencent.com/pypi/simple
# Expose the port of the container
EXPOSE 5000
EXPOSE 5678
# run script
CMD ["python", "server.py"]
远程调试flask服务时,docker-compose.debug.yml 配置
这里使用的是docker-compose.debug.yml,是为了区别于docker-compose.yml
启动docker-compose.debug.yml的方式是:docker-compose -f docker-compose.debug.yml up
version: "3.9"
services:
pic_server:
build: ./
# tty: true
# stdin_open: true
# image: web_dl-main_server:latest
ports:
- "5000:5000"
- "5678:5678"
restart: always
volumes:
- ".:/app"
command: ["python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "--wait-for-client", "server.py"]
容器启动后,会自动执行command的设置的命令
这个命令会覆盖Dockerfile中的CMD命令,例如会覆盖Dockerfile原来的命令:CMD ["python", "server.py"]
远程调试flask服务时,vscode 的调试客户端配置
.vscode\launch.json
见后文:vscode 的调试客户端配置
调试我的web-dl服务
web-dl service github address: https://github.com/qyzhizi/web_dl
docker-compose.debug.yml 配置
这里使用的是docker-compose.debug.yml,是为了区别于docker-compose.yml
启动docker-compose.debug.yml的方式是:docker-compose -f docker-compose.debug.yml up
docker-compose.debug.yml
的内容是:
version: "3.9"
services:
main_server:
depends_on:
- redis
build: ./
env_file:
- .env
ports:
- "9000:9000"
- "5678:5678"
restart: always
volumes:
- ".:/app"
command: >
sh -c "python web_dl/cmd/celery_work > celery_work.log 2>&1 &
python -m debugpy --listen 0.0.0.0:5678 --wait-for-client web_dl/cmd/main"
redis:
image: "redis/redis-stack-server:latest"
容器启动后,会自动执行command的设置的命令
command: >
sh -c "python web_dl/cmd/celery_work > celery_work.log 2>&1 &
python -m debugpy --listen 0.0.0.0:5678 --wait-for-client web_dl/cmd/main"
这个命令会覆盖Dockerfile中的CMD命令,例如会覆盖Dockerfile原来的命令:CMD ["bash", "-c", "web_dl/cmd/run.sh"]
第一个命令:python web_dl/cmd/celery_work > celery_work.log 2>&1 &
,它是在后台执行一个python脚本web_dl/cmd/celery_work
,最后的&
表示后台执行
这里一定要后台执行,因为这个脚本不会终止。否者第二个命令就无法被终端执行,而是一直等第一个命令执行结束。
第二个命令:python -m debugpy --listen 0.0.0.0:5678 --wait-for-client web_dl/cmd/main"
, 它是启动docker远端调试服务的关键,python 启动debugpy,
并且监听0.0.0.0:5678
, --wait-for-client
表示等待客户端的连接接(docker这边启动的是服务端),客户端本文采用的vscode的python调试模块(后文再介绍相关配置)。
最后启动python 脚本web_dl/cmd/main
,这个脚本是python web服务的入口点。
vscode 的调试客户端配置
安装python 扩展插件
打开vscode的调试界面,如果你之前没有创建过launch.json, 那就选择创建launch.json 文件,然后选择调试器Docker: Debug in Container
,然后生成一个文件launch.json
接下来配置这个launch.json,如下:
{
// Use IntelliSense to understand related attributes。
// Hover to see descriptions of existing properties。
// For more information, please visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: remote attach",
"type": "python",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
"justMyCode": true
}
]
}
其中:
"connect": {
"host": "localhost",
"port": 5678
},
这个表示连接到本地的5678端口,因为调试的服务端是本地, 如果你的docker服务在其他地方,比如云端,那么这里需要填写机器的ip地址,可能还会有密码需要配置,
目前笔者还没有试过远程连接docker服务,先就不管了。
"justMyCode": true
表示只是调试你写的代码,第三方库的代码就不调试了,这里笔者也没有试过,先记录一下。
另外:
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
这个表示本地代码到docker容器的代码映射,因为在Dockerfile中,代码的根目录是/app
,所以"remoteRoot": "/app"
${workspaceFolder}
表示vscode的工作目录,这里是把当前工作目录与容器的/app
进行映射。
之所以要做映射,是因为在调试时,可以准确找到对应的代码。
参考
https://blog.hipolabs.com/remote-debugging-with-vscode-docker-and-pico-fde11f0e5f1c https://github.com/Microsoft/ptvsd/issues/1131