How to deploy static templates with GO (GOLANG)

I followed the sample GO application in your docs. I end up with the following error:

panic: html/template: pattern matches no files: `resources/templates/*`

I’m on Windows NOT using Docker. I’ve tried forward and backward slashes and my latest attempt tries filepath.Join.

r.LoadHTMLGlob(filepath.Join(".", "resources", "templates", "*"))

How do these static templates files get uploaded? Do I need to embed them?

The docs say…

We’re using a template as it makes it easier to show what you should do with assets that aren’t the actual application.

…but I can’t find anything that says what to do with the assets to get them uploaded.

They should just get bundled into the Docker image! Our build process will upload everything in the working directory to a remote Docker daemon, then do the build. This means / should work.

It’s possible we broke this with a recent buildpack update. Can you try adding this Dockerfile to the directory to see if this works?

FROM golang:1.16 as builder
WORKDIR /go/src/app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -v -o app
FROM alpine:latest  
COPY --from=builder /go/src/app/app /goapp/app
WORKDIR /goapp
COPY . /throwaway
RUN cp -r /throwaway/resources ./resources || echo "No resources to copy"
RUN rm -rf /throwaway
RUN apk --no-cache add ca-certificates
CMD ["/goapp/app"]

We did break that guide. The buildpack we’re using doesn’t include the .tmpl files in the final build. I reverted it to our previous working guide, sorry about that!

If you change the [build] section in the generated fly.toml to this, it should work:

  builtin = "go"

Then you can run fly deploy to build and deploy it.

I started using the new embedding in GO and that works.

I tried with just builtin = "go" and that didn’t work. I tried adding a file named Dockerfile with your contents and that didn’t work.

2021-05-02T16:16:29Z [info] panic: html/template: pattern matches no files: `./resources/templates/*`
2021-05-02T16:16:29Z [info] goroutine 1 [running]:
2021-05-02T16:16:29Z [info] html/template.Must(...)
2021-05-02T16:16:29Z [info]     /layers/paketo-buildpacks_go-dist/go/src/html/template/template.go:374
2021-05-02T16:16:29Z [info]*Engine).LoadHTMLGlob(0xc000085ba0, 0x55dd8e9c64f0, 0x17)
2021-05-02T16:16:29Z [info]     /workspace/vendor/ +0x385
2021-05-02T16:16:29Z [info] main.main()
2021-05-02T16:16:29Z [info]     /workspace/cmd/newfly/main.go:23 +0x4b

I don’t know if I needed to tell it to use the Dockerfile or if it just would. I don’t use Docker at all.

I still couldn’t make your sample GO application work. Will I still be able to deploy static assets? How does it know what to include and exclude? Does it just bring everything up in any directory of the project? I think I’ll be OK using the GO embed feature introduced in 1.16 but I’d like to have options :slight_smile:

Oh! You’ll need to remove the [build] block entirely to get the Dockerfile to work.

The Dockerfile defines what to include in the build. Buildpacks are like enhanced dockerfiles that are a little more opaque and magical. So what’s happening in that Dockerfile I gave you is:

# this copies the binary from the build step
COPY --from=builder /go/src/app/app /goapp/app

# this adds everything to the image
COPY . /throwaway

# this copies the resources directory if it exists
RUN cp -r /throwaway/resources ./resources || echo "No resources to copy"

# this removes everything else so you're left with binary + resources
RUN rm -rf /throwaway

Dockerfiles are kind of a pain to write and keep lean, but they are reasonably straightforward to read.