skip to Main Content

I would like to be able to make my code stop on breakpoints with VScode. My project is built with docker-compose and works without debugging on port 8000.

Here are my configurations files:

docker-compose:

version: '3.4'

services:
  murmurside:
    image: murmurside
    build: ./murmur_side
    command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m uvicorn app.main:app --host 0.0.0.0 --port 8000"]
    volumes:
      - ./murmur_side/:/murmur_side/
    ports:
      - 8000:8000
      - 5678:5678
    environment:
      - DATABASE_URL=postgresql://USERNAME:PASSWORD@db/fastapi_db_2

  db:
    image: postgres:13-alpine
    volumes:
      - postgres_data2:/var/lib/postgresql/data/
    expose:
      - 5432
    environment:
      - POSTGRES_USER=USERNAME
      - POSTGRES_PASSWORD=PASSWORD
      - POSTGRES_DB=fastapi_db_2

volumes:
  postgres_data2:

dockerfile :

# For more information, please refer to https://aka.ms/vscode-docker-python
FROM python:3.10-slim

EXPOSE 8000

WORKDIR /murmur_side

# 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
COPY requirements.txt .
RUN python -m pip install -r requirements.txt

COPY . /murmur_side

# Creates a non-root user with an explicit UID and adds permission to access the /app folder
# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /murmur_side
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", "-k", "uvicorn.workers.UvicornWorker", "app.main:app"]

launch.json :

I tested a ‘launch’ configuration but the debugger then bumps on the database related code. It does not seem to properly link to the database : after DATABASE_URL = os.getenv("DATABASE_URL") DATABASE_URL stays empty.

{
    "configurations": [
        {
            "name": "Docker: Python - Fastapi",
            "type": "docker",
            "request": "launch",
            "preLaunchTask": "docker-run: debug",
            "python": {
                "pathMappings": [
                    {
                        "localRoot": "${workspaceFolder}",
                        "remoteRoot": "/app"
                    }
                ],
                "projectType": "fastapi"
            }
        }
    ]
}

I also tested an ‘attach’ configuration. In that case, I get a debugger container launched at a random port but I get nothing when I browse to 127.0.0.1:randomPort

{
    "configurations": [
        {
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "connect": {
                "host": "0.0.0.0",
                "port": 8000     # I also tried with 5678
            },
            "preLaunchTask": "docker-run: debug",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "/murmur_side"
                }
            ]
        }
    ]
}

On this project I see that they added database credentials in the tasks.json. But I did not find any documentation stating that elsewhere. I tried that but I am unsure for the options other than username, password and dbname since I did not have to mention them in the docker-compose. Maybe I am also mistaking on the ports since there are several ones.

tasks.json:

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "docker-build",
            "label": "docker-build",
            "platform": "python",
            "dockerBuild": {
                "tag": "sd4timapi_pip_debug:latest",
                "dockerfile": "${workspaceFolder}/murmur_side/Dockerfile",
                "context": "${workspaceFolder}/murmur_side/",
                "pull": true
            }
        },
        {
            "type": "docker-run",
            "label": "docker-run: debug",
            "dependsOn": [
                "docker-build"
            ],
            "dockerRun": {      # I also tried without this section
                "image": "sd4timapi_pip_debug:latest",   
                "volumes": [
                    {
                        "containerPath": "/murmur_side/",
                        "localPath": "${workspaceFolder}/murmur_side/"
                    }
                ],
                "ports": [
                    {
                        "containerPort": 8000,
                        "hostPort": 8001,  # because it doesn't allow me to put 8000 : "port is already allocated"
                        "protocol": "tcp"
                    }
                ],
                "env": {
                    "APP_PORT": "8000",           #UNSURE
                    "DEBUG": "TRUE",
                    "ENVIRONMENT": "local",       #UNSURE
                    "POSTGRES_USER": "USERNAME",
                    "POSTGRES_PASS": "PASSWORD",
                    "POSTGRES_DBNAME": "fastapi_db_2",
                    "POSTGRES_HOST": "db_host",  #UNSURE
                    "POSTGRES_PORT": "5432",     #UNSURE
                    "POSTGRES_APPLICATION_NAME": "sd4timapi_pip_debug", #UNSURE
                  }
            },
            "python": {
                "args": [
                    "app.main:app",
                    "--host",
                    "0.0.0.0",
                    "--port",
                    "8000"
                ],
                "module": "uvicorn"
            }
        }
    ]
}

2

Answers


  1. This works for me, for debugging my FastAPI app in VS Code.

    Here’s the ".vscode/launch.json" file:

    {
      // Use IntelliSense to learn about possible attributes.
      // Hover to view descriptions of existing attributes.
      // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
      "version": "0.2.0",
      "configurations": [
        // Debug with FastAPI
        {
          "name": "Python: FastAPI",
          "type": "python",
          "request": "launch",
          "module": "uvicorn",
          "args": [
            "app.main:app",
            "--host",
            "0.0.0.0",
            "--port",
            "81",
            "--reload"
          ],
          "jinja": true,
          "justMyCode": false
        },
      ]
    }
    

    I get the following messages in the VS Code terminal logs, and then I can debug with breakpoints, etc.

    Go to http://localhost:81/docs in your browser since I deployed to port 81.

    INFO:     Will watch for changes in these directories: ['/workspace']
    INFO:     Uvicorn running on http://0.0.0.0:81 (Press CTRL+C to quit)
    INFO:     Started reloader process [13707] using WatchFiles
    INFO:     Started server process [13801]
    INFO:     Waiting for application startup.
    INFO:     Application startup complete.
    INFO:     127.0.0.1:36070 - "GET /docs HTTP/1.1" 200 OK
    
    Login or Signup to reply.
  2. Same issue, I was able to solve.

    docker-compose.debug.yaml:

    services:
    api:
        build:
            context: ./backend
            dockerfile: dockerfile
        container_name: api
        command: sh -c "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m uvicorn main:api --host 0.0.0.0 --port 8080 --reload"
        ports:
            - 8080:8080
            - 5678:5678
        environment:
            environment: dev
            db_name: dev
            db_host: http://localhost:8000
        volumes:
            - ./backend/:/app/
        depends_on:
            - surreal
    surreal:
        image: surrealdb/surrealdb:latest
        container_name: surreal
        ports:
            - 8000:8000
        command: start --log trace --user root --pass root --bind 0.0.0.0:8000
    

    launch.json:

    {
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "port": 5678,
            "host": "localhost",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}/backend",
                    "remoteRoot": "/app"
                }
            ]
        },
    ]
    

    }

    In main.py the FastApi app is named as api:

    from core import ValidationException, Db, routers
    from api.settings import Settings
    from fastapi import FastAPI
    
    
    settings = Settings()
    
    api = FastAPI(title='Api', version='1.0.0', openapi_url=settings.OPENAPI_URL)
    api.add_exception_handler(ValidationException, validate)
    db = Db(settings.DB_NAME, settings.DB_HOST)
    
    @api.on_event('startup')
    async def startup_event():
        routers.register(api)
        db.init()
    
    if __name__ == '__main__':
        import uvicorn
        uvicorn.run('main:api', host="127.0.0.1", port=8080, reload=True, proxy_headers=True)
    

    Hope it helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search