From 9b15f32087e7a33f88e930d19def8f7e57a2a48d Mon Sep 17 00:00:00 2001 From: Rohan Verma Date: Mon, 25 Nov 2019 01:37:21 +0530 Subject: [PATCH 1/2] blog: Building Go Plugins inside Docker --- ...019-11-24-build-go-plugins-using-docker.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 content/blog/2019/2019-11-24-build-go-plugins-using-docker.md diff --git a/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md b/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md new file mode 100644 index 0000000..c80267d --- /dev/null +++ b/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md @@ -0,0 +1,65 @@ ++++ +title = "Building Go Plugins inside Docker" +date = 2019-11-24T15:30:03+05:30 +draft = false +tags = ["golang", "docker"] +categories = ["tutorials"] +type = "post" +url = "blog/2019/11/15/building-go-plugins-using-docker" +author = "Rohan Verma" ++++ + +Using Go plugins in your projects comes with a lot of caveats. As of writing, +there hasn't been much development on the feature recently. The +[commit history](https://github.com/golang/go/commits/master/src/plugin/plugin.go) +shows us that the last commit happened nearly 2 years ago. On the gopher slack, +the sentiment, more or less, is that this is not a priority anymore. Along with +this, there are multiple issues that come up with maintaining projects that use +it: + +- The go version for both host and plugin should match exactly +- External dependencies should match +- Host and plugin `GOPATH` needs to exactly match while building +- Plugins cannot depend on interfaces or structs of the host + +To learn more you can refer [this issue](https://github.com/golang/go/issues/20481#issuecomment-326832200) detailing some of the problems with +go plugins + +It works well if the projects bundles all the plugins in its own source tree and +both the host and plugins are built together at the same time. But, that limits +the scope of the project. Externally maintained plugins are impossible to +build independent of the host program. + +To solve this, we can use Docker to build both the host program, the bundled plugins, +and the custom plugin together. Then this image can be distributed instead +of distributing the host and loading the plugins separately in production. + +```Dockerfile +FROM golang:1.12-alpine AS builder +RUN apk update && apk add gcc libc-dev make git +WORKDIR /myproject-plugin/ +# Clone and build myproject and myproject-plugin together +# prevent version conflict for go plugins +RUN git clone https://github.com/rhnvrm/myproject.git && \ + mkdir -p myproject/bundled_plugins/myplugin +# Load our custom plugin from disk +COPY ./myplugin.go ./myproject/bundled_plugins/myplugin/myplugin.go +# CGO_ENABLED=1 is required +ENV CGO_ENABLED=1 GOOS=linux +# `make build` builds the host program and bundled plugins +# `go build` our custom plugin +RUN cd myproject && \ + make deps && make build && \ + go build -ldflags="-s -w" -buildmode=plugin -o myplugin.prov \ + bundled_plugins/myplugin/myplugin.go + +FROM alpine:latest AS deploy +RUN apk --no-cache add ca-certificates +WORKDIR /myproject/ +# Copy the assets from the builder image +COPY --from=builder /myproject-plugin/myproject/myproject /myproject-plugin/myproject-plugin/myproject/smtp.prov /myproject-plugin/myproject/bundled1.prov /myproject-plugin/myproject/bundled2.prov /myproject-plugin/myproject/myplugin.prov ./ + +CMD ["./myproject", "--config", "/etc/myproject/config.toml", "--prov", "smtp.prov", "--prov", "bundled1.prov", "--prov", "bundled2.prov", "--prov", "myplugin.prov"] +``` + +This image can then be pushed and used where it needs to be deployed. \ No newline at end of file From df17b348e2c727d4d1839149f201806dda334822 Mon Sep 17 00:00:00 2001 From: Rohan Verma Date: Mon, 25 Nov 2019 02:01:06 +0530 Subject: [PATCH 2/2] fix: update hugo version --- Dockerfile | 2 +- content/blog/2019/2019-11-24-build-go-plugins-using-docker.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0fb1856..2ad2acb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:latest as build -ENV HUGO_VERSION 0.56.0 +ENV HUGO_VERSION 0.59.1 ENV HUGO_BINARY hugo_${HUGO_VERSION}_Linux-64bit.tar.gz # Install Hugo diff --git a/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md b/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md index c80267d..b4b8d7a 100644 --- a/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md +++ b/content/blog/2019/2019-11-24-build-go-plugins-using-docker.md @@ -57,9 +57,9 @@ FROM alpine:latest AS deploy RUN apk --no-cache add ca-certificates WORKDIR /myproject/ # Copy the assets from the builder image -COPY --from=builder /myproject-plugin/myproject/myproject /myproject-plugin/myproject-plugin/myproject/smtp.prov /myproject-plugin/myproject/bundled1.prov /myproject-plugin/myproject/bundled2.prov /myproject-plugin/myproject/myplugin.prov ./ +COPY --from=builder /myproject-plugin/myproject/myproject /myproject-plugin/myproject-plugin/myproject/bundled0.prov /myproject-plugin/myproject/bundled1.prov /myproject-plugin/myproject/bundled2.prov /myproject-plugin/myproject/myplugin.prov ./ -CMD ["./myproject", "--config", "/etc/myproject/config.toml", "--prov", "smtp.prov", "--prov", "bundled1.prov", "--prov", "bundled2.prov", "--prov", "myplugin.prov"] +CMD ["./myproject", "--config", "/etc/myproject/config.toml", "--prov", "bundled0.prov", "--prov", "bundled1.prov", "--prov", "bundled2.prov", "--prov", "myplugin.prov"] ``` This image can then be pushed and used where it needs to be deployed. \ No newline at end of file