# internaluploader-server. Build context is server/. # # Registries are fully qualified: podman enforces short-name resolution and # fails a non-interactive build with "cannot prompt without a TTY" rather than # choosing one. FROM docker.io/library/node:22-alpine AS build WORKDIR /src COPY package.json package-lock.json ./ RUN npm ci COPY tsconfig.json tsconfig.test.json ./ COPY src ./src COPY test ./test # Typecheck and test INSIDE the image build — an image that compiles but fails # its own tests should not reach a registry. RUN npm run typecheck RUN npm test RUN npm run build # Drop devDependencies from what gets copied forward. RUN npm prune --omit=dev FROM docker.io/library/node:22-alpine AS runtime WORKDIR /app ENV NODE_ENV=production COPY --from=build /src/node_modules ./node_modules COPY --from=build /src/dist ./dist COPY --from=build /src/package.json ./package.json # uid 1000 — the same uid/gid the metube container writes /downloads with, so # both apps' files on the share look identical. USER node EXPOSE 8080 CMD ["node", "dist/index.js"]