-
Notifications
You must be signed in to change notification settings - Fork 111
Expand file tree
/
Copy pathDockerfile
More file actions
62 lines (48 loc) · 2.67 KB
/
Dockerfile
File metadata and controls
62 lines (48 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
### Build stage
FROM node:20-alpine AS build
LABEL maintainer="nodejs-poolController"
LABEL org.opencontainers.image.title="nodejs-poolController"
LABEL org.opencontainers.image.description="Bridge Pentair / compatible pool automation equipment to modern interfaces (REST, WebSockets, MQTT, Influx, Rules)."
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"
LABEL org.opencontainers.image.source="https://github.com/tagyoureit/nodejs-poolController"
# Install build toolchain only for native deps (serialport, etc.)
RUN apk add --no-cache make gcc g++ python3 linux-headers udev tzdata git
WORKDIR /app
# Leverage Docker layer caching: copy only manifests first
COPY package*.json ./
COPY defaultConfig.json config.json
# Install all deps (including dev) for build
RUN npm ci
# Copy source
COPY . .
# Build Typescript
RUN npm run build
# Remove dev dependencies while keeping a clean node_modules with prod deps only
RUN npm prune --production
### Runtime stage
FROM node:20-alpine AS prod
LABEL org.opencontainers.image.title="nodejs-poolController"
LABEL org.opencontainers.image.description="Bridge Pentair / compatible pool automation equipment to modern interfaces (REST, WebSockets, MQTT, Influx, Rules)."
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"
LABEL org.opencontainers.image.source="https://github.com/tagyoureit/nodejs-poolController"
ENV NODE_ENV=production
# Use existing 'node' user from base image; just ensure work directory exists
WORKDIR /app
RUN mkdir -p /app
RUN mkdir -p /app/logs /app/data /app/backups /app/web/bindings/custom \
&& chown -R node:node /app/logs /app/data /app/backups /app/web/bindings /app/web/bindings/custom || true
# Copy only the necessary runtime artifacts from build stage
COPY --chown=node:node --from=build /app/package*.json ./
COPY --chown=node:node --from=build /app/node_modules ./node_modules
COPY --chown=node:node --from=build /app/dist ./dist
COPY --chown=node:node --from=build /app/defaultConfig.json ./defaultConfig.json
COPY --chown=node:node --from=build /app/config.json ./config.json
COPY --chown=node:node --from=build /app/README.md ./README.md
COPY --chown=node:node --from=build /app/LICENSE ./LICENSE
USER node
# Default HTTP / HTTPS (if enabled) ports from defaultConfig (http 4200, https 4201)
EXPOSE 4200 4201
# Basic healthcheck (container considered healthy if process responds to tcp socket open)
HEALTHCHECK --interval=45s --timeout=6s --start-period=40s --retries=4 \
CMD node -e "const n=require('net');const s=n.createConnection({host:'127.0.0.1',port:4200},()=>{s.end();process.exit(0)});s.on('error',()=>process.exit(1));setTimeout(()=>{s.destroy();process.exit(1)},5000);" || exit 1
ENTRYPOINT ["node", "dist/app.js"]