build(website): Dockerfile + production start script for Coolify
Make the marketing site deployable standalone from apps/website (the repo has no root package.json, so the build must run in this subdir — set Base Directory to apps/website in Coolify). - Add a multi-stage Dockerfile (pnpm build -> node .output/server/index.mjs, port 3000, NUXT_PUBLIC_SITE_URL default) + .dockerignore. - Add a "start" script for the Nixpacks path (Nuxt SSR has no default start). - Guard the bind-mount-only /shared-packages components dir with existsSync so standalone builds don't warn on the missing path (the site uses no shared component).
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
.nuxt
|
||||||
|
.output
|
||||||
|
.git
|
||||||
|
dist
|
||||||
|
*.log
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Production image for the dezky marketing site (Nuxt 4 SSR).
|
||||||
|
# Build context = this directory (apps/website). In Coolify set the build pack
|
||||||
|
# to "Dockerfile" and Base Directory to apps/website.
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM node:22-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
RUN corepack enable
|
||||||
|
# Install deps first for layer caching (pnpm version comes from packageManager).
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
COPY . .
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
FROM node:22-alpine AS runtime
|
||||||
|
WORKDIR /app
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
|
ENV PORT=3000
|
||||||
|
# Absolute canonical / OG / sitemap URLs. Override in Coolify if the domain
|
||||||
|
# differs (e.g. a staging URL).
|
||||||
|
ENV NUXT_PUBLIC_SITE_URL=https://dezky.eu
|
||||||
|
COPY --from=build /app/.output ./.output
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["node", ".output/server/index.mjs"]
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
// the Docker app stack. Locally it runs behind Traefik at dezky.local /
|
// the Docker app stack. Locally it runs behind Traefik at dezky.local /
|
||||||
// www.dezky.local with the same mkcert TLS as the rest of the platform.
|
// www.dezky.local with the same mkcert TLS as the rest of the platform.
|
||||||
|
|
||||||
|
import { existsSync } from 'node:fs'
|
||||||
|
|
||||||
const siteUrl = process.env.NUXT_PUBLIC_SITE_URL
|
const siteUrl = process.env.NUXT_PUBLIC_SITE_URL
|
||||||
|| (process.env.NODE_ENV === 'production' ? 'https://dezky.eu' : 'http://localhost:3000')
|
|| (process.env.NODE_ENV === 'production' ? 'https://dezky.eu' : 'http://localhost:3000')
|
||||||
|
|
||||||
@@ -25,7 +27,12 @@ export default defineNuxtConfig({
|
|||||||
// CountrySelect.vue is just <CountrySelect>. Mirrors portal/operator.
|
// CountrySelect.vue is just <CountrySelect>. Mirrors portal/operator.
|
||||||
components: [
|
components: [
|
||||||
'~/components',
|
'~/components',
|
||||||
{ path: '/shared-packages/ui/components', pathPrefix: false },
|
// The shared @dezky/ui dir is bind-mounted in the Docker dev stack; include
|
||||||
|
// it only when present so standalone builds (e.g. Coolify) don't warn on
|
||||||
|
// the missing absolute path. The marketing site uses no shared component.
|
||||||
|
...(existsSync('/shared-packages/ui/components')
|
||||||
|
? [{ path: '/shared-packages/ui/components', pathPrefix: false }]
|
||||||
|
: []),
|
||||||
],
|
],
|
||||||
|
|
||||||
app: {
|
app: {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "TMPDIR=/tmp nuxt dev --host 0.0.0.0 --port 3000",
|
"dev": "TMPDIR=/tmp nuxt dev --host 0.0.0.0 --port 3000",
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
|
"start": "node .output/server/index.mjs",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"preview": "nuxt preview",
|
"preview": "nuxt preview",
|
||||||
"typecheck": "nuxt typecheck",
|
"typecheck": "nuxt typecheck",
|
||||||
|
|||||||
Reference in New Issue
Block a user