diff --git a/Dockerfile b/Dockerfile index 93fde5a..bd09524 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,11 +8,13 @@ RUN npm ci COPY . . RUN npm run build -FROM nginx:1.27-alpine AS runtime +FROM node:20-alpine AS runtime -COPY nginx.conf /etc/nginx/conf.d/default.conf -COPY --from=build /app/dist /usr/share/nginx/html +WORKDIR /app + +COPY --from=build /app/dist ./dist +COPY server.js ./server.js EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] +CMD ["node", "server.js"] diff --git a/server.js b/server.js new file mode 100644 index 0000000..b26145e --- /dev/null +++ b/server.js @@ -0,0 +1,57 @@ +import { createReadStream, existsSync, statSync } from 'node:fs' +import { extname, join, normalize } from 'node:path' +import http from 'node:http' + +const root = join(process.cwd(), 'dist') +const port = Number(process.env.PORT || 80) + +const contentTypes = { + '.css': 'text/css; charset=utf-8', + '.html': 'text/html; charset=utf-8', + '.js': 'application/javascript; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.svg': 'image/svg+xml', + '.webp': 'image/webp', + '.ico': 'image/x-icon', + '.txt': 'text/plain; charset=utf-8', + '.woff': 'font/woff', + '.woff2': 'font/woff2', +} + +const sendFile = (res, filePath) => { + const ext = extname(filePath).toLowerCase() + const contentType = contentTypes[ext] || 'application/octet-stream' + + res.writeHead(200, { + 'Content-Type': contentType, + 'Cache-Control': ext === '.html' ? 'no-cache' : 'public, max-age=31536000, immutable', + }) + + createReadStream(filePath).pipe(res) +} + +http + .createServer((req, res) => { + const requestPath = normalize(decodeURIComponent(req.url || '/')).replace(/^(\.\.[/\\])+/, '') + const targetPath = join(root, requestPath === '/' ? 'index.html' : requestPath) + + if (existsSync(targetPath) && statSync(targetPath).isFile()) { + sendFile(res, targetPath) + return + } + + const indexPath = join(root, 'index.html') + if (existsSync(indexPath)) { + sendFile(res, indexPath) + return + } + + res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }) + res.end('Not Found') + }) + .listen(port, '0.0.0.0', () => { + console.log(`Static server listening on ${port}`) + })