Writing Dockerfiles is a pain in the ass.
All you want to do is publish your SPA or PWA dist files in a docker container and maybe even push it to a private registry.
Instead of having to write a Dockerfile, pull some base OS, increase the size of the container image, add potential attack surfaces / vulnerabilities coming from those base OS images, you can wrap and embed it in a Go binary.
Install ko
Create a ko-build.sh in the project root
|
#!/bin/bash ko login registry.domain.tld -u myuser -p mypassword KO_DOCKER_REPO=registry.domain.tld/user/my-frontend ko build --platform=all |
|
go mod init git.domain.tld/user/repo touch main.go |
and edit main.go and insert the following
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
package main import ( "embed" "io/fs" "log" "net/http" "strings" ) //go:embed dist var pwa embed.FS //go:embed dist/index.html var index embed.FS var indexFile []byte func init() { var e error indexFile, e = index.ReadFile("dist/index.html") if e != nil { log.Fatal(e.Error()) } } func main() { root, e := fs.Sub(pwa, "dist") if e != nil { log.Fatal(e.Error()) } log.Fatal(http.ListenAndServe(":8080", Handler(root))) } func Handler(root fs.FS) http.Handler { handler := http.FileServer(http.FS(root)) return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { _path := req.URL.Path // static files if strings.Contains(_path, ".") || _path == "/" { handler.ServeHTTP(w, req) return } w.Write(indexFile) }) } |
assuming your bundler, e.g. vite, places dist files in your project root’s dist
dir (vite default),
|
dist ├── assets │ ├── index-D-1oofZ3.css │ └── index-DMGf-fk6.js ├── index.html └── vite.svg |
If your dist files are in dist/pwa
and your index file is at dist/pwa/index.html
edit the lines accordingly.
This is effectively what would be in nginx:
|
location / { try_files $uri $uri/ /index.html; } |
Your container exposes port 8080
Build and publish
Since you only need to write this once, you can copy the main.go to every project that requires it and adjust the ko-build.sh script.
Yes, this survives CTRL+F5 reloads. It routes everything through index.html unless it’s a static file that exists on the filesystem.
#spa #pwa #go #ko #docker #registry #build #publish