feat(build): embed static assets into Go binary
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
Embed frontend build output directly into Go binary using //go:embed. This removes runtime dependency on ../frontend/public/ path and simplifies Docker builds by serving assets from embedded filesystem. - Add backend/web/embed.go with embed.FS directive - Update server to serve from embedded static assets - Update Makefile to copy frontend build to web/static/ - Update Dockerfile for simplified multi-stage build - Update frontend package.json output paths - Remove custom 'oc' command from flake.nix dev shell
This commit is contained in:
50
Dockerfile
50
Dockerfile
@@ -1,70 +1,30 @@
|
||||
# Multi-stage build for Aethera
|
||||
# Stage 1: Build frontend assets
|
||||
# Step 1: Build Frontend
|
||||
FROM oven/bun:1 AS frontend-builder
|
||||
|
||||
WORKDIR /app/frontend
|
||||
|
||||
# Copy frontend package files
|
||||
COPY frontend/package.json frontend/bun.lock ./
|
||||
|
||||
# Install dependencies
|
||||
RUN bun install --frozen-lockfile
|
||||
|
||||
# Copy frontend source code
|
||||
COPY frontend/ ./
|
||||
|
||||
# Build frontend assets
|
||||
RUN bun run build
|
||||
|
||||
# Stage 2: Build Go binary
|
||||
# Stage 2: Build Backend
|
||||
FROM golang:1.25-alpine AS backend-builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache git
|
||||
|
||||
# Copy go mod files
|
||||
COPY backend/go.mod backend/go.sum ./
|
||||
|
||||
# Download Go dependencies
|
||||
RUN go mod download
|
||||
|
||||
# Copy backend source code
|
||||
COPY backend/ ./
|
||||
COPY --from=frontend-builder /app/frontend/public/ ./web/static/
|
||||
RUN go build -ldflags="-w -s" -o aethera ./cmd
|
||||
|
||||
# Copy frontend assets from previous stage
|
||||
COPY --from=frontend-builder /app/frontend/public/dist ./public/dist
|
||||
COPY --from=frontend-builder /app/frontend/public/index.html ./public/
|
||||
COPY --from=frontend-builder /app/frontend/public/pages ./public/pages
|
||||
|
||||
# Build the Go binary
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o aethera ./cmd
|
||||
|
||||
# Stage 3: Create minimal runtime image
|
||||
# Stage 3: Minimal Runtime
|
||||
FROM alpine:3.21
|
||||
|
||||
# Install ca-certificates for HTTPS calls
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the binary from the builder stage
|
||||
COPY --from=backend-builder /app/aethera .
|
||||
|
||||
# Copy static assets
|
||||
COPY --from=backend-builder /app/public ./public
|
||||
|
||||
# Create data directory
|
||||
RUN mkdir -p /app/data
|
||||
|
||||
# Expose the default port
|
||||
EXPOSE 8080
|
||||
|
||||
# Set environment variable defaults
|
||||
ENV AETHERA_LISTEN=0.0.0.0
|
||||
ENV AETHERA_PORT=8080
|
||||
ENV AETHERA_DATA_DIR=/app/data
|
||||
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["./aethera"]
|
||||
|
||||
4
Makefile
4
Makefile
@@ -4,6 +4,9 @@ all: frontend backend
|
||||
|
||||
frontend:
|
||||
cd frontend && bun run build
|
||||
mkdir -p backend/web/static
|
||||
cp frontend/public/index.html backend/web/static/ 2>/dev/null || true
|
||||
cp -r frontend/public/pages backend/web/static/ 2>/dev/null || true
|
||||
|
||||
backend:
|
||||
cd backend && go build -o ./dist/aethera ./cmd
|
||||
@@ -11,6 +14,7 @@ backend:
|
||||
clean:
|
||||
rm -rf frontend/public/dist
|
||||
rm -rf backend/dist
|
||||
rm -rf backend/web/static
|
||||
|
||||
dev:
|
||||
cd backend && go run ./cmd --listen 0.0.0.0 &
|
||||
|
||||
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
dist
|
||||
web/static/
|
||||
|
||||
@@ -2,6 +2,7 @@ package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"time"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"reichard.io/aethera/internal/api"
|
||||
"reichard.io/aethera/internal/store"
|
||||
"reichard.io/aethera/web"
|
||||
)
|
||||
|
||||
func StartServer(settingsStore store.Store, dataDir, listenAddress string, listenPort int) {
|
||||
@@ -17,12 +19,13 @@ func StartServer(settingsStore store.Store, dataDir, listenAddress string, liste
|
||||
// Create API Instance - use settingsStore as the unified store for both settings and chat
|
||||
logger := logrus.New()
|
||||
api := api.New(settingsStore, dataDir, logger)
|
||||
feFS := http.FileServer(http.Dir("../frontend/public/"))
|
||||
mux.Handle("GET /", feFS)
|
||||
|
||||
// Serve UI Pages
|
||||
pagesFS := http.FileServer(http.Dir("../frontend/public/pages/"))
|
||||
mux.Handle("GET /pages/", http.StripPrefix("/pages/", pagesFS))
|
||||
// Serve embedded static assets
|
||||
staticFS, err := fs.Sub(web.Assets, "static")
|
||||
if err != nil {
|
||||
logrus.Fatal("Failed to create static filesystem: ", err)
|
||||
}
|
||||
mux.Handle("GET /", http.FileServer(http.FS(staticFS)))
|
||||
|
||||
// Serve Generated Data
|
||||
genFS := http.FileServer(http.Dir(path.Join(dataDir, "generated")))
|
||||
|
||||
6
backend/web/embed.go
Normal file
6
backend/web/embed.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package web
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed static/*
|
||||
var Assets embed.FS
|
||||
13
flake.nix
13
flake.nix
@@ -21,11 +21,6 @@
|
||||
config.allowUnfree = true;
|
||||
}
|
||||
);
|
||||
|
||||
oc = pkgs.writeShellScriptBin "oc" ''
|
||||
PRJ_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
||||
cd "$PRJ_ROOT" && OPENCODE_EXPERIMENTAL_LSP_TOOL=true opencode
|
||||
'';
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
@@ -38,11 +33,11 @@
|
||||
# Frontend
|
||||
bun
|
||||
watchman
|
||||
tailwindcss_4
|
||||
|
||||
# Custom Commands
|
||||
oc
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
export LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "aethera",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "bun build src/main.ts --outdir public/dist --target browser --watch & bunx @tailwindcss/cli -i styles.css -o public/dist/styles.css --watch",
|
||||
"build": "bun build src/main.ts --outdir public/dist --target browser && bunx @tailwindcss/cli -i styles.css -o public/dist/styles.css --minify",
|
||||
"dev": "bun build src/main.ts --outdir public/dist --target browser --watch & bunx tailwindcss -i styles.css -o public/dist/styles.css --watch",
|
||||
"build": "bun build src/main.ts --outdir ../backend/web/static/dist --target browser && bunx tailwindcss -i styles.css -o ../backend/web/static/dist/styles.css --minify",
|
||||
"lint": "eslint ./src/**"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Reference in New Issue
Block a user