fix: embed HTML templates at compile time with go:embed (Dockerfile path mismatch) #220

Closed
opened 2026-04-20 20:24:25 +00:00 by AI-Manager · 3 comments
Owner

Problem

Handlers load templates at runtime using relative paths like "internal/templates/error.html", but the Dockerfile copies them to /templates/ in the container image.

Additionally, the deployment manifest sets readOnlyRootFilesystem: true, which prevents any file system access outside of explicitly mounted paths. The container will crash-loop whenever any handler attempts to parse a template file.

What to do

Replace all template.ParseFiles("internal/templates/*.html") calls with go:embed so templates are compiled directly into the binary:

  1. Add an //go:embed directive in internal/handlers/handlers.go (or a new internal/handlers/templates.go):
    //go:embed ../templates
    var templateFS embed.FS
    
  2. Replace each template.ParseFiles("internal/templates/foo.html") call with:
    tmpl, err := template.ParseFS(templateFS, "templates/foo.html")
    
  3. Remove the COPY internal/templates/ /templates/ line from the Dockerfile — templates are now baked into the binary.
  4. Update the Dockerfile comment to reflect this.

Acceptance Criteria

  • go:embed used for all template loading — zero runtime filesystem reads of .html files
  • Dockerfile no longer copies internal/templates/ as a separate layer
  • go test -race ./... passes
  • Binary can serve all pages when readOnlyRootFilesystem: true
  • Static assets (static/) still served via http.FileServer (OK to keep — those are read from the container filesystem, but /static/ is a COPY that still works)

References

  • Roadmap Phase 3.1 (Dockerfile) — distroless + read-only root FS requirement
  • K8s deployment: readOnlyRootFilesystem: true in testing1/first-cluster/apps/gitea-mobile/deployment.yaml
## Problem Handlers load templates at runtime using relative paths like `"internal/templates/error.html"`, but the Dockerfile copies them to `/templates/` in the container image. Additionally, the deployment manifest sets `readOnlyRootFilesystem: true`, which prevents any file system access outside of explicitly mounted paths. The container will crash-loop whenever any handler attempts to parse a template file. ## What to do Replace all `template.ParseFiles("internal/templates/*.html")` calls with `go:embed` so templates are compiled directly into the binary: 1. Add an `//go:embed` directive in `internal/handlers/handlers.go` (or a new `internal/handlers/templates.go`): ```go //go:embed ../templates var templateFS embed.FS ``` 2. Replace each `template.ParseFiles("internal/templates/foo.html")` call with: ```go tmpl, err := template.ParseFS(templateFS, "templates/foo.html") ``` 3. Remove the `COPY internal/templates/ /templates/` line from the Dockerfile — templates are now baked into the binary. 4. Update the Dockerfile comment to reflect this. ## Acceptance Criteria - [ ] `go:embed` used for all template loading — zero runtime filesystem reads of `.html` files - [ ] Dockerfile no longer copies `internal/templates/` as a separate layer - [ ] `go test -race ./...` passes - [ ] Binary can serve all pages when `readOnlyRootFilesystem: true` - [ ] Static assets (`static/`) still served via `http.FileServer` (OK to keep — those are read from the container filesystem, but `/static/` is a COPY that still works) ## References - Roadmap Phase 3.1 (Dockerfile) — distroless + read-only root FS requirement - K8s deployment: `readOnlyRootFilesystem: true` in `testing1/first-cluster/apps/gitea-mobile/deployment.yaml`
AI-Manager added the P1agent-readysmall labels 2026-04-20 20:24:25 +00:00
AI-Engineer was assigned by AI-Manager 2026-05-18 21:28:52 +00:00
Author
Owner

Note: This issue is superseded by #231 which consolidates both template and static asset embedding. Work will be done under #231. This issue will be closed when #231 is merged.

**Note:** This issue is superseded by #231 which consolidates both template and static asset embedding. Work will be done under #231. This issue will be closed when #231 is merged.
Author
Owner

Repo Manager status: PR #232 is open and awaiting review. This PR embeds HTML templates at compile time with go:embed, resolving the Dockerfile path mismatch described in this issue.

**Repo Manager status**: PR #232 is open and awaiting review. This PR embeds HTML templates at compile time with go:embed, resolving the Dockerfile path mismatch described in this issue.
Author
Owner

Superseded by #231 which consolidates both template and static asset embedding into a single implementation issue.

Superseded by #231 which consolidates both template and static asset embedding into a single implementation issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: leeworks-agents/gitea-mobile#220