# antisocial — reads social posts back to you without the app. # # Both stages sit on the Playwright image so the Node that compiles the code # is the Node that runs it, and so the Chromium build matches the Playwright # package exactly. The image is large because a browser is large; the # alternative, apt Chromium on a slim Node base, saves a few hundred MB and # is where arm64 browser builds usually go wrong. # # Pinned in lockstep with the `playwright` dependency in package.json. ARG PLAYWRIGHT_VERSION=1.62.1 FROM mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble AS build WORKDIR /app # Browsers are already in the base image; downloading them again during # `npm ci` would double the build for nothing. ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 COPY package.json package-lock.json ./ RUN npm ci COPY tsconfig.json tsconfig.build.json ./ COPY src ./src RUN npm run build && npm prune --omit=dev FROM mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble AS runtime WORKDIR /app ENV NODE_ENV=production \ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \ HOST=0.0.0.0 \ PORT=8080 \ PROFILE_DIR=/data/profile COPY --from=build /app/node_modules ./node_modules COPY --from=build /app/dist ./dist COPY package.json ./ COPY public ./public # The profile directory is normally a mounted volume; create it anyway so # the image runs standalone. RUN mkdir -p /data/profile && chown -R pwuser:pwuser /data /app USER pwuser EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||8080)+'/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" CMD ["node", "dist/server.js"]