Skip to content

Commit 46e08b8

Browse files
authored
feat: use embed to build single binary (#2)
1 parent ca50dc8 commit 46e08b8

File tree

13 files changed

+125
-33
lines changed

13 files changed

+125
-33
lines changed

.air.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tmp_dir = "tmp"
77
bin = "./tmp/main"
88
cmd = "go build -o ./tmp/main ."
99
delay = 1000
10-
exclude_dir = ["assets", "tmp", "vendor", "testdata", "frontend/node_modules"]
10+
exclude_dir = ["assets", "tmp", "vendor", "testdata", "frontend/node_modules", "docs/node_modules", "node_modules", "dist", "frontend/build"]
1111
exclude_file = []
1212
exclude_regex = ["_test.go"]
1313
exclude_unchanged = false
@@ -21,7 +21,9 @@ tmp_dir = "tmp"
2121
poll = false
2222
poll_interval = 0
2323
post_cmd = []
24-
pre_cmd = []
24+
pre_cmd = [
25+
"npm run build --workspace=frontend",
26+
]
2527
rerun = false
2628
rerun_delay = 500
2729
send_interrupt = false

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
frontend/build/

.github/workflows/next.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ jobs:
2020
uses: actions/checkout@v4
2121
with:
2222
fetch-depth: 0
23+
- uses: actions/setup-node@v4
24+
with:
25+
node-version: 20
26+
cache: 'npm'
27+
cache-dependency-path: frontend/package-lock.json
2328
- # Add support for more platforms with QEMU (optional)
2429
# https://github.com/docker/setup-qemu-action
2530
name: Set up QEMU

.github/workflows/pr.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ jobs:
1818
uses: actions/checkout@v4
1919
with:
2020
fetch-depth: 0
21+
- uses: actions/setup-node@v4
22+
with:
23+
node-version: 20
24+
cache: 'npm'
25+
cache-dependency-path: frontend/package-lock.json
2126
- # Add support for more platforms with QEMU (optional)
2227
# https://github.com/docker/setup-qemu-action
2328
name: Set up QEMU

.github/workflows/release.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ jobs:
2121
uses: actions/checkout@v4
2222
with:
2323
fetch-depth: 0
24+
- uses: actions/setup-node@v4
25+
with:
26+
node-version: 20
27+
cache: 'npm'
28+
cache-dependency-path: frontend/package-lock.json
2429
- # Add support for more platforms with QEMU (optional)
2530
# https://github.com/docker/setup-qemu-action
2631
name: Set up QEMU

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ secret/
3535
node_modules
3636

3737
dist/
38+
frontend/build/

.goreleaser.yaml

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ before:
1616
- go mod tidy
1717
# you may remove this if you don't need go generate
1818
- go generate ./...
19+
- npm ci --workspace=frontend
20+
- npm run build --workspace=frontend
1921

2022
builds:
2123
- env:
@@ -42,13 +44,32 @@ archives:
4244

4345
dockers:
4446
- use: buildx
47+
dockerfile: goreleaser.Dockerfile
4548
image_templates:
46-
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}"
47-
- "ghcr.io/dirathea/{{ .ProjectName }}:v{{ .Major }}"
48-
- "ghcr.io/dirathea/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}"
49-
- "ghcr.io/dirathea/{{ .ProjectName }}:latest"
49+
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}-arm64"
50+
- "ghcr.io/dirathea/{{ .ProjectName }}:v{{ .Major }}-arm64"
51+
- "ghcr.io/dirathea/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64"
52+
goarch: arm64
5053
build_flag_templates:
51-
- "--platform=linux/amd64,linux/arm64"
54+
- "--platform=linux/arm64"
55+
- use: buildx
56+
dockerfile: goreleaser.Dockerfile
57+
image_templates:
58+
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}-amd64"
59+
- "ghcr.io/dirathea/{{ .ProjectName }}:v{{ .Major }}-amd64"
60+
- "ghcr.io/dirathea/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64"
61+
build_flag_templates:
62+
- "--platform=linux/amd64"
63+
64+
docker_manifests:
65+
- name_template: "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}"
66+
image_templates:
67+
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}-amd64"
68+
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}-arm64"
69+
- name_template: "ghcr.io/dirathea/{{ .ProjectName }}:latest"
70+
image_templates:
71+
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}-amd64"
72+
- "ghcr.io/dirathea/{{ .ProjectName }}:{{ .Tag }}-arm64"
5273

5374
changelog:
5475
sort: asc

Dockerfile

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,45 @@
1-
# Stage 1: Build the Go server
2-
FROM golang:1.23-alpine AS server-builder
1+
# Stage 1: Build the Remix frontend
2+
FROM node:20-alpine AS frontend-builder
33

44
# Set the Current Working Directory inside the container
55
WORKDIR /app
66

