File: README.org

package info (click to toggle)
emacs-lsp-docker 1.0.0%2Bgit20250423.ff41f4a-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 348 kB
  • sloc: lisp: 705; sh: 50; makefile: 24; cpp: 19; javascript: 13; python: 10
file content (216 lines) | stat: -rw-r--r-- 12,656 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

#+ATTR_HTML: align="center"; margin-right="auto"; margin-left="auto"
=lsp-mode= uses =lsp-docker= to run language servers using in containers

[[./images/logo.png]]

[[https://melpa.org/#/lsp-docker][file:https://melpa.org/packages/lsp-docker-badge.svg]]
[[https://stable.melpa.org/#/lsp-docker][file:https://stable.melpa.org/packages/lsp-docker-badge.svg]]
[[https://github.com/emacs-lsp/lsp-docker/actions][file:https://github.com/emacs-lsp/lsp-docker/workflows/CI/badge.svg]]

* Table of Contents                                       :TOC_4_gh:noexport:
  - [[#preconfigured-language-servers][Preconfigured language servers]]
  - [[#usage][Usage]]
  - [[#emacslsplsp-docker-langservers][emacslsp/lsp-docker-langservers]]
    - [[#configuration][Configuration]]
    - [[#how-it-works][How it works]]
  - [[#emacslsplsp-docker-full][emacslsp/lsp-docker-full]]
    - [[#flags][Flags]]
      - [[#emacs][Emacs]]
      - [[#spacemacs][Spacemacs]]
  - [[#custom-language-server-containers][Custom language server containers]]
    - [[#building-a-container-or-an-image-manually][Building a container (or an image) manually:]]
    - [[#registering-a-language-server-using-a-persistent-configuration-file][Registering a language server using a persistent configuration file:]]
    - [[#registering-a-language-server-using-a-dir-locals-file][Registering a language server using a =.dir-locals= file:]]
    - [[#automatic-image-building][Automatic image building:]]
  - [[#docker-over-tramp-tbd][Docker over TRAMP (TBD)]]
  - [[#see-also][See also]]
  - [[#maintainers][Maintainers]]

** Preconfigured language servers
   =emacslsp/lsp-docker-langservers= has the following content:
   - Language servers:
     | Language              | Language Server                   |
     |-----------------------+-----------------------------------|
     | Bash                  | [[https://github.com/mads-hartmann/bash-language-server][bash-language-server]]              |
     | C++                   | [[https://github.com/MaskRay/ccls][ccls]]                              |
     | CSS/LessCSS/SASS/SCSS | [[https://github.com/vscode-langservers/vscode-css-languageserver-bin][css]]                               |
     | Dockerfile            | [[https://github.com/rcjsuen/dockerfile-language-server-nodejs][dockerfile-language-server-nodejs]] |
     | Go                    | [[https://golang.org/x/tools/cmd/gopls][gopls]]                             |
     | HTML                  | [[https://github.com/vscode-langservers/vscode-html-languageserver][html]]                              |
     | JavaScript/TypeScript | [[https://github.com/theia-ide/typescript-language-server][typescript-language-server]]        |
     | Python                | [[https://github.com/python-lsp/python-lsp-server][pylsp]]                             |
** Usage
   There are two ways of working with containerized language servers:
   - 2 containers provided by =lsp-docker=:
      - [[#emacslsplsp-docker-langservers][emacslsp/lsp-docker-langservers]]
      - [[#emacslsplsp-docker-full][emacslsp/lsp-docker-full]]
   - [[#custom-language-server-containers][Custom language server containers]]

** 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
      #+begin_src bash
      git clone https://github.com/emacs-lsp/lsp-docker
      #+end_src
    - Pull the container
      #+begin_src bash
      docker pull emacslsp/lsp-docker-langservers
      #+end_src
    - Add repo to load path and register the docker clients in your =~/.emacs= file
      #+begin_src elisp
      ;; 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)
      #+end_src
*** 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
    | Flag            | Purpose                                | Default                                               |
    |-----------------+----------------------------------------+-------------------------------------------------------|
    | EMACS_D_VOLUME  | Emacs folder to use for =/root/.emacs= | Emacs: =$(pwd)/emacs.d= Spacemacs: =$(pwd)/spacemacs= |
    | PROJECTS_VOLUME | Directory to mount at /Projects        | =$(pwd)/demo-projects/=                               |
    | TZ              | Timezone to user in container          | Europe/Minsk                                          |
    | DOCKER_FLAGS    | Any additional docker flags            | N/A                                                   |
**** Emacs
     - Clone =lsp-docker=.
       #+begin_src bash
       git clone https://github.com/emacs-lsp/lsp-docker
       cd lsp-docker
       #+end_src
     - Run
       #+begin_src bash
       bash start-emacs.sh
       #+end_src
**** Spacemacs
     - Clone =lsp-docker=.
       #+begin_src bash
       git clone https://github.com/emacs-lsp/lsp-docker
       cd lsp-docker
       #+end_src
     - Clone spacemacs repo
       #+begin_src bash
       # Clone spacemacs develop
       git clone -b develop https://github.com/syl20bnr/spacemacs spacemacs
       #+end_src
     - Run
       #+begin_src bash
       EMACS_D_VOLUME=/path/to/spacemacs bash start-spacemacs.sh
       #+end_src

** 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).
   The docker images may feature an optional tag, if omitted _latest_ will be assumed.

*** 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:
#+begin_src
<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
#+end_src

It is structured in the following way:

#+begin_src yaml
  # single server configuration
  lsp:
    server:
      type: docker
      # subtype:
      # - "container": attach to an already running container
      # - "image": when image does not exist, try to build it based on the dockerfile found in the project-scope
      #   (see Automatic image building). An image might feature an optional tag, i.e. '<image>:<tag>'. If a
      #   tagless image is indicated 'latest' will be assumed.
      subtype: container
      # Image/container name to use for this language server.
      name: image-container-name
      # server id of a registered LSP server. You can find the list of registered servers evaluating:
      #
      # `(ht-keys lsp-clients)`
      #
      # source:
      # https://stackoverflow.com/questions/17066169/retrieve-keys-from-hash-table-sorted-by-the-values-efficiently
      server: server-id-of-the-base-server
      # an (optional) array of parameters (docker or podman) to launch the image with
      # initially intended to host the '--userns' parameter
      # NOTE: 'launch_parameters' are not used with 'container' subtype servers
      # in this case embed all required parameters when creating the server instead
      launch_parameters:
        - "--userns=nomap"
      # command to launch the language server 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 entrypoint
      launch_command: "launch command with arguments"
    mappings:
      # NOTE: the paths must be within the project this server is being build for
      - source: "/your/host/source/path"
        destination: "/your/path/inside/the/container"

  # multiple server configuration
  lsp:
    server:
      - type: ...
        subtype: ...
        ...                       # keys as in the classic single server case, e.g. type, subtype, etc...
      - ...                       # other single server configuration(s)
    mappings:                     # shared among all servers
      - source: <path-on-host>
        destination: <path-on-lang-server>
      ...                         # other mappings
#+end_src

*** 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
   - [[https://github.com/Silex/docker.el][docker]] - package for managing =docker= images/containers.
** Maintainers
   - [[https://github.com/yyoncho][yyoncho]]
   - [[https://github.com/rnikoopour][rnikoopour]]