Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

4.1KB

+++ title = “Containerized development workflow using remote gopls server” date = 2019-11-05T15:30:03+05:30 draft = false categories = [“golang”] type = “post” url = “blog/2019/11/05/containerized-dev-using-remote-gopls” author = “Rohan Verma” +++

If your CGO development toolchain depends on external dependencies such as system libraries, or you want to develop on an older version of go while having a different version on your host, you can use a docker container and mount the source from your host machine and build the project inside the container. This can enable us to have a consistent development environment across various developers and their host systems without having to modify system libraries.

This article is a follow up to my previous article on using containers to develop on archaic projects that require specific system libraries. Last time I discussed how to create a container having all the dependencies and dev tools installed and use them to operate on the host file system. Taking this a step forward, the biggest roadblock that arises with this approach is that our host machine
now loses the ability to run gotools on our source code. That means your editor cannot run any of the tools you depend on to write, lint, or format your go source code.

To overcome this, we can use the experimental remote lsp server feature available in gopls. gopls (pronounced: “go please”) is the official language server for the Go language. With this mode, the gopls running on the host forwards all the commands to the gopls in our container. This way the host system does not need to have any of the dependencies installed and can then use the container gopls server to modify the source in the editor of the host.

Let us look at the Dockerfile for this system.

FROM ubuntu:xenial AS builder
RUN apt-get update
# Install system dependencies that we might need
RUN apt-get install -y gcc g++

# Install Depencies like Go and Swig in our container.
WORKDIR /tmp
# Install Go
RUN wget https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz
RUN tar -C /usr/local -xzf go1.12.9.linux-amd64.tar.gz
# Install Swig
RUN wget http://prdownloads.sourceforge.net/swig/swig-4.0.1.tar.gz
RUN tar -zxvf swig-4.0.1.tar.gz
RUN cd /tmp/swig-4.0.1 && ./configure && make && make install

# Create user
RUN useradd -m -r -u 1000 myuser
RUN groupmod -g 1000 myuser

# Replicate/fake the host system tree
RUN mkdir -p /home/myuser/code/go/myhostdir/myproject
RUN chown -R myuser:myuser /home/myuser/code/go/myhostdir/myproject
USER myuser

WORKDIR /home/myuser/code/go/myhostdir/myproject

RUN GO111MODULE=on go get golang.org/x/tools/gopls@latest
CMD gopls -listen=":7050"

Firstly, we install all the dependencies and then create a user which will have access to the source code.

Then we have to replicate the host path in the container and set that as our work directory. This is a quirk of gopls, if there is a mismatch in the path, the host will communicate the wrong path to the server running in the container and will be unable to find it inside the container.

Finally, we install gopls in the container and then start it in the container with the -listen=":7050" flag.

Now we can expose this port to our host machine.

docker run -d --name "myproject" -u `id -u` -p 7050:7050 \
    -v /home/myuser/code/go/myhostdir/myproject:/home/myuser/code/go/myhostdir/ \
    myproject myproject:latest

Notice, that we also mount the host source in the container with the same path, the reason is explained above.

We must now add the following flag to your editor config along with any other flags we use for the language server to connect to the remote gopls server.

gopls -remote "localhost:7050"

After adding this flag, you will now be able to edit your source with all the added benefits that come with a language server.

Since this is an experimental feature, it might break (a lot). Do let me know in the comments if this was helpful for you.