Debugging with vscode with persistent docker setup

Hello!

I have set up a development environment following GitHub - juliusknorr/nextcloud-docker-dev: Nextcloud development environment using docker-compose

However I can’t get debugging to work.

I have:

  • Installed xdebug extension in vs code
  • ran ./scripts/php-mod-config nextcloud xdebug.mode debug
  • selected a breakpoint

But no luck..

I saw NextCloud debugging help - #2 by christianlupus but can’t make sense of the path mapping mentioned;

I put the app in nextcloud-docker-dev/workspace/server/apps-extra/appName

Opened vscode in the appName folder (cd blabla/apps-extra/appName then code .).

created the following launch.json (in a .vscode folder in the appName root):

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "pathMappings": {
                "/var/www/html/apps-extra/appName": "${workspaceFolder:appName}"
            },
            "log": true
        }
    ]
}

And in the debug console I’m getting a bunch of activity (response, success: true), but execution does not stop at the breakpoints (and I have seen them being passed trough other means, like a log being written but execution should stop before..)


Could someone walk me trough how to get the debugging working? I just want to be able to step trough the code..

The thing is that you would typically have the complete server opened in vsCode. So, either open a multi-root project or use code blabla (in your example).

It could work without, then the path mapping would be like

   "/var/www/html/apps-extra/appName": ${workspaceFolder}

But I am not 100% convinced, that PHP will understand that this needs to stop if the root file index.php is not triggered.

Can you provide an excerpt of the logs? There is probably an error message available…

Christian

Hello! Thanks for helping me!

I’m not completely sure which log you want to see but:

Debug console in vscode between 'start debug', passing break and finally 'stopping'
Listening on { address: '::', family: 'IPv6', port: 9003 }
<- launchResponse
Response { seq: 0, type: 'response', request_seq: 2, command: 'launch', success: true }

<- initializedEvent
InitializedEvent { seq: 0, type: 'event', event: 'initialized' }

-> setBreakpointsRequest
{ command: 'setBreakpoints',
  arguments:
   { source:
      { name: 'GroupUserAddedListener.php',
        path:
         '/home/me/Documents/kod/nextcloud-docker-dev/workspace/server/apps-extra/appName/lib/Event/GroupUserAddedListener.php' },
     lines: [],
     breakpoints: [],
     sourceModified: false },
  type: 'request',
  seq: 3 }

<- setBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 3,
  command: 'setBreakpoints',
  success: true,
  body: { breakpoints: [] } }

-> setFunctionBreakpointsRequest
{ command: 'setFunctionBreakpoints',
  arguments: { breakpoints: [] },
  type: 'request',
  seq: 4 }

<- setFunctionBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 4,
  command: 'setFunctionBreakpoints',
  success: true,
  body: { breakpoints: [] } }

-> setExceptionBreakpointsRequest
{ command: 'setExceptionBreakpoints',
  arguments: { filters: [] },
  type: 'request',
  seq: 5 }

<- setExceptionBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 5,
  command: 'setExceptionBreakpoints',
  success: true,
  body: { breakpoints: [] } }

-> configurationDoneRequest
{ command: 'configurationDone', type: 'request', seq: 6 }

<- configurationDoneResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 6,
  command: 'configurationDone',
  success: true }

-> threadsRequest
{ command: 'threads', type: 'request', seq: 7 }

<- threadsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 7,
  command: 'threads',
  success: true,
  body: { threads: [] } }

-> setBreakpointsRequest
{ command: 'setBreakpoints',
  arguments:
   { source:
      { name: 'GroupUserAddedListener.php',
        path:
         '/home/me/Documents/kod/nextcloud-docker-dev/workspace/server/apps-extra/appName/lib/Event/GroupUserAddedListener.php' },
     lines: [ 17 ],
     breakpoints: [ { line: 17 } ],
     sourceModified: false },
  type: 'request',
  seq: 8 }

<- setBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 8,
  command: 'setBreakpoints',
  success: true,
  body:
   { breakpoints:
      [ { verified: true,
          line: 17,
          source:
           { name: 'GroupUserAddedListener.php',
             path:
              '/home/me/Documents/kod/nextcloud-docker-dev/workspace/server/apps-extra/appName/lib/Event/GroupUserAddedListener.php' },
          id: 1 } ] } }

-> disconnectRequest
{ command: 'disconnect',
  arguments: { restart: false, terminateDebuggee: true },
  type: 'request',
  seq: 9 }

<- disconnectResponse
Response { seq: 0, type: 'response', request_seq: 9, command: 'disconnect', success: true }

I don’t get any entries in docker compose logs -f --tail 1 nextcloud from just starting and stopping debugging in vscode, which probably is a bad sign xD

Now if my problems disappear if i open the entire server I really don’t mind! As long as I can run git in the app folder without it being disturbed by the rest..

To clarify, my full path to the app is

/home/me/Documents/kod/nextcloud-docker-dev/workspace/server/apps-extra/appName/

You suggest running code from the “server” directory?

I suppose I would need to change the mapping, I also saw in your cookbook example that you have one mapping for just “/var/www/html”: “${workspaceFolder:base}” but there is no “base” folder anywhere I looked..?

Thanks again!

With cookbook, I have a multi-root project. The different roots are aliased and one is called. base. Thus, the name there.

I missed one part: Do a ./scripts/php-mod-config nextcloud xdebug.log_level 7 to make the container output what it is doing while using xdebug. After it is running, you can set it to 1 instead of 7. Then, the container should be much more verbose (similar to the output of VS code).

