Introduction
Go 1.16's //go:embed directive embeds files into the binary at compile time. When building inside Docker, the compiler can only access files within the build context (files sent to the Docker daemon). If embedded files are excluded by .dockerignore or not included in the COPY instruction, the build fails with pattern X: no matching files found.
Symptoms
main.go:10:12: pattern templates/*.html: no matching files foundweb.go:15:5: pattern public/*: no matching files found- Build works locally but fails in Docker
docker buildsucceeds but embedded content is empty or stale.gitignoreaccidentally becomes.dockerignoreexcluding needed files
[builder 5/6] RUN go build -o /app/server ./cmd/server:
#0 0.312 cmd/server/main.go:14:12: pattern dist/*: no matching files found
------
> [builder 5/6] RUN go build -o /app/server ./cmd/server:
------Common Causes
.dockerignoreexcludes the directories referenced by//go:embed- Frontend build output (dist/, build/) not generated before
go build - COPY instruction does not include embedded file directories
- Build context is a subdirectory, not the project root
- Symlinked files not followed by Docker build context
Step-by-Step Fix
- 1.Include embedded files in Docker build context:
- 2.```dockerfile
- 3.# WRONG - only copies Go source, not embedded files
- 4.FROM golang:1.22 AS builder
- 5.WORKDIR /app
- 6.COPY go.mod go.sum ./
- 7.RUN go mod download
- 8.COPY cmd/ cmd/
- 9.COPY main.go .
- 10.RUN go build -o server ./cmd/server # FAILS: embed files missing
# CORRECT - copy everything needed FROM golang:1.22 AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . # Includes templates/, public/, etc. RUN go build -o server ./cmd/server ```
- 1.Multi-stage build with frontend asset generation:
- 2.```dockerfile
- 3.# Stage 1: Build frontend
- 4.FROM node:20 AS frontend
- 5.WORKDIR /frontend
- 6.COPY web/package.json web/package-lock.json ./
- 7.RUN npm ci
- 8.COPY web/ .
- 9.RUN npm run build # Produces dist/ directory
# Stage 2: Build Go binary with embedded assets FROM golang:1.22 AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . COPY --from=frontend /frontend/dist ./cmd/server/dist RUN go build -o server ./cmd/server
# Stage 3: Runtime FROM debian:bookworm-slim COPY --from=builder /app/server /server CMD ["/server"] ```
- 1.Fix .dockerignore to not exclude embedded files:
- 2.
` - 3.# .dockerignore
- 4.node_modules/
- 5..git/
- 6..github/
- 7.*.md
- 8.Dockerfile
- 9.docker-compose.yml
# Make sure these are NOT excluded: # templates/ # public/ # dist/ # **/*.html # **/*.json ```
- 1.Verify embed files are included:
- 2.```dockerfile
- 3.# Add a debug step before go build
- 4.FROM golang:1.22 AS builder
- 5.WORKDIR /app
- 6.COPY . .
- 7.RUN echo "=== Checking embed files ===" && \
- 8.ls -la templates/ && \
- 9.ls -la public/ && \
- 10.ls -la cmd/server/dist/
- 11.RUN go build -o server ./cmd/server
- 12.
` - 13.Use go:embed with explicit file list:
- 14.```go
- 15.// Instead of glob patterns that may match nothing
- 16.//go:embed templates/index.html templates/error.html
- 17.var templatesFS embed.FS
// Or use individual files instead of globs //go:embed public/style.css public/app.js public/logo.png var publicFS embed.FS ```
Prevention
- Use
COPY . .in Docker builds when relying on//go:embed - Keep
.dockerignoreminimal - only exclude truly unnecessary files - Add a verification step in Dockerfile that lists embed target directories
- In CI, run
go buildbefore Docker build to catch embed issues early - Use
go generateto validate embed patterns: add//go:generate ls templates/ - Consider serving static files from disk in development, embedded in production