diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b2ccc93 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +node_modules +dist +.env +.env.* +*.log +.git diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5b88d6f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM node:20-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY tsconfig.json ./ +COPY src ./src +RUN npm run build + +FROM node:20-alpine +WORKDIR /app +ENV NODE_ENV=production +COPY package*.json ./ +RUN npm ci --omit=dev +COPY --from=build /app/dist ./dist + +EXPOSE 5001 + +HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=5 \ + CMD node -e "require('http').get('http://localhost:'+(process.env.PORT||5001)+'/api/health', r => process.exit(r.statusCode===200?0:1)).on('error', () => process.exit(1))" + +CMD ["node", "dist/index.js"] diff --git a/src/index.ts b/src/index.ts index 0778093..414af0d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,11 @@ app.use(cors()); app.use(express.json({ limit: '50mb' })); app.use(express.urlencoded({ extended: true, limit: '50mb' })); +// Root-level healthcheck (some platforms/proxies probe this instead of /api/health) +app.get('/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString() }); +}); + // API Root Routes app.use('/api', routes);