Im trying to debug my Django process from vs code. But I am not able to get it to work. In my manage.py:
import ptvsd
try:
ptvsd.enable_attach("my_secret", address=('localhost', 3000))
except:
pass
In my docker-compose:
version: '3'
services:
db:
image: postgres
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
- "3000:3000"
depends_on:
- db
And my debug info in launch.json:
{
"name": "Attach (Remote Debug)",
"type": "python",
"request": "attach",
"localRoot": "${workspaceFolder}",
"remoteRoot": "/code",
"port": 3000,
"secret": "my_secret",
"host": "localhost"
},
Dockerfile:
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
EXPOSE 3000
When starting the debug session I get a message saying: "debug adapter process has terminated unexpectedly". Does anyone have any tips on how to get this working? Im running ptvsd 3.0.0 both on my computer and in the docker container.
Three points to check to debug Django in a Docker environment with VSCode:
VSCode remote debugging works only with ptvsd==3.0.0 for now (cf. VSCode documentation)
With docker-compose, ptvsd needs to be attached to the default route 0.0.0.0 in order to be reached from the host machine (like the Django development server)
ptvsd rely on sockets (which can be attached only once to a port) and Django development server reloads the manage.py file after each code changes in the project. So after each code modification, the debug server will fail to attach. To work around this problem, the best solution is to attach the ptvsd debugger in the wsgi.py file, which is only loaded once.
In order to enable remote debugging for Django apps in VS Code (e.g. when debugging docker containers), do the following:
Add ptvsd to your requirements.txt file
ptvsd == 4.3.2
To your launch.json, add this:
{
"name": "Remote Django App",
"type": "python",
"request": "attach",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/remote_root/of/your/app"
}
],
"port": 3000,
"host": "localhost"
}
(Edit the remoteRoot option to reflect your app).
To your manage.py, add this:
if __name__ == "__main__": # This already exists
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_project.settings") # This already exists
from django.core.management import execute_from_command_line # This already exists
from django.conf import settings
if settings.DEBUG:
if os.environ.get('RUN_MAIN') or os.environ.get('WERKZEUG_RUN_MAIN'):
import ptvsd
ptvsd.enable_attach(address = ('0.0.0.0', 3000))
print "Attached remote debugger"
execute_from_command_line(sys.argv) # This already exists
Note: The third if statement here ensures the debugger does not get attached again after a live reload.
Be sure to open port 3000 in your docker command or docker-compose.yml
Run your app:
python manage.py runserver 0.0.0.0:8000
Line-by-line debugging
Note: In some (non-Django) cases line-by-line debugging does not work, unless you use double backslashes (\) in your remoteRoot parameter (Viscual Studio Code), even though the remote server runs on Linux. E.g. "remoteRoot": "\\remote_root\\of\\your\\app"
Sources
Source 1
Source 2
Your problem is likely that the webserver is reloading your file and killing your connection. Put a print or log statemet in the start of your settings.py code and see if it is being loaded twice. Then run it with a no-reload flag. ptvsd==3.0.0 does work for as long as it is installed both on host and remote machine.
Related
I have been looking for a way to start a python debugger so I can debug my flask app which is being executed with gunicorn inside a docker container and then connect to it with my VSCode from outside.
But I dont find any solutions. In fact someone here suggests that it is not possible at all?
Is there a way to debug my flask app executed by gunicorn?
So it looks like this is very difficult, if not impossible atm, to do with gunicorn. So what I did was
Create a degub_app.py file in my project with :
from myapp.api import create_app
if __name__=="__main__":
app = create_app()
app.run('0.0.0.0', 8000, debug=False)
I created a debug container which runs nothing on start it just waiting idle like this in my docker-compose file:
api-debug:
image: "myapp:latest"
restart: on-failure:3
environment:
volumes:
- ./:/usr/src/app
depends_on:
- rabbitmq
- redis
- mongo
tty: true
stdin_open: true
command: tail -F anything
ports:
- 8000:8000
Then using VSCode with the Remote Container pluggin i attached to that container. This starts a new VSCode window and shows you the files inside the container.
Note Since the VSCode is now connected to the container I had to re-install the Python extension (you can look this up but it is easy just go to pluggins and re-install to container)
I created a launch.json inside the container to run the degub_app.py that I mentioned above like this:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Debug API",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}my_path/debug_api.py",
"console": "integratedTerminal",
"justMyCode": false
}
]
}
I have a container running on my host with a python process and I have the vs code installed on the host. Is it possible to debug the python process from the host installed vscode ? If yes, how can this be achieved ?
Since I do not know what python process you have running, I'll use FastAPI as an example.
First, you need to define a new configuration in the file <project_root>/.vscode/launch.json. To access this file, you can go to the Run & Debug section on the activity bar, and press the cog/wheel at the top.
Add a new item in the configurations like shown below.
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Remote Attach",
"type": "python",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "."
}
]
}
]
}
Now you need to include debugpy. If you are using a requirements file, you can just add it there. If you use Poetry, you can run poetry add debugpy in your terminal (the Dockerfile example shows how you can use Poetry in a docker image).
First option - In your Dockerfile you need to run debugpy and make it listen for port 5678.
Now the debugger will start every time you run the container and await attachment.
FROM python:3.10.0
# Set the working directory:
WORKDIR /usr/src
# Copy the pyproject.toml file (or requirements.txt) to cache them in the docker layer:
COPY [ "./src/pyproject.toml", "./"]
# Set the python path if needed.
# For example, if main.py is not located in the project root:
ENV PYTHONPATH="$PYTHONPATH:${PWD}"
# Upgrade pip and install Poetry:
RUN pip install --upgrade pip && pip install poetry==1.1.12
# Project initialization using Poetry:
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi
# Run the application:
CMD ["python", "-m", "debugpy", "--wait-for-client", "--listen", "0.0.0.0:5678", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload", "--reload-exclude", "tests"]
EXPOSE 8000 5678
Second option - Set up the debugger in the main.py file by adding the lines below. This means that the debugger will be attached to the container when it starts; if the debugger variable is set to True.
debugger = True
if __name__ == "__main__":
if debugger:
import debugpy
debugpy.listen(("0.0.0.0", 5678))
debugpy.wait_for_client()
uvicorn.run(
"main:app",
host="localhost",
port=8000,
log_level="info",
reload=True,
)
Both examples need the Dockerfile to expose the port 5678.
Now, after running the container, the debugger will "pause" and await attachment. To attach the debugger, go back to Run & Debug section on the activity bar in VSCode and select Python: Remote Attach from the dropdown menu and press play.
Now you should be able to use the debugger inside the docker container.
I want to debug my Django application using a docker container in Visual Studio Code.
Microsoft published a guide how to do that, which I followed step by step:
https://code.visualstudio.com/docs/containers/quickstart-python
But when I try to run the debugger, I get the following error message:
Timed out waiting for launcher to connect
Here is what I did step by step:
I initialized a simple Django application using django-admin startproject helloworld
In VS Code I opened the folder including the manage.py
Opened Command Palette Ctrl + Shift + P, and then selected Docker: Add Docker Files to Workspace...
Select Application Platform Python: Django
Include Docker Compose files No
Relative path to the app's entrypoint manage.py
What ports does your app listen on? 8000
VS Codes then creates several files (see below).
When I try to start the debugger (like in the guide), I get the following error message:
The terminal doesn't show any error messages, but the commands executed:
.vscode/launch.json:
{
"configurations": [
{
"name": "Docker: Python - Django",
"type": "docker",
"request": "launch",
"preLaunchTask": "docker-run: debug",
"python": {
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
"projectType": "django"
}
}
]
}
.vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "docker-build",
"platform": "python",
"dockerBuild": {
"tag": "dockerdebugging:latest",
"dockerfile": "${workspaceFolder}/Dockerfile",
"context": "${workspaceFolder}",
"pull": true
}
},
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": [
"docker-build"
],
"python": {
"args": [
"runserver",
"0.0.0.0:8000",
"--nothreading",
"--noreload"
],
"file": "manage.py"
}
}
]
}
Dockerfile:
# For more information, please refer to https://aka.ms/vscode-docker-python
FROM python:3.8-slim-buster
EXPOSE 8000
# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE 1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED 1
# Install pip requirements
ADD requirements.txt .
RUN python -m pip install -r requirements.txt
WORKDIR /app
ADD . /app
# Switching to a non-root user, please refer to https://aka.ms/vscode-docker-python-user-rights
RUN useradd appuser && chown -R appuser /app
USER appuser
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "helloworld.wsgi"]
requirements.txt:
# To ensure app dependencies are ported from your virtual environment/host machine into your container, run 'pip freeze > requirements.txt' in the terminal to overwrite this file
django==3.0.3
gunicorn==20.0.4
VS Code Version: 1.47.1
Python Extension Version: v2020.7.94776
The idea of debugging in vs code is to:
use debugpy to launch your code with a port, say 5678
in vscode to 'Remote Attach' to that process.
I may be wrong but what i can see from your code, you didn't attach to your process.
I wrote the way I did here, I use docker-compose and docker. My way is different with yours but you will get the idea...:)
My issue were missing packages. Docker usually works fine, I haven't had any issues before at all.
I originally installed docker like described in the official documentation:
https://docs.docker.com/engine/install/ubuntu/
But after I tried installing the docker.io package, debugging worked fine in VS Code:
sudo apt install docker.io
There's no errors compared to the vscode tutorial in your project. Cause the error is timeout waiting for luncher to connect, try restart docker service and reload your window in vscode.
Here is a clue and a workaround:
The instructions I followed had me open VS code inside my ubuntu WLS2 instance. Note: my app is just a generic python app, not django.
If I click this and change it to open as a windows folder, then fun debug, everything suddenly works for me. (It spins up the docker and connects to it with debug, does breakpoints etc.)
I think what is happening for me is that "sometimes" docker is starting the container/app on its own WSL instance and my ubuntu instance cannot route to it for the debug.
I say sometimes, because sometimes it works. I think it might be related to which application (docker, ubuntu, vscode) I start first when I boot my machine.
I've messed with the docker, resources, WSL integration settings, the windows firewall, and restarted various things.
I'm sure a proper fix is not that complicated, however running VS code in native windows is enough of a fix for me. I don't see why the added complexity of starting the VS code session inside WSL is actually necessary.
I am developing a Python Django app in a Dockerized container. I have successfully setup remote debugging to attach to my Django server inside of a container. Me configuration is as follows.
launch.json
{
"name": "Remote Django App",
"type": "python",
"request": "attach",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
"port": 9001,
"host": "localhost"
}
manage.py
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'llf_api.settings')
try:
from django.core.management import execute_from_command_line
from django.conf import settings
if settings.DEBUG:
if os.environ.get('RUN_MAIN') or os.environ.get('WERKZEUG_RUN_MAIN'):
import ptvsd
ptvsd.enable_attach(address=('0.0.0.0', 8001))
print("Attached remote debugger")
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
docker-compose.yml
services:
api:
image: ${DOCKER_IMAGE_BASE}:${DOCKER_TAG}
build:
context: .
dockerfile: ./Dockerfile.development
env_file:
- .env
environment:
- DATABASE_URL=postgres://username:password#db/db_name
volumes:
- .:/app
command: >
bash -c "wait-for-it --service db:5432
&& python3 manage.py runserver 0.0.0.0:8000"
ports:
- "9000:8000"
- "9001:8001"
depends_on:
- db
tty: true
stdin_open: true
The problem is that I run VS Code inside of a dev container (the Dockerfile.development above). So VS Code is essentially running within the same container the Django server is running which would make me think I need to attach to the local port (8001) the ptvsd is running on by setting my launch.json to the following:
launch.json
{
"name": "Local Django App",
"type": "python",
"request": "attach",
"host": "api",
"port": 8001
}
However this doesn't work. When I try to attach the debugger in VS Code it appears to eventually timeout. Does anyone know how this could be accomplished?
My understanding of how VS Code and my server were running was inherently wrong. The server and VS Code are running off of the same image but NOT the same containers. The containers are running side by side and therefore the local networking is not available to either.
To make this work I realized I needed the VS Code container to access the server's container via the debugging port opened on the host. The only way I know how to do that is by using docker.for.mac.localhost as the host. So all that needed to change from my original setup was the launch.json configuration.
launch.json
{
"name": "Remote Django App",
"type": "python",
"request": "attach",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
"port": 9001,
"host": "docker.for.mac.localhost"
}
VS Code now attaches to port 9001 which has been exposed on the host and connects to the host using docker.for.mac.localhost. It works!
trying to get remote debugging for my python flask API I have. I'm able to docker-compose up and have postman successfully call the running container, but when I try to attach the debugger, it never compiles. Below is my yml, dockerfile and vscode launch settings... the following error I get is:
There was an error in starting the debug server. Error = {"code":"ECONNREFUSED","errno":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1","port":5050}
version: '2'
services:
website:
build: .
command: >
python ./nomz/app.py
environment:
PYTHONUNBUFFERED: 'true'
volumes:
- '.:/nomz'
ports:
- '5000:5000'
- '5050'
DockerFile
FROM python:3.6-slim
ENV INSTALL_PATH /nomz
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
EXPOSE 5000 5050
VSCode Launch Settings
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"localRoot": "${workspaceFolder}/nomz/app.py",
"remoteRoot": "/nomz/",
"port": 5050,
"host": "localhost"
}
I finally got it working with remote debugging. I had to pip3 install ptvsd==3.0.0 on my local, and make sure that the requirements.txt for my docker container had the same version. (note: the latest version 3.2.1 didn't work)
#BrettCannon had the right link for a good tutorial
https://code.visualstudio.com/docs/python/debugging#_remote-debugging
What I had to do was add some code to the app.py of the flask app. I originally was getting address already in use error when starting the container, so I added the socket code and after the first successful attach of debugger I didn't seem to need it anymore (strange I know, but that's why I left it in in case someone else gets that error)
try:
import ptvsd
# import socket
# sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# sock.close()
ptvsd.enable_attach(secret=None,address=('0.0.0.0',5050))
ptvsd.wait_for_attach()
except Exception as ex:
print('Not working: ')
also i took the debug kwarg off the app.run() in app.py for the flask app.
This all gave me the ability to connect the debugger, but the breakpoints where "Unverified", so the last thing that had to happen was a path to the app.py in the launch.json for the remoteRoot. I will say I created a small test api to get this working, and it only need the first level of pathing (ie. /app and not /app/app/app.py)Here is a github of the test api I made (https://github.com/tomParty/docker_python). So if the debugger is attaching, but your breakpoints are unverified, play around with the path of the remoteRoot
"remoteRoot": "/nomz/nomz/app.py"