I want to create a development environment for a reactjs application. I am new to Docker and have been trying to create an environment using Docker. Below is my Dockerfile code.
# Base node image
FROM node
# create working directory
ADD ./code /usr/src/app
WORKDIR /usr/src/app
# add node_modules path to environment
ENV PATH /usr/src/app/node_modules/.bin:PATH
# copy and install dependencies
COPY ./code/package.json /usr/src/app/package.json
RUN npm install --quiet
RUN npm install react-scripts#1.1.1 -g --silent
# start app
# CMD ["npm","start"]
However, I am getting the error "npm: not found" at line RUN npm install --quiet.
I confirm that node comes with npm:
$ docker run -it --rm node /bin/bash
root#b35e1a6d68f8:/# npm --version
5.6.0
But the line
ENV PATH /usr/src/app/node_modules/.bin:PATH
overwrites the initial PATH, so you should try replacing it with
ENV PATH /usr/src/app/node_modules/.bin:${PATH}
Also, note that your ADD ./code ... line is clumsy, because it would add all the files of your application (including ./code/package.json!) and this step comes too early (w.r.t. Docker's cache mechanism), so I'd suggest to simply remove that line ADD ./code /usr/src/app and add a line COPY ./code ./ after the RUN npm install ...
Finally you may also want to take a look at the official documentation for "dockerizing" a Node.js app: https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
Related
How do I configure this as a multi stage build
yarn start maps to
"start": "nodemon ./server-build/index.js",
Dockerfile
FROM node:14.17.3-alpine AS build
RUN apk add --no-cache build-base gcc autoconf automake libtool zlib-dev libpng-dev nasm
RUN npm i nodemon -g
WORKDIR /app/web-web
ENV PATH /app/web-web/node_modules/.bin:$PATH
COPY package.json /app/web-web/package.json
RUN yarn install --network-timeout 1000000000
COPY . /app/web-web
RUN yarn run build:staging
COPY . /app/web-web
EXPOSE 3006
CMD ["yarn", "start"]
Warning NOT Tested code.
The Dockerfile below is not tested and you must consider it as a starting point.
Missing some info, the apk packages are required only for build or else to run ?
I suggest you read about multi-stage build
###############################################################
# This stage do:
# 1. Install required software
# 2. Copy package.json and install deps
###############################################################
FROM node:14.17.3-alpine AS build
# This packet are required ONLY for build ??? Otherwise add on final stage
RUN apk add --no-cache build-base gcc autoconf automake libtool zlib-dev libpng-dev nasm
WORKDIR /app/web-web
ENV PATH /app/web-web/node_modules/.bin:$PATH
COPY package.json /app/web-web/package.json
RUN yarn install --network-timeout 1000000000
###############################################################
# This stage do:
# 1. copy node_modules from build stage to this image
# 2. build app and run
###############################################################
FROM node:14.17.3-alpine AS final
WORKDIR /app/web-web
# Magic append here: I copy from prev stage (build) to this one
COPY --from=build /app/web-web .
COPY . /app/web-web
RUN npm i nodemon -g
RUN yarn run build:staging
EXPOSE 3006
CMD ["yarn", "start"]
I am deploying a react app to Heroku via TravisCI. The fact that I'm using Heroku doesn't really affect what I'm about to ask, I'm pretty sure, it's just there for context. Travis successfully deploys the app until I add a testing step (the script section) in .travis.yml:
language: generic
sudo: required
services:
- docker
before_install:
- docker build -t myapp:prod -f Dockerfile.prod .
script:
- docker run -e CI=true myapp:prod npm run test
after_success:
- docker build -t myapp:prod -f Dockerfile.prod .
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_ID" --password-stdin
- docker push myapp:prod
deploy:
provider: heroku
app: myapp
skip_cleanup: true
api_key:
secure: <my_key>
However, my Dockerfile.prod is a multi-stage node + nginx where the nginx stage doesn't keep any node or npm stuff:
# build environment
FROM node:13.12.0-alpine as builder
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install app dependencies
COPY package.json ./
COPY package-lock.json ./
# some CI stuff I guess
RUN npm ci
RUN npm install react-scripts#3.4.1 -g --silent
COPY . ./
RUN npm run build
# production environment
FROM nginx:stable-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
# If using React Router
COPY --from=builder /app/build /usr/share/nginx/html
# For Heroku
CMD sed -i -e 's/$PORT/'"$PORT"'/g' /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'
Therefore, it is my understanding that .travis.yml tries to run that npm run test command inside my nginx container and can't execute npm commands (no node installed, right?). So guided by SO answers such as this one I started adding commands into that nginx stage such as
COPY package.json ./
COPY package-lock.json ./
RUN apk add --update npm
but I realized I might be approaching this the wrong way. Should I perhaps be adding npm through Travis? That is, should I include in .travis.yml in the scripts section something like docker run -e CI=true myapp:prod apk add --update npm and whatever else is necessary? This would result in a smaller nginx image no? However, would I run into problems with package.json from the node stage in Dockerfile.prod or anything like that?
In summary, to use TravisCI to test a dockerized react app served with nginx, at what point should I install npm into my image? Does it happen as part of script in .travis.yml or does it happen in Dockerfile.prod? If it is recommened to npm run tests inside Dockerfile.prod, would I do that in the first stage (node) or the second (nginx)?
Thanks
EDIT: Not sure if this can be considered solved, but a user on Reddit recommended to simply RUN npm run test right before the RUN npm run build.
I have an Angular application with the following Dockerfile
FROM node:8
ENV APP_HOME /app
RUN mkdir -pv $APP_HOME
WORKDIR $APP_HOME
ENV NODE_ENV production
ENV NPM_CONFIG_LOGLEVEL warn
ENV CUSTOM_REGISTRY https://registry.npmjs.org/
RUN npm config set strict-ssl false
RUN npm config set registry $CUSTOM_REGISTRY
COPY . $APP_HOME
RUN npm install -g #angular/cli
RUN npm install
As you can see, in the copy command, we copy the current directory to the working directory of the container, however, after I SSH into the container to check if all the files were copied, I see that files which have two . in them are not copied.
Some examples are -
.angular-cli.json
.travis.yml
How can I move these files over to the container, the .angular-cli.json is specially critical for me to make the application run.
My Dockerfile is using alpine and globally installing react-scripts. When it tries to install it, it fails with "could not get uid/gid" error. I added the "---unsafe-perm" option to the npm install -g command. The docker container is successfully created, but the permissions in the container are messaged up for the installed files. I see the username and group set to 1000 for all of them. I tried adding the following command to the Dockerfile right before the install step but that didn't help.
RUN npm -g config set user root
Build error
Error: could not get uid/gid
[ 'nobody', 0 ]
at /usr/local/lib/node_modules/npm/node_modules/uid-number/uid-number.js:37:16
at ChildProcess.exithandler (child_process.js:296:5)
at ChildProcess.emit (events.js:182:13)
at maybeClose (internal/child_process.js:961:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:250:5)
TypeError: Cannot read property 'get' of undefined
at errorHandler (/usr/local/lib/node_modules/npm/lib/utils/error-handler.js:205:18)
at /usr/local/lib/node_modules/npm/bin/npm-cli.js:76:20
at cb (/usr/local/lib/node_modules/npm/lib/npm.js:228:22)
at /usr/local/lib/node_modules/npm/lib/npm.js:266:24
at /usr/local/lib/node_modules/npm/lib/config/core.js:83:7
at Array.forEach (<anonymous>)
at /usr/local/lib/node_modules/npm/lib/config/core.js:82:13
at f (/usr/local/lib/node_modules/npm/node_modules/once/once.js:25:25)
at afterExtras (/usr/local/lib/node_modules/npm/lib/config/core.js:173:20)
at Conf.<anonymous> (/usr/local/lib/node_modules/npm/lib/config/core.js:231:22)
/usr/local/lib/node_modules/npm/lib/utils/error-handler.js:205
if (npm.config.get('json')) {
^
TypeError: Cannot read property 'get' of undefined
at process.errorHandler (/usr/local/lib/node_modules/npm/lib/utils/error-handler.js:205:18)
at process.emit (events.js:182:13)
at process._fatalException (internal/bootstrap/node.js:472:27)
ERROR: Service 'sample-app' failed to build: The command '/bin/sh -c npm install react-scripts#1.1.1 -g' returned a non-zero code:
Dockerfile
/usr/src/app # cat Dockerfile
# build environment
FROM node:10-alpine as builder
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install
RUN npm install react-scripts#1.1.1 -g
COPY . /usr/src/app
RUN npm run build
# production environment
FROM nginx:1.13.9-alpine
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
UPD Fixed in nodejs#12.4.0?
Check if this is linked to nodejs/docker-node issue 813:
Root cause seems to be: Thread stack size
The default stack size for new threads on glibc is determined based on the resource limit governing the main thread’s stack (RLIMIT_STACK).
It generally ends up being 2-10 MB.
There three possible solutions:
Talk to Alpine teams to fix it. There were some discussions already
Fix it in the node docker alpine image as follows
Set default npm_config_unsafe_perm=true in the docker image as a workaround until it's fixed.
You already tried the third option, but consider also:
Alternatively, you should switch to the slim (Debian) variant until this get's fixe upstream by the Alpine team.
I faced same issue in Docker for node-alpine image when I am dockerizing my react application
I resolved with following dockerfile configuration.
FROM node:8.10.0-alpine
# Set a working directory
WORKDIR /usr/src/app
COPY ./build/package.json .
COPY ./build/yarn.lock .
# To handle 'not get uid/gid'
RUN npm config set unsafe-perm true
# Install Node.js dependencies
RUN yarn install --production --no-progress
# Copy application files
COPY ./build .
# Install pm2
RUN npm install -g pm2 --silent
# Run the container under "node" user by default
USER node
CMD ["pm2", "start", "mypm2config.yml", "--no-daemon", "--env", "preprod"]
I'm having some issues with a multi-stage Dockerfile for an ejected create-react-app. The Dockerfile is listed below:
FROM node:9.6.1 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
COPY . /usr/src/app
RUN npm run build
FROM nginx:1.13.9-alpine
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
The Dockerfile runs successfully until it gets to step 10 (COPY) where it throws the following error:
COPY failed: stat /var/lib/docker/overlay2/2fc8af4cb8db9777246cae48721d8a93917c73e415a02680f1e3a73c8780b903/merged/usr/src/app/build: no such file or directory
I've googled away but can't find a clear answer. Has anyone experienced anything similar?
When you build the application it's building in another cointainer/layer. You i'll need to build the application before and copy the build folder to /usr/src/app.
So, this is fine:
FROM node:9.6.1 as builder
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json .
COPY public public
COPY src src
RUN npm install --silent
RUN npm run build
COPY build .
RUN rm -rf src
RUN rm -rf build
FROM nginx:1.13.9-alpine
COPY --from=builder /usr/src/app /usr/share/nginx/html
EXPOSE 80
I'm removing the src and build folders since that's not necessary and can expose an critical part of your application.
Hence, no doubt about the security of dockerizing an application.
It's hard to tell from that, but my best guess would be that "RUN npm install --silent" is failing, possibly because it can't download one of your packages due to either a network issue or some other reason, therefore your build is then failing and not producing the build folder.
I had the same error using volumes Just because project (and Also dockerfile obviously) was outside Users/[currentuser] folder.. It Easy in "program files". Moving project from program files folder ti Users/[currentuser] It worked. I don't know if it's the same case. Try It and let me know
Possibly because COPY . /usr/src/app should be done inside top level directory so that build is created inside /usr/src/app. Do one thing. Put this command 'COPY . /usr/src/app' at the top(before WORKDIR /usr/src/app) and post the output here so I can help you better.
A cleaner way to do this would be like the following:
FROM node:9.6.1 as builder
WORKDIR /build
ENV PATH /build/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
COPY . /build/app
RUN npm run build
FROM nginx:1.13.9-alpine
COPY --from=builder /build /usr/share/nginx/html
EXPOSE 80