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
ENV PORT=8080
EXPOSE 8080
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:

[build]
  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] github.com/gin-gonic/gin.(*Engine).LoadHTMLGlob(0xc000085ba0, 0x55dd8e9c64f0, 0x17)
2021-05-02T16:16:29Z [info]     /workspace/vendor/github.com/gin-gonic/gin/gin.go:209 +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.

Hey Kurt,

Just letting you know that I finally got around to testing out fly.io today and ran into this same issue. It’s quite confusing having your application work locally and then seemingly be missing elements in production with the buildpacks being a little magical.

That said, it makes sense that static assets and the like wouldn’t be bundled into a binary.

I guess I would point out that the Golang documentation explicitly makes reference to having a template (“We’re using a template as it makes it easier to show what you should do with assets that aren’t the actual application.”) and then never actually addresses it.

As a new user, this made me think that either the documentation writer forgot to address the addition of a template or that fly.io would just magically know what to do with it and that doesn’t really leave you with any obvious path since it all looks correct and the sample repo doesn’t have anything magic (or even a fly.toml!)

Anyway, your Dockerfile example did work for me so thanks! It probably makes sense to update the documentation though. Imagine there’s too many permutations of where files live (views, templates, static…) for fly to be able to handle the many locations.

Thanks

These are good comments. Notably, we’re hiring for Golang dev UX / dev advocacy soon. We’d like for fly launch to just magically work with almost every go app.

We’ll see if we can get the docs cleaned up as well!