Introduction
Go's embed directive (//go:embed) includes files in the binary at compile time. When building inside Docker, the embedded files must exist in the build context at the correct relative path. If the Dockerfile's COPY order is wrong or the build context excludes the files, the build fails with "pattern X: no matching files found".
This is a common CI/CD issue when transitioning from local development to containerized builds.
Symptoms
- go build fails with "go:embed: pattern static/*: no matching files found"
- Build works locally but fails in Docker or CI pipeline
- Error references embedded files that exist in the source tree
Common Causes
- Dockerfile COPY command runs after go build, so embedded files aren't in the image yet
- .dockerignore excludes the embedded file patterns
- Working directory in Dockerfile doesn't match the embedded file paths
Step-by-Step Fix
- 1.Copy embedded files before running go build: Ensure embedded files are in the build context.
- 2.```dockerfile
- 3.FROM golang:1.22 AS builder
WORKDIR /app
# Copy go module files first COPY go.mod go.sum ./ RUN go mod download
# Copy embedded files BEFORE building COPY static/ static/ COPY templates/ templates/ COPY *.sql migrations/
# Copy the rest COPY . .
# Now build - embedded files are available RUN go build -o myapp ./cmd/myapp
FROM alpine:latest COPY --from=builder /app/myapp /myapp CMD ["/myapp"] ```
- 1.Fix .dockerignore to include embedded files: Ensure .dockerignore doesn't exclude embed patterns.
- 2.
` - 3.# .dockerignore - BAD (excludes embedded files):
- 4.static/
- 5.templates/
# .dockerignore - GOOD (keeps embedded files): .git/ .docker/ .env *.md tests/
# Or be explicit: !static/ !templates/ !migrations/ ```
- 1.Use multi-stage build with explicit paths: Separate build and runtime stages clearly.
- 2.```dockerfile
- 3.FROM golang:1.22 AS builder
- 4.WORKDIR /src
- 5.COPY go.mod go.sum ./
- 6.RUN go mod download
- 7.COPY . .
- 8.RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/myapp ./cmd/myapp
FROM alpine:3.19 RUN apk add --no-cache ca-certificates WORKDIR /app # The embedded files are already IN the binary COPY --from=builder /app/myapp . EXPOSE 8080 CMD ["./myapp"] ```
Prevention
- Always COPY embedded file directories before running go build in Dockerfile
- Review .dockerignore to ensure it doesn't exclude embed patterns
- Test Docker builds locally before pushing to CI
- Use go:embed with specific file patterns rather than broad globs