I am building a Node.js project and it has a DockerFile in it . I am referring a sample DockerFile and I have questions related to it .
DockerFile
FROM alpine 3.14
COPY .npmrc ./
RUN npm install pnpm@${9} -- global
RUN pnpm config set store-dir ~./pnpm-store
WORKDIR /app
COPY package*.json
COPY..
RUN pnpm build
COPY --from=builder /app/dist ./dist/
RUN useradd -ms /bin/bash vault
Questions:
a) when the WORKDIR /app is set at line number 5 , will the "COPY .npmrc ./" work since the working directory itself is not created at line 3.
b) Why do we need to set store-dir at line number 4. Is that the location where pnpm commands get executed?
c) what is the purpose of copying from /app/dist to ./dist/ . Is it not possible to run the app from /app folder?
d) why do we need to add users as mentioned in line 10?
(a) WORKDIR
creates the directory if it doesn't already exist, so you're fine. (I see occasional Dockerfiles that RUN mkdir
just before WORKDIR
, and that line can be deleted.)
(b) Many package-management tools store a cache of downloaded files. If the default cache location is somewhere that's not writable, then you might need to specify an alternate location. (In newer Docker, a RUN --mount=type=cache,...
directive can cause the cache to actually be used.)
(c) This line suggests a substantial part of the Dockerfile is missing. The COPY --from=...
syntax generally goes with a multi-stage build, with the idea that the first part of the Dockerfile builds the application and then a later part contains only what's necessary to run it. A typical pattern for a Node application would look like
FROM node:lts AS builder
...
# (this includes devDependencies)
RUN npm ci
RUN npm build
FROM node:lts
...
ENV NODE_ENV=production
# (and so this does not include devDependencies)
RUN npm ci
COPY --from=builder /app/dist ./dist
(d) Just in general in Unix, it's not considered good practice to run things as root if you don't need to. In Docker it's common to create some non-root user. Best practices here are to have the user not own the files – you don't want the application to overwrite its own source – and to not bother with any sort of shell or home directory, since you don't "log in" to a Docker container.
# ... implicitly as root ...
RUN pnpm build
# Switch to a non-root user only when you're declaring how to run the container
RUN useradd -r vault
USER vault
CMD ["node", "dist/main.js"]