First of all, I am really new to dockers and everything that relates to it. I tried to use tutorials and instructions from web, but I see the answers from this question and I guess I don't have other options other than move to Linux completely (which I really don't want to do)
I have a docker-compose project with ASP.NET Core, Nginx and React. FrontEnd and BackEnd have their own dockerfile and dockerignore.
FrontEnd doesn't update code changes at all.
I tried to build only client service by using docker-compose build --no-cache but after two minutes of compiling I see that it didn't change anything.
Only possible solution for me is to delete docker-compose project and compile every service again. But it makes development so much difficult.
dockerfile:
FROM node:16-alpine
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY ./package.json /app
RUN npm install
COPY . .
RUN npm run build
CMD ["npm", "start"]
docker-compose.yml (client service):
client:
image: client
build:
context: ./walletfrontend
dockerfile: Dockerfile
environment:
- WATCHPACK_POLLING=true
I tried to use WATCHPACK_POLLING=true as suggested in another question but I think it does nothing and I am not really sure why is it needed for.
UPDATE:
So I think I found a solution in this article:
https://shahmirprogrammer.medium.com/docker-with-react-changes-reflect-real-time-inside-a-container-f83acf208f8a
It really updates the changes in real time.
So my next goal is to change this strange command which I don't have a clue what it does to docker-compose equivalent:) :
docker run -d -p 3000:3000 -v /app/node_modules -v $(pwd):/app --name dockerized-react-app react-app-image:1
UPDATE #2:
So I think solution is to use volumes with correct path to my host machine:
volumes:
- /app/node_modules
- ./walletfrontend:/app
It's been almost a week and it was really difficult to find a solution for this. I hope this would help in the future for newbies like me
FROM node:16-alpine
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY ./package.json /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
copy all the files before you run npm install.
a really useful tutorial on this can be found here
https://mherman.org/blog/dockerizing-a-react-app/
Dockerfile
# pull official base image
FROM node:13.12.0-alpine
# 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 ./
RUN npm install --silent
RUN npm install react-scripts#3.4.1 -g --silent
# add app
COPY . ./
# start app
CMD ["npm", "start"]
docker-compose.yml
version: '3.7'
services:
sample:
container_name: sample
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/app'
- '/app/node_modules'
ports:
- 3001:3000
environment:
- CHOKIDAR_USEPOLLING=true
that guide I just linked you also contains info on how to get your app production ready
Related
version: "1.0.0"
services:
########################################################################################################
############################################# VALIDLY #################################################
########################################################################################################
validly-studio:
build:
context: ./studio
dockerfile: Dockerfile
volumes:
- type: bind
source: ./studio
target: /app
- /app/node_modules
restart: unless-stopped
ports:
- 3000:3000
networks:
- validly
networks:
validly:
above is my docker-compose.yml file
FROM node:16.14-alpine
# set working directory
WORKDIR /app
# install app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm install
# add app
COPY . ./
# start app
CMD ["npm", "start"]
this is my Dockerfile.
docker builds the react app and it prompts me to goto localhost:3000 where the app is running. But when I goto localhost:3000. I shows connection refused.
In your Dockerfile you copy in folder App everything to app/
And in your docker-compose you map /app to /app/node_modules.
This will not work.
Choose 1 of the two, and my instinct (and many error in the past) tell me that you should build everything in Dockerfile, including copying node_modules, and don't touch it in docker-compose.
Dockerfile
Template Dockerfile for React: (this one with NextJS environment, which makes it only more complex)
# Dependencies Container
FROM node:lts-alpine3.12 AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Here we create node_modules
COPY package.json ./
COPY package-lock.json ./
RUN npm install -g npm#7.24.0 --no-update-notifier
RUN npm --version
RUN npm ci --no-update-notifier
# Rebuild the source code only when needed
FROM node:lts-alpine3.12 AS builder
WORKDIR /app
COPY . .
# Here we copy node_modules from previous intermediate container
COPY --from=deps /app/node_modules ./node_modules
RUN npm install -g npm#7.24.0 --no-update-notifier
RUN npm --version
RUN node -v
RUN npm run build --no-update-notifier
# Production Image
FROM node:16-bullseye AS runner
WORKDIR /app
ENV NODE_ENV production
# Here we only copy. No building needed, keeps the image small.
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/package-lock.json ./package-lock.json
RUN addgroup -gid 1001 nodejs
RUN adduser -uid 1002 nextjs
RUN adduser nextjs nodejs
RUN chown -R nextjs:nodejs /app/.next
USER nextjs
docker-compose.yml
Here a template docker-compose.yml using the above Dockerfile
version: "3.9"
services:
webshop:
build:
context: ./build
dockerfile: Dockerfile_webshop
image: mywebshop
restart: "no"
container_name: MyWebshop
command: ["npm", "start"]
As you see, no volumes needed.
I'm trying to dockerize a basic CRA template created through npx create-react-app project-name, of which Dockerfile would look like:
FROM node:latest
WORKDIR /usr/src/client
COPY ./ ./
RUN npm install
EXPOSE 3000
CMD ["npm", "start"]
I've built the image by running docker build -t containername .
and then run it with docker run -it -p 3000:3000 containername
Everything works fine, the container runs successfully and I can see the webpage running on the browser.
Problem here is webpack hot reloading not working, causing the app to not recompile upon changes.
Same question was posed already here and here but sadly with unsuccessful results. Problem seems to appear for Windows users, but in my case I'm on Mac.
I've tried already:
Updating npm start script with CHOKIDAR_USEPOLLING=true react-scripts start
Adding EXPOSE 35729 as explained here
Any suggestion is highly appreciated, thank you in advance!
i think webpack server doesn't see any new changes, because you modify your local file, but container uses its copies in runtime, which was passed in build time. so you should mount your local dir to container.
i can suggest you use docker-compose to mount your work dir from host to container:
docker-compose.yml
version: '3.4'
services:
app:
build: ./
volumes:
- ./src:/usr/src/client
ports:
- 3000:3000 # HOST:CONTAINER
command: npm start
or maybe use -v $(pwd)/src:/app/src in run command docker run ...
Unbelievably, the issue was caused by the working directory naming.
In order to fix it, I simply had to change it from /usr/src/client to /app and it started recompiling, even though I have no clue of the why.
FROM node:latest
WORKDIR /app
COPY ./ ./
RUN npm install
EXPOSE 3000
CMD ["npm", "start"]
The following worked for me.
docker run -p 3000:3000 -v ${PWD}:/usr/app -e CHOKIDAR_USEPOLLING=true globoreactapp/latest
Run that on windows poweshell.
If you are using windows cmd, you may try,
docker run -p 3000:3000 -v %cd%:/usr/app -e CHOKIDAR_USEPOLLING=true globoreactapp/latest
And if you are running on some linux distro, you can try something like this.
docker run -p 3000:3000 -v -e CHOKIDAR_USEPOLLING=true $(pwd):/usr/app
So here specifying
-e CHOKIDAR_USEPOLLING=true
made the difference for me.
Also with docker-compose, you need to add the same environment variable. Mine looks as follows.
version: '3'
services:
redis-server:
image: 'redis'
node-app:
build:
context: ./globoappserver
ports:
- "9080:8080"
container_name: api-server
ui:
build:
context: ./globo-react-app-ui
environment:
- CHOKIDAR_USEPOLLING=true
ports:
- "7000:3000"
stdin_open: true
volumes:
- ./globo-react-app-ui:/usr/app
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.
// Dockerfile
# pull base image
FROM node:10.15.1-alpine
# 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 ./yarn.lock ./
RUN yarn install
RUN yarn global add react-scripts#3.4.1 // not sure if this is even necessary
# add app
COPY . ./
# start app
CMD ["yarn", "start"]
Command I'm running to build it:
docker build -t matrix-fe:dev .
Command to run it:
docker run -it --rm -v ${PWD}:/app -v /app/node_modules -p 3000:3000 -e CHOKIDAR_USEPOLLING=true matrix-fe:dev
And then this is my composer yml:
version: '3.7'
services:
matrix-fe:
container_name: matrix-fe
build:
context: ./a-fe
dockerfile: Dockerfile
volumes:
- './a-fe:/app'
- '/app/node_modules'
ports:
- 3000:3000
environment:
- CHOKIDAR_USEPOLLING=true
Then to build and run it:
docker-compose up --build
Error I'm getting:
matrix-fe | yarn run v1.13.0
matrix-fe | $ react-scripts start
matrix-fe | It looks like you're trying to use TypeScript but do not have typescript installed.
matrix-fe | Please install typescript by running yarn add typescript.
matrix-fe | If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files).
matrix-fe |
Why is this happening? I can obviously try to also install typescript, but it is a dependency in package.json and should be installed, I also added node_modules to path. How is running the image with and without docker-compose different? Compose does create a different image called matrix_matrix-fe, but then Dockerfile hasn't changed. docker-compose.yml is in a top level folder, structure looks like this:
/matrix
/a-fe
./package.json
./Dockerfile
...
/a-be
./docker-compose.yml
Help me understand what's different, volumes are same, ENV variables are same, not seeing anything off.
Edit: forgot to mention that running the image without docker-compose doesn't output errors, it's working properly.
I'm trying to make that every time a new change is made on the app I do not need to build the app, and then run the docker-compose file. What I'm trying to do is that when I change code in my application (ReactJs) to just go and run docker-compose file, so then docker-compose will build and run it using nginx.
Here's what my docker-compose.yml looks like:
version: '2'
services:
nginx:
image: 'bitnami/nginx:1.14.2'
ports:
- '80:8080'
volumes:
- ./build:/var/www/my-app
- ./nginx.conf:/opt/bitnami/nginx/conf/nginx.conf:ro
Right now with this code, I need to build the application myself running npm run build and then go and run the docker-compose file so it would take the changes.
I don't exactly know how to do it, so I assume I need to create a Dockerfile run npm run build and then call the bitmani/nginx:1.14.2 based on their docs: https://hub.docker.com/r/bitnami/nginx/
FROM node:8.7.0-alpine
RUN npm install
RUN npm run build
docker run --name nginx \
-v /path/to/my_vhost.conf:/opt/bitnami/nginx/conf/vhosts/my_vhost.conf:ro \
-v /path/to/nginx-persistence/nginx/conf/bitnami/certs:/bitnami/nginx/conf/bitnami/certs \
bitnami/nginx:latest
and in docker-compose.yml call build . instead of image: bitnami/nginx.
You should use a stage build for this. Your Dockerfile should look like this:
# Stage 1 - Building image
FROM node:8.7.0-alpine as node
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Stage 2 - Running image
FROM bitnami/nginx:1.14.2
COPY --from=node /usr/src/app/build /var/www/my-app
COPY ./nginx.conf /opt/bitnami/nginx/conf/nginx.conf
And your docker-compose:
version: '3.3'
services:
myApp:
image: myapp:1.0
container_name: my-app
build: .
ports:
- 80:8080
I adapted this from one of my projects so if you have any issues let me know and I'll check them.
I hope it helps.