create a Dockerfile for node
FROM node:20-alpine # 1) Create non-root user# addgroup --system appgroup: Creates a system group named appgroup.# adduser --system --ingroup appgroup appuser: Creates a system user named appuser and adds it to appgroup.# USER appuser: Tells Docker to run all subsequent commands (including your app) as appuser instead of root.RUN addgroup -S appgroup && adduser -S -G appgroup appuser # 2) Set working directoryWORKDIR /app # Fix: Set ownership of /app to app userRUN chown app:app /app # 3) Copy only manifest files first (better layer caching)COPY --chown=app:app package*.json ./ # 4) Install deps (prod only for production images)USER app RUN npm ci --omit=dev # 5) Copy the rest of the appCOPY --chown=app:app . . # 6) Runtime configENV NODE_ENV=production EXPOSE 8000 CMD ["npm", "start"]
Create a .dockerignore
node_modules npm-debug.log .git .gitignore Dockerfile .dockerignore .env dist coverage .vscodeBuild the image
docker build -t blogapi:latest .Run Container with .env
docker run -d --restart unless-stopped --name blogapi --env-file .env -p 8000:8000 blogapi:latest
Inspect and interact
- Logs (follow):
docker logs -f web-app - Stop / remove:
docker stop web-app docker rm web-app
Optional: Dev mode (hot reload)
Publihs image
docker logindocker tag blogapi:latest <your-username>/blogapi:latestdocker push <your-username>/blogapi:latest