If you change the path mapping do not forget to stop/start the debugger in code to make the new settings active.

Let’s try it out: put "/var/www/html/apps-extra/appName": ${workspaceFolder} in the launch file and see if the logs are still pointing to the folder under /home.

Chris

Ah I see, that indeed made it much more verbose:

$ docker compose logs -f --tail 1 nextcloud
nextcloud-1  | [Sun Sep 28 18:03:01.622106 2025] [core:notice] [pid 1:tid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
nextcloud-1  | 
nextcloud-1  | ==> /var/log/xdebug.log <==
nextcloud-1  | [1412] Log opened at 2025-09-28 18:03:36.119248
nextcloud-1  | [1412] [Config] INFO: Control socket set up successfully: '@xdebug-ctrl.1412'
nextcloud-1  | [1412] [Config] INFO: Trigger value for 'XDEBUG_TRIGGER' not found, falling back to 'XDEBUG_SESSION'
nextcloud-1  | [1412] [Config] INFO: Trigger value for 'XDEBUG_SESSION' not found, so not activating
nextcloud-1  | Sun Sep 28 18:03:36 2025 (1412): [Error] APM: Locking APM for 300 seconds for reason: Cannot connect to the agent
nextcloud-1  |  
nextcloud-1  | 
nextcloud-1  | ==> /var/log/xdebug.log <==
nextcloud-1  | [1412] Log closed at 2025-09-28 18:03:36.442015
nextcloud-1  | 
nextcloud-1  | [1429] Log opened at 2025-09-28 18:05:01.696275
nextcloud-1  | [1429] [Config] INFO: Control socket set up successfully: '@xdebug-ctrl.1429'
nextcloud-1  | [1429] [Config] INFO: Trigger value for 'XDEBUG_TRIGGER' not found, falling back to 'XDEBUG_SESSION'
nextcloud-1  | [1429] [Config] INFO: Trigger value for 'XDEBUG_SESSION' not found, so not activating
nextcloud-1  | [1429] Log closed at 2025-09-28 18:05:02.170624
nextcloud-1  | 

I cleared some heartbeat notifications a open browsersession was triggering

Is this the about the docker compose tweak @stuma was talking about in the other thread? I kinda glossed over it..

How do you activate the debugging process? The user stuma configured it statically which will send every request into debug mode (I do not like this, personally).

Instead, you can use an add-on for your browser or set XDEBUG_SESSION to any non-empty text in the GET parameters. I suspect, you know what you are to do (otherwise ask).

1 Like

That was the last piece of the puzzle, thank you!

I didn’t know one had to further activate the debugging process, I thought that was handled from “start debugging” in vscode (since it already has to communicate breakpoints and so on). That was also how it behaved with the nextcloud devcontainer, so it set my expectations.

I have to say, needing to activate debug in three places is a bit silly (./scripts/php-mod-config nextcloud xdebug.mode debug, vscode “start debugging” and in the browser aswell..).

Well it works now anyway, thank you for the help!

Well, not really.

The php-mod-config must be done only once per container. So, you can more or less forget about this.

As you are not ctually starting the loading of the website in VS code, PHP will actively connect to VS code once a browser request is received. So, not VS code starts the debuging directly. To indicate for the browser to start a session, you have to activate it using the XDEBUG_SESSION variable. To make VS code listen for actual requests (by PHP) you have to start the “debug” session there. It just starts the server on port 9003 to wait PHP’s requests.

PS: Do not forget to disable the logging to reasonable values.

1 Like

Follow up on this: If I want to debug occ calls, how do I do that? Should I set it up like stuma did or is there some way to catch debugging in both browser triggered events and such that i trigger in the commandline with php occ myapp:settings or w/e?

Thanks again!

Hello.

See this URL: Xdebug: Documentation » Step Debugging

You can simply set a environment variable and PHP should start a debugging session. If this is inside a docker container, you have to be a bit careful, to get it right: the environment must be changed inside the container and the network of the body must be addressed correctly to reach the ide from within the container. So, best test it out before starting an actual debugging session.

Chris

1 Like

Hi,

When your debugging with VSCode, you have to keep in mind that the debugger listening point (listen on 9003 port) is a node server program, that will communicate with your IDE. If your editing your code on a remote Linux server (by example), when you “start debugger”, this launches the node (debug params) on the Linux server.

So, your xdebug.ini, in your docker, must point to that node server. In the julius docker (wich i’ve been using sometimes), the address to use is 172.17.0.1. Should be host.docker.internal if it was defined, but i’ts not apparently. You can check this on your install.

Here is the content of my xdebug.ini, that is located in /usr/local/etc/php/conf.d. The main points are xdebug.mode, client_host and start_with_request.

xdebug.mode = debug
xdebug.idekey=VSCODE
xdebug.trace_output_name=trace.%R.%u
xdebug.profiler_output_name=profile.%R.%u
xdebug.output_dir=/shared

xdebug.log = /var/log/xdebug.log
xdebug.log_level = 1

xdebug.discover_client_host=true
xdebug.client_host=172.17.0.1

xdebug.start_with_request = yes 
xdebug.trace_format=0

Also, the debugger won’t catch your code if your mapping is not correct.
In the VSCODE debug configuration, you MUST map the path in the docker with the IDE source editing point, eg (pathMappings)


		{
			"name": "Listen for Xdebug",
			"type": "php",
			"request": "launch",
			"port": 9003,
			"pathMappings": {
				"/var/www/html/":"/home/seb/src/nextcloud-src-dev/"
			}
		},

Hope it helps,

1 Like