dockergokubernetesdockerfilego-html-template

Dockerfile directory structure for Go Webapp


I'm developing a test hello app in Go, which will have access to a Postgres DB. This will use a statefulset to release in kubernetes and has one pod with two container images (one for pgsql & one for goapp).

├── hello-app
|   ├── templates
|       ├── file1.gohtml
|       ├── file2.gohtml
|       └── file3.gohtml
|   ├── Dockerfile
|   └── hello-app.go
├── psql
|   ├── Dockerfile
|   ├── createUser.sh
|   └── createDB.sql
├── yaml
|   └── statefulset.yaml

I am stuck getting the Dockerfile and Go app to tie up. In my first bit of Go code I use the 'template.Must' function to reference the 'templates' directory. Obviously when I run this up as a container the directory structure is different.

I've not quite worked out how to do this in the Dockerfile yet and was looking for some guidance.

/app/hello-app.go

package main

import (

        "database/sql"
        "fmt"
        "os"
        _ "github.com/lib/pq"
        "html/template"
        "net/http"
        "strconv"
)

var db *sql.DB
var tpl *template.Template

func init() {
        host := os.Getenv("VARIABLE")
        var err error
        db, err = sql.Open("postgres", "postgres://user:password@"+host+"/dbname?sslmode=disable")
        if err != nil {
                panic(err)
        }

        if err = db.Ping(); err != nil {
                panic(err)
        }
        fmt.Println("You connected to your database.")

        tpl = template.Must(template.ParseGlob("templates/*.gohtml"))

/app/Dockerfile

FROM golang:1.8-alpine
RUN apk add --update go git
RUN go get github.com/lib/pq/...
ADD . /go/src/hello-app
RUN go install hello-app
Add templates templates/
ENV USER=username \
    PASSWORD=password \
    DB=dbname \
    HOST=hostname \
    PORT=5432

FROM alpine:latest
COPY --from=0 /go/bin/hello-app/ .
ENV PORT 4040
CMD ["./hello-app"]

When I run this up as is in kubernetes (GCP) I get the following log entry on the hello-app container.

panic: html/template: pattern matches no files: templates/*.gohtml goroutine 1 [running]: html/template.Must


Solution

  • In the second stage of your Dockerfile, you are only copying your Go binary from the previous stage. You must also copy your templates directory to the second stage as well so the Go binary can reference your HTML templates:

    FROM golang:1.8-alpine
    RUN apk add --update go git
    RUN go get github.com/lib/pq/...
    ADD . /go/src/hello-app
    RUN go install hello-app
    ENV USER=username \
        PASSWORD=password \
        DB=dbname \
        HOST=hostname \
        PORT=5432
    
    FROM alpine:latest
    COPY --from=0 /go/bin/hello-app/ .
    COPY --from=0 /go/src/hello-app/templates ./templates
    ENV PORT 4040
    CMD ["./hello-app"]
    

    I'm not sure if this is common practice but when I'm confused about what contents are in what folder within the build process, I simply ls the directory in question to get a better understanding of what might be happening during the build process:

    RUN ls
    

    Obviously you can remove these lines once you've finalized your Dockerfile.