Using Helix Editor with a Dockerized Python LSP

Lars BlumbergLars Blumberg
2 min read

Running a LSP in a docker container definitely keeps your operating system clean from all dependencies required to run LSPs. Additionally that allows you to run and configure different LSPs in different containers for different projects.

The next section lists all files that you can set up to run a dockerized Python LSP that helix will connect to when editing Python files in your current project. All mentioned file paths are relative to your project’s root directory.

Set up these files in your project directory

pylsp/Dockerfile

FROM python:3.11-slim-bookworm
RUN pip install python-lsp-server[all]
CMD ["pylsp"]

docker-compose.yaml

services:
  pylsp:
    build:
      context: ./pylsp
    profiles:
      - pylsp
    volumes:
      - ./:${ROOT_DIR}/

Assigning a profile ensures that the pylsp service doesn’t auto-start together with your project’s regular docker stack. Instead the pylsp service is started and stopped by helix whenever you open helix inside your project directory.

Run docker compose build pylsp to initially create the LSP service container.

Makefile / .env

.env:
    echo "ROOT_DIR=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))" | tee .env

The language server container needs your local project root directory mapped to the very same path inside the container, independently of the project’s (sub-)directory from which you start the helix editor. Otherwise you run into directory mapping problems such as described in this helix github issue.

To address this we will keep a .env file around which we populate with your project’s root directory. This file is best created once from above Makefile by running make .env in your project’s root dir. By adjusting the volume mapping to the actual project path every developer can now check out your project at a different location in their file system.

In case you’ve moved your project elsewhere later, simply delete .env and rerun make .env.

Do not commit .env and instead add .env to the project’s .gitignore as this file is developer machine specific.

.helix/languages.toml

[[language]]
language-servers = ["pylsp"]
name = "python"

[language-server.pylsp]
args = ["compose", "run", "--build", "--rm", "pylsp"]
command = "docker"

Now the LSP container is started whenever you open helix in your project directory. The container will also nicely stop whenever you quit helix.

You could also configure LSP plugins such as flake8 via above .helix/languages.toml but that should rather be done inside pyproject.toml.

Choose different LSP plugins

Above setup installs the default plugins. You may however opt to use different plugins such as the great ruff plugin. Therefore add pip install python-lsp-ruff to the above Dockerfile and replace python-lsp-server[all] with python-lsp-server.

To install the mypy plugin add pip install pylsp-mypy to the Dockerfile.

0
Subscribe to my newsletter

Read articles from Lars Blumberg directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Lars Blumberg
Lars Blumberg

Full stack developer, CTO and CEO of tech startups.