Files
trip-plan/Dockerfile
T
grabowski 1d86c68665 Fix bind-mount data dir permissions via entrypoint
Docker creates ./data root-owned on the host, but the app runs as the unprivileged node user, causing SQLITE_CANTOPEN on first deploy. New entrypoint starts as root, chowns DATA_DIR, then drops privileges with setpriv. Compose keeps the SQLite database in ./data next to the compose file. Also trims scripts/ and playwright artifacts from the image.
2026-07-18 23:54:50 +07:00

36 lines
1.2 KiB
Docker

# Trip Plan — production image
# node:20-slim (Debian/glibc) so better-sqlite3 prebuilt binaries load correctly.
FROM node:20-slim
ENV NODE_ENV=production \
PORT=3000 \
DATA_DIR=/app/data
WORKDIR /app
# Install production dependencies first for better layer caching.
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
# Application code.
COPY src/ ./src/
COPY public/ ./public/
# Data directory for the SQLite file (volume-mounted in compose).
# Owned by the unprivileged `node` user that ships with the base image.
RUN mkdir -p /app/data && chown -R node:node /app
# The entrypoint starts as root only to chown a bind-mounted DATA_DIR
# (Docker creates host dirs root-owned), then drops to `node` via setpriv.
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3000
# Any HTTP response (including 401) from the API means the server is up.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD node -e "fetch('http://localhost:3000/api/auth/me').then(()=>process.exit(0)).catch(()=>process.exit(1))"
CMD ["node", "src/server/index.js"]