diff --git a/.forgejo/workflows/build-and-dockerise.yml b/.forgejo/workflows/build-and-dockerise.yml index 3a5c6b4..223f232 100644 --- a/.forgejo/workflows/build-and-dockerise.yml +++ b/.forgejo/workflows/build-and-dockerise.yml @@ -57,11 +57,11 @@ jobs: org.opencontainers.image.revision=${{ github.sha }} org.opencontainers.image.ref.name=${{ github.ref_name }} - - name: Build and push Docker image + - name: Build and push minimal Docker image uses: docker/build-push-action@v5 with: context: . - file: ./Dockerfile + file: ./Dockerfile # Uses the Alpine-based minimal container push: true tags: ${{ steps.meta.outputs.tags }} # Use tags from metadata step labels: ${{ steps.meta.outputs.labels }} # Use labels from metadata step diff --git a/Dockerfile b/Dockerfile index 9d9bb8e..d2c7577 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,26 +12,32 @@ RUN bun install --frozen-lockfile # Copy source code and configuration files COPY . . -# Build the application with Vite +# Build the frontend with Vite and compile the server to executable RUN bun run build -# Production stage -FROM oven/bun:latest +# Minimal production stage using Alpine +FROM alpine:latest + +# Install CA certificates for HTTPS requests and glibc compatibility +RUN apk --no-cache add ca-certificates tzdata gcompat WORKDIR /app -# Copy package files -COPY package.json bun.lock* ./ +# Copy the compiled executable from the build stage (Linux build will not have .exe extension) +COPY --from=builder /app/dist/server /app/server -# Install only production dependencies -RUN bun install --frozen-lockfile --production +# Copy the built frontend assets (but ensure we don't overwrite the server executable) +COPY --from=builder /app/dist/*.html /app/dist/ +COPY --from=builder /app/dist/assets /app/dist/assets -# Copy built application and server from build stage -COPY --from=builder /app/dist ./dist -COPY src/server.ts ./src/server.ts +# Make the server executable +RUN chmod +x /app/server # Expose the port EXPOSE 3000 -# Start the application -CMD ["bun", "run", "prod"] \ No newline at end of file +# Set environment to production +ENV NODE_ENV=production + +# Start the application using the compiled executable +CMD ["/app/server"] \ No newline at end of file diff --git a/package.json b/package.json index 12ea908..1b4bf8e 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,11 @@ "type": "module", "scripts": { "start": "bun src/server.ts", - "dev": "concurrently \"bun run --hot src/server.ts\" \"vite build --watch\"", - "build": "vite build", + "dev": "concurrently \"bun run --hot src/server.ts\" \"vite\"", + "build": "vite build && bun build src/server.ts --compile --outfile dist/server", + "build:frontend": "vite build", + "build:server": "bun build src/server.ts --compile --outfile dist/server", + "test:executable": "npm run build && NODE_ENV=production ./dist/server.exe", "preview": "vite preview", "prod": "NODE_ENV=production bun src/server.ts" }, diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index 5b23a1c..0000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -onlyBuiltDependencies: - - '@tailwindcss/oxide' - - esbuild diff --git a/src/server.ts b/src/server.ts index eb186c0..7ef52b5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,5 +1,6 @@ import { Elysia, t } from 'elysia'; import { staticPlugin } from '@elysiajs/static'; +import path from 'path'; // Song data interface interface LastSong { @@ -87,9 +88,16 @@ setInterval(checkAndUpdateSong, 1000); // Initial fetch checkAndUpdateSong(); +// Determine static assets path - adjust for compiled executable +const assetsPath = process.env.NODE_ENV === 'production' + ? path.join(path.dirname(process.execPath || __dirname), 'dist') + : 'dist'; + +console.log('Serving static assets from:', assetsPath); + const app = new Elysia() .use(staticPlugin({ - assets: 'dist', + assets: assetsPath, prefix: '' })) .ws('/music', { diff --git a/vite.config.js b/vite.config.js index 05ac03a..6959824 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,4 +1,4 @@ -import { defineConfig } from 'vite' +import { defineConfig } from 'vite' import tailwindcss from '@tailwindcss/vite' import Icons from 'unplugin-icons/vite' @@ -13,4 +13,16 @@ export default defineConfig({ }, }) ], + server: { + port: 5173, + host: 'localhost', + proxy: { + // Proxy the backend WebSocket/API on /music to the Bun server + '/music': { + target: 'http://localhost:3000', + changeOrigin: true, + ws: true, + }, + }, + }, }) \ No newline at end of file