Projects that use docker for local development run into a problem when trying to use language servers with their text editor—they don’t handle multiple environments.
There are a few ways around it, but they all have trade-offs.
Running a remote language server
You can connect to a remote language server (it is a server after all) by wrapping the command in a script and configuring your text editor to use it.
For example (assuming you have docker container with
#!/bin/bash # Runs a python-language-server in a running container for use with # eglot in emacs. docker compose -f /path/to/my/docker-compose.yml \ exec \ -T \ myservice pyls
Everything works with the exception of jump-to-definition (at least when using Emacs
eglot). That’s because the file path returned by the language server is the file path in the container, not your host machine.
In Emacs, you can hack around this in
eglot (albeit in an inelegant way) by redefining
xref-make-file-location like so:
;; HACK: If the xref file doesn't exist, it probably came from a ;; remote LSP server using eglot. Try mapping it to the local ;; file system. Maybe someday it will be supported in eglot. ;; See: https://github.com/joaotavora/eglot/issues/350 (eval-after-load "xref" '(defun xref-make-file-location (file line column) (if (not (file-exists-p file)) (make-instance 'xref-file-location :file (format "~/your/host/file/path" file) :line line :column column) (make-instance 'xref-file-location :file file :line line :column column))))
Edit files in the remote language server container
To get around the compatibility issues that comes from running in two different environments (the host machine and the container), you can edit the files remotely in the container that is running the language server (in Emacs you can use docker-tramp). This keeps the environment consistent, but it’s a bit clunky when you need to remember where the files are and flipping back and forth (e.g. when doing a `git commit` from the host machine).