I'm working on a Rails project and using Docker containers with a web and a db container. The Rails files are on the laptop and mounted into the web container. The web container has the Ruby executable as well as the Gems -- including the Solargraph gem. The solargraph executable is the one that Bundler generates.

I am using Emacs 28.2 on macOS. I have the lsp-mode and lsp-docker packages loaded because features includes both of those symbols after I visit a Ruby file. I also have the projectile and projectile-rails packages loaded. The projectile-rails appears to work because after a visit a Ruby file, projectile-rails-find-controller works. I have a .lsp-docker.yml file at the root of my application:

    type: docker
    subtype: image
    name: lsp-docker-ruby-server
    server: "pedzsan/hatred:1.0"
    launch_command: "/root/bin/solargraph stdio"
    - source: "."
      destination: "/hatred"

The application is using .git as well as bundler.

What I'm wanting is for the lsp-mode to see the .lsp-bundler.yml file and know that it needs to talk to the solargraph language server via Docker using lsp-docker but I get the feeling that I'm miles off base and missing a very basic concept. None of the functions in lsp-docker.el seem to be getting called.

The first time I load a Ruby file, I get this message:

LSP :: The following servers support current file but do not have automatic installation: ruby-ls sorbet-ls typeprof-ls ruby-syntax-tree-ls steep-ls

and *lsp-log* has:

Command "solargraph stdio" is not present on the path.
Command "srb typecheck --lsp --disable-watchman" is not present on the path.
Command "typeprof --lsp --stdio" is not present on the path.
Command "stree lsp" is not present on the path.
Command "steep langserver --log-level warn" is not present on the path.


I'm lost and clueless on how lsp-mode figures out to use lsp-docker. I think that is my first stumbling point.

1 Answer 1


For others, this is working for me. I have this in a separate file that I require via my init files. I also have (eval . (lsp t)) in my .dir-locals.el in the project's root.

(require 'lsp-docker)

;; In the lsp-mode directory (where lsp-mode.el lives) is a
;; subdirectory called "clients".  In there is a list of "clients".  I
;; can't figure these terms out BUT the list below is a list of these
;; "clients" that you want to be enabled inside the client / server /
;; THING that you are defining / creating.  In my case, as far as I
;; know, I want just the Solargraph "client".
;; Actually this list is just a list of packages to `require' at the
;; time the THING is registered -- so... it is much ado about nothing?
(setq lsp-docker-client-packages

;; From reading, I guess they call the external server the "server"
;; and the piece either inside or outside of Emacs talking to the
;; server, the "client".  But it gets very confusing (keep reading).
;; Emacs has structures which are defined via `cl-defstruct'.
;; `lsp-clients' is a hash of `lsp--client' structures which has a
;; "slot" `server-id' whose comment is: "Unique identifier for
;; representing the client object.".
;; As mentioned `lsp-clients' is a hash (key value pairs) with the
;; keys being the `server-id' (which is also within the structure).
;; With all that in mind, then:
;; :server-id -- needs to be an existing entry in lsp-clients.  You
;;     can see the list and their priorities by executing:
;;         (maphash
;;          (lambda (key value)
;;            (insert (format "%S  %d\n"
;;                            key
;;                            (lsp--client-priority value))))
;;          lsp-clients)
;;     in the *scratch*  buffer.
;; :docker-server-id -- The name or id of the new "client object"
;;     a.k.a. the `server-id'.  The existing entry is found via the
;;     `server-id', updated, and entered as a new client using the
;;     docker-server-id.
;; :server-command -- This string is munged via
;;     `lsp-docker-launch-new-container' into a list of strings which
;;     is used to start the language server inside the Docker
;;     image/container.  Basically it will turn into:
;;         docker run --name TBD1 --rm -i TBD2 TBD3 `server-command'
;;     TBD1 is `docker-container-name'; TBD2 are `path-mappings' that
;;     have been transformed into a list of "-v" options.  TBD3 is
;;     `docker-image-id'
;; `docker-container-name' and `docker-image-id' will be specified below.
(setq lsp-docker-client-configs
      '((:server-id ruby-ls :docker-server-id rubyls-docker :server-command "/root/bin/solargraph stdio")))

 :path-mappings '(("/Users/pedz/Source/hatred" . "/hatred"))
 :docker-image-id "pedzsan/hatred:1.0"
 :docker-container-name "docker-ruby-lsp"
 :priority 10
 :client-packages lsp-docker-client-packages
 :client-configs lsp-docker-client-configs)

(provide 'lsp-docker-start)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.