You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

4.4 KiB

DAP Remote Debugging Example

A minimal example showing how to debug a C++ program running in a remote container from any DAP-compatible client — Neovim, VSCode, Emacs, and others.

┌────────────────────────┐                         ┌──────────────────────┐
│      YOUR EDITOR       │     DAP over TCP        │      REMOTE          │
│  (Neovim, VSCode,…)    │ ◀─────────────────────▶ │  (Alpine container)  │
│                        │      port 13000         │                      │
│  • source code         │                         │  • codelldb DAP      │
│  • breakpoints         │                         │    server            │
│  • variable inspection │                         │  • debugapp (C++17)  │
│                        │                         │  • socat forwarder   │
└────────────────────────┘                         └──────────────────────┘

The remote container runs codelldb as a DAP (Debug Adapter Protocol) server. Your editor connects to it over TCP, sends a launch request, and codelldb starts the program on the remote. This avoids gdbserver's entry-point assembly issue entirely and keeps source paths clean.

Quick start (full setup)

The included docker-compose.yml spins up both the remote container and a Neovim-based devstation:

docker compose build
docker compose up -d remote          # start the codelldb DAP server
docker compose run --rm devstation   # interactive Neovim session

Inside Neovim, open src/calculator.cpp, press <leader>db on a line to set a breakpoint, then <leader>dc and select "Remote launch (codelldb remote:13000)".

See devstation/README.md for the full Neovim keybinding reference.

Using your own editor

You don't need the devstation container. Build and run the remote alone, then connect from whatever editor you prefer:

docker build -t dap-debug-remote -f remote/Dockerfile .
docker run -d --name remote \
  -p 13000:13000 \
  --cap-add SYS_PTRACE \
  --security-opt seccomp=unconfined \
  dap-debug-remote

Then follow the guide for your editor in remote/README.md — it covers VSCode, Neovim, Emacs, and generic DAP clients.

Repository layout

.
├── docker-compose.yml        # Two-service compose (remote + devstation)
├── README.md                 # This file
│
├── common/
│   └── project/              # C++ demo project (shared by both containers)
│       ├── CMakeLists.txt
│       └── src/
│
├── remote/
│   ├── Dockerfile            # Alpine + codelldb + socat + project build
│   ├── entrypoint.sh         # codelldb DAP server + socat forwarder loop
│   └── README.md             # Standalone usage + VSCode/other editor guides
│
└── devstation/
    ├── Dockerfile            # Alpine + Neovim (LazyVim) + nvim-dap
    ├── README.md             # Neovim keybindings and setup details
    ├── nvim-config/
    │   └── lua/plugins/      # LazyVim plugin specs (theme, lsp, dap)
    └── scripts/
        └── precompile-treesitter.lua

How it works

  1. codelldb runs on the remote as a DAP server (--port 13001 --multi-session). It binds to 127.0.0.1 only, so socat forwards external connections from 0.0.0.0:13000 to codelldb's listener.
  2. Your editor connects to port 13000 and sends a standard DAP launch request. codelldb starts the program on the remote, captures stdout/stderr, and streams output events back.
  3. The project source lives at /project on the remote (and on the devstation if you use it), so debug-info paths match and editors open source files correctly when stopped at a breakpoint.
  4. The remote entrypoint restarts codelldb after each session, so you can reconnect without restarting the container.
  5. SYS_PTRACE + seccomp:unconfined on the remote allow codelldb to debug the child process.

Note: codelldb is a glibc binary but runs on Alpine (musl) via gcompat plus a tiny shim library providing the missing __res_init symbol.