7-
# Copy go mod and sum files
8-
COPY go.mod go.sum ./
7+
# Copy package.json and package-lock.json
8+
COPY frontend/package.json frontend/package-lock.json ./
99

10-
# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
11-
RUN go mod download
10+
# Install dependencies
11+
RUN npm install
1212

1313
# Copy the source from the current directory to the Working Directory inside the container
14-
COPY ./ .
14+
COPY frontend/ .
1515

16-
# Build the Go app
17-
RUN go build -o server .
16+
# Build the Remix app
17+
RUN npm run build
1818

19-
# Stage 2: Build the Remix frontend
20-
FROM node:20-alpine AS frontend-builder
19+
# Stage 2: Build the Go server
20+
FROM golang:1.23-alpine AS server-builder
2121

2222
# Set the Current Working Directory inside the container
2323
WORKDIR /app
2424

25-
# Copy package.json and package-lock.json
26-
COPY frontend/package.json frontend/package-lock.json ./
25+
# Copy go mod and sum files
26+
COPY go.mod go.sum ./
2727

28-
# Install dependencies
29-
RUN npm install
28+
# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
29+
RUN go mod download
3030

3131
# Copy the source from the current directory to the Working Directory inside the container
32-
COPY frontend/ .
32+
COPY ./ .
3333

34-
# Build the Remix app
35-
RUN npm run build
34+
# Copy the Remix build output from the frontend-builder stage
35+
COPY --from=frontend-builder /app/build ./frontend/build
36+
37+
# Build the Go app
38+
# Ensure the Remix build output exists
39+
RUN if [ ! -f frontend/build/client/index.html ]; then echo "Remix build output not found!"; exit 1; fi
40+
41+
# Build the Go app
42+
RUN go build -o server .
3643

3744
# Stage 3: Create the final image
3845
FROM alpine:latest
@@ -43,9 +50,6 @@ WORKDIR /app
4350
# Copy the Go server binary from the server-builder stage
4451
COPY --from=server-builder /app/server .
4552

46-
# Copy the Remix build output from the frontend-builder stage
47-
COPY --from=frontend-builder /app/build ./frontend/build
48-
4953
# Expose port 8080 to the outside world
5054
EXPOSE 8080
5155

frontend/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
"vite": "^5.1.0",
3939
"vite-tsconfig-paths": "^4.2.1"
4040
},
41+
"optionalDependencies": {
42+
"@rollup/rollup-linux-x64-gnu": "4.22.4"
43+
},
4144
"engines": {
4245
"node": ">=20.0.0"
4346
}

goreleaser.Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Goreleaser Dockerfile
2+
FROM alpine:latest
3+
4+
# Set the Current Working Directory inside the container
5+
WORKDIR /app
6+
7+
COPY pasolo pasolo
8+
9+
# Expose port 8080 to the outside world
10+
EXPOSE 8080
11+
12+
# Command to run the executable
13+
CMD ["./pasolo"]

main.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"bytes"
5+
"embed"
56
"encoding/json"
67
"fmt"
78
"io"
@@ -11,17 +12,19 @@ import (
1112

1213
"github.com/dirathea/pasolo/pkg/config"
1314
"github.com/dirathea/pasolo/pkg/cookie"
15+
"github.com/dirathea/pasolo/pkg/frontend"
1416
"github.com/dirathea/pasolo/pkg/register"
1517
"github.com/dirathea/pasolo/pkg/session"
1618
"github.com/dirathea/pasolo/pkg/user"
1719
"github.com/go-webauthn/webauthn/webauthn"
1820
"github.com/labstack/echo/v4"
19-
"github.com/labstack/echo/v4/middleware"
2021
)
2122

2223
var (
2324
webAuthn *webauthn.WebAuthn
2425
err error
26+
//go:embed all:frontend/build/client
27+
frontendFs embed.FS
2528
)
2629

2730
func main() {
@@ -211,10 +214,7 @@ func main() {
211214
return c.JSON(200, "OK")
212215
})
213216

214-
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
215-
Root: "frontend/build/client",
216-
HTML5: true,
217-
}))
217+
frontend.Setup(e, frontendFs)
218218

219219
address := fmt.Sprintf(":%s", config.Server.Port)
220220

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/frontend/handler.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package frontend
2+
3+
import (
4+
"embed"
5+
"net/http"
6+
7+
"github.com/labstack/echo/v4"
8+
"github.com/labstack/echo/v4/middleware"
9+
)
10+
11+
func Setup(e *echo.Echo, fsEmbed embed.FS) {
12+
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
13+
Root: "frontend/build/client",
14+
Filesystem: http.FS(fsEmbed),
15+
HTML5: true,
16+
}))
17+
}

0 commit comments

Comments
 (0)