• Stars
    star
    245
  • Rank 165,304 (Top 4 %)
  • Language
    Emacs Lisp
  • License
    GNU General Publi...
  • Created over 5 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Scripts and configurations to leverage lsp-mode in docker environment

lsp-mode uses lsp-docker to run language servers using in containers

./images/logo.png

Table of Contents

Preconfigured language servers

emacslsp/lsp-docker-langservers has the following content:

Usage

There are two ways of working with containerized language servers:

emacslsp/lsp-docker-langservers

This container is used by lsp-docker to run Language Servers for lsp-mode over local sources. You must pull the container before lsp-docker can use it

Configuration

  • Clone the repo
    git clone https://github.com/emacs-lsp/lsp-docker
        
  • Pull the container
    docker pull emacslsp/lsp-docker-langservers
        
  • Add repo to load path and register the docker clients in your ~/.emacs file
    ;; Uncomment the next line if you are using this from source
    ;; (add-to-list 'load-path "<path-to-lsp-docker-dir>")
    (require 'lsp-docker)
    
    (defvar lsp-docker-client-packages
        '(lsp-css lsp-clients lsp-bash lsp-go lsp-pylsp lsp-html lsp-typescript
          lsp-terraform lsp-clangd))
    
    (setq lsp-docker-client-configs
        '((:server-id bash-ls :docker-server-id bashls-docker :server-command "bash-language-server start")
          (:server-id clangd :docker-server-id clangd-docker :server-command "clangd")
          (:server-id css-ls :docker-server-id cssls-docker :server-command "css-languageserver --stdio")
          (:server-id dockerfile-ls :docker-server-id dockerfilels-docker :server-command "docker-langserver --stdio")
          (:server-id gopls :docker-server-id gopls-docker :server-command "gopls")
          (:server-id html-ls :docker-server-id htmls-docker :server-command "html-languageserver --stdio")
          (:server-id pylsp :docker-server-id pyls-docker :server-command "pylsp")
          (:server-id ts-ls :docker-server-id tsls-docker :server-command "typescript-language-server --stdio")))
    
    (require 'lsp-docker)
    (lsp-docker-init-clients
      :path-mappings '(("path-to-projects-you-want-to-use" . "/projects"))
      :client-packages lsp-docker-client-packages
      :client-configs lsp-docker-client-configs)
        

How it works

lsp-mode starts the image passed as :docker-image-id and mounts :path-mappings in the container. Then when the process is started lsp-mode translates the local paths to docker path and vice versa using the :path-mappings specified when calling lsp-docker-init-default-clients. You may use lsp-enabled-clients and lsp-disabled-clients to control what language server will be used to run for a particular project(refer to lsp-mode FAQ on how to configure .dir-locals).

emacslsp/lsp-docker-full

The container emacslsp/lsp-docker-full contains:

  • The above language servers
  • Emacs28 compiled with native JSON support for better performance.

Flags

FlagPurposeDefault
EMACS_D_VOLUMEEmacs folder to use for /root/.emacsEmacs: $(pwd)/emacs.d Spacemacs: $(pwd)/spacemacs
PROJECTS_VOLUMEDirectory to mount at /Projects$(pwd)/demo-projects/
TZTimezone to user in containerEurope/Minsk
DOCKER_FLAGSAny additional docker flagsN/A

Emacs

  • Clone lsp-docker.
    git clone https://github.com/emacs-lsp/lsp-docker
    cd lsp-docker
        
  • Run
    bash start-emacs.sh
        

Spacemacs

  • Clone lsp-docker.
    git clone https://github.com/emacs-lsp/lsp-docker
    cd lsp-docker
        
  • Clone spacemacs repo
    # Clone spacemacs develop
    git clone -b develop https://github.com/syl20bnr/spacemacs spacemacs
        
  • Run
    EMACS_D_VOLUME=/path/to/spacemacs bash start-spacemacs.sh
        

Custom language server containers

You can use manually built language containers or images hosting language server(s), just follow a few simple rules (shown below).

Building a container (or an image) manually:

You have 2 constraints:

  • A language server must be launched in stdio mode (other types of communication are yet to be supported)
  • A docker container (only container subtype, see the configuration below) must have your language server as an entrypoint (basically you have to be able to launch it with docker start -i <container_name> as it is launched this way with lsp-docker)

When you have sucessfully built a language server, you have to register it with either a configuration file or a .dir-locals file.

Registering a language server using a persistent configuration file:

A configuration file is a yaml file that can be located at:

<PROJECT_ROOT>/.lsp-docker.yml
<PROJECT_ROOT>/.lsp-docker.yaml
<PROJECT_ROOT>/.lsp-docker/.lsp-docker.yml
<PROJECT_ROOT>/.lsp-docker/.lsp-docker.yaml
<PROJECT_ROOT>/.lsp-docker/lsp-docker.yml
<PROJECT_ROOT>/.lsp-docker/lsp-docker.yaml
<PROJECT_ROOT>/.lsp-docker/config.yml
<PROJECT_ROOT>/.lsp-docker/config.yaml

It is structured in the following way:

lsp:
  server:
    type: docker
    subtype: container # Or image. container subtype means launching an existing container
    # image subtype means creating a new container each time from a specified image
    name: not-significant-but-unique-name # Must be unique across all language servers
    server: server-id-of-the-base-server # Server id of a registered server (by lsp-mode) 
    launch_command: "launch command with arguments" # Launch command of the language server
    # (selected by a server id specified above) in stdio mode
    # Note: launch_command is not used with container subtype servers
    # as a command is embedded in a container itself and serves as an entrypoint
  mappings:
    - source: "/your/host/source/path"
      destination: "/your/local/path/inside/a/container"

Registering a language server using a .dir-locals file:

Just refer to the source code and general conventions of using .dir-locals. The variable you need is lsp-docker-persistent-default-config, its content is merged with the lsp section from a configuration file (if present).

Automatic image building:

You can also build an image automatically (currently supported only for image subtype): just drop the corresponding Dockerfile into the .lsp-docker folder in the project root (Dockerfile may be named as Dockerfile or Dockerfile.lsp). Building process is triggered by the lsp-docker-register call (you will be prompted whether you want to build the image). Image building takes place in the project root (not in the .lsp-docker subfolder)! In case of an automatic build the image will be registered automatically (based on the values from the config or .dir-locals file).

You can also troubleshoot any issues with supplemental docker calls (checking whether the required image already exists, building a new image) using the supplemental logging functionality: there are 2 variables: first you have to set lsp-docker-log-docker-supplemental-calls to true-like value (by default it is nil) and then specify the log buffer in the lsp-docker-log-docker-supplemental-calls-buffer-name variable (by default it is set to *lsp-docker-supplemental-calls*)

Docker over TRAMP (TBD)

Docker running the language servers and hosting the sources, Emacs running on the desktop machine and connecting to docker instance over TRAMP.

See also

  • docker - package for managing docker images/containers.

Maintainers