If you're using Sveltekit with Docker — or with Caprover, for that matter — chances are you need a Dockerfile. Below you can find two versions: one for adapter-node, and the other for adapter-static.
If you're using adapter-node
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/build build/
COPY --from=builder /app/node_modules node_modules/
COPY package.json ./
EXPOSE 3000
ENV NODE_ENV=production
CMD [ "node", "build" ]If you're using adapter-static
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production
FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.confwith adapter-static you need to have the nginx conf
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Serve the specific .html files for routes like /about
location / {
try_files $uri $uri.html $uri/ =404;
}
# Static file handling with caching headers
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|html)$ {
expires 6M;
access_log off;
add_header Cache-Control "public";
}
# Disable caching for index.html to prevent outdated builds
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires -1;
}
# Optional: health check endpoint
location /health {
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# Custom error handling
error_page 404 /404.html;
}Also in svelte.config.js, check the fallback
import adapter from '@sveltejs/adapter-static';
import sveltePreprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter({
fallback: '404.html' // this filename can be whatever you want
})
}
};
export default config;