I’ve got the following Dockerfile for a React app and I’m running tests after I build this container. This is my first day with Docker and I’m following a course, so not really sure what I’m doing.
FROM node:13.12.0-alpine as builder
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
RUN apt-get update && apt-get install -y npm
ARG NODE_VERSION=14
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash -
&& apt-get update
&& apt-get autoremove
&& apt-get install -y nodejs
COPY --from=builder /app/build /usr/share/nginx/html
The reason I have these two RUN
after FROM nginx
is that after running docker build -t username/project-name .
, I’d run docker run ID npm run test
and get /docker-entrypoint.sh: 38: exec: npm: not found
.
Since I added the two RUN
statements (which I’m not sure is a good idea) the build is still successful, but then I run the tests with docker run ID npm run test
and I get the following error:
npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path /package.json
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, open '/package.json'
npm ERR! enoent This is related to npm not being able to find a file.
I’ve also tried running docker run -w /app ID npm run test
but get the ENOENT: no such file or directory, open '/app/package.json'
error.
My file structure is this:
project
node_modules
src
Dockerfile
package.json
...
2
Answers
This is an multi-stage build.
docker build -t username/project-name .
creates a container from the last stage starting withfrom nginx
. In this container you copy the build directory but no package.json.To solve this problem you could do the following
builder
. To do this add in the Dockerfile the following lineRUN npm run test
builder
container withdocker build --target=builder -t username/project-name
and usedocker run ID npm run test
The overall multi-stage build pattern you show here is typical for producing a deployable image with a browser-based application compiled down to static files. The entire contents of the image are the last stage, starting from the final
FROM
line:So this image only contains the contents of the
./build
tree from the first stage and nothing else. Thepackage.json
file and thenode_modules
tree aren’t part of this.There’s no rule that you must use exclusively Docker-based tools, even if you’re eventually shipping a Docker image. For day-to-day development I’d recommend using a host-based Node environment, rather than trying to indirectly use Docker to simulate it. Then you can run your unit tests before you package up your application.