How to save build from Docker Container? - reactjs

I use Volumes! But smth went wrong.
My web-app config:
And if I use volumes: -"../web/build:/web/build" it doesn't work.
My NGINX config:
I start docker-compose up --build and see that build is complete in /build. I use RUN ls /build to check it. All is correct.
But when I check on server (not in Docker) web/build - folder is created, but is empty.
Why? How can I save build to use it in NGINX?
My Dockerfile for web-app:

in your dockerfile add name to the first image builder for example then use it to copy the files to nginx
FROM node:13.13.0 as builder
WORKDIR .
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
COPY --from=builder /build /usr/share/nginx/html

Related

React not reading environment variable value in production from docker-compose.yml but reading it on local machine

I tried to pass my variable from docker-compose.yml to docker container but my container doesn't see the value of this variable. I have tried many cases but all to no avail. here are my attempts.
First try:
FROM node:alpine3.17 as build
LABEL type="production"
WORKDIR /react-app
COPY package.json ./
COPY package-lock.json ./
RUN npm install
COPY . ./
ARG REACT_APP_BACKEND_URL
ENV REACT_APP_BACKEND_URL=$REACT_APP_BACKEND_URL
RUN npm run build
# production environment
FROM nginx:stable-alpine
COPY --from=build /react-app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Second try:
FROM node:alpine3.17 as build
LABEL type="dev"
WORKDIR /react-app
COPY package.json ./
COPY package-lock.json ./
# The RUN command is only executed while the build image
RUN npm install
COPY . ./
ARG REACT_APP_BACKEND_URL
ENV REACT_APP_BACKEND_URL=$REACT_APP_BACKEND_URL
RUN npm run build
RUN npm install -g serve
EXPOSE 3000
# The CMD command is only executed while the image is running
CMD serve -s build
And I built the container from Dockerfiles, then I pushed it to docker-hub with various version and after that I run docker-compose.yml from the remote server.
My docker-compose.yml
version: '3'
services:
stolovaya51-react-static-server:
container_name: stolovaya51-react-production:0.0.1 (for example)
build:
args:
- REACT_APP_BACKEND_URL=REACT_APP_BACKEND_URL
ports:
- "80:80"
- "3000:3000"
By the way, when I run this code on my local machine, I see the value of the environment variable, but when I try to run this code on the server, I only see the variable name, but the value = "".
I don't know the reason, what's the matter?
I have found the answear for my question!
Firstly, i have combined two repository with frontend and backend into one project.
Then, i have redesigned my project structure and gathere together two parts of my application. For now i have this structure:
root_project_folder:
./frontend
...some src
./frontend/docker/Dockerfile
./backend
...somer src
./backend/docker/Dockerfile
docker-compose.yml
And now, my frontend applies all args from docker-compose.yml from the root folder

Trouble running a docker container for react-app where package.json is in a subfolder

I am trying to create a dockerfile for a project that has the following folder structure:
HDWD-project
|_ client
| |_ package.json
|_ server
|_ package.json
Client is a react-app and I am just working with this at the moment, before including server which is the backend.
I am having real trouble figuring out the logic of the dockerfile and have googled furiouly for the last two days. All the examples are too easy.
I just can't seem to get react-app to start in the container, and get varying error messages. But I need to know the dockerfile is fine before I proceed.
FROM node:latest
WORKDIR HDWD-project
COPY ./client/package.json .
RUN npm install
COPY . .
RUN cd client
CMD ["npm", "start"]
Going forward I have a script that can start both the server and the client, but I'm just trying to get my head around docker and getting the client frontend to run fine.
Would anyone be able to correct me on where the issue in this config is and explain it?
This is a docker file for the frontend(client in your case). You can make a dockerfile under your client folder and build the image with docker build -t image-name:tag-name .
# Pull the latest node image from dockerhub
FROM node:latest
# Create app directory
WORKDIR /usr/src/app
# Copy package.json and package-lock.json to the workdir
COPY package*.json ./
# Install the dependencies
RUN npm install
# Bundle app source
COPY . .
# Run the app in docker
CMD ["npm", "start"]

How to get Next.JS environment variables on client side?

I have a Next.Js application that I will deploy with docker. I am passing my environment variables in docker file and docker-compose.yaml. Next version: 12.1.6
Dockerfile
# Install dependencies only when needed
FROM node:16-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# If using npm with a `package-lock.json` comment out above and use below instead
# COPY package.json package-lock.json ./
# RUN npm ci
# Rebuild the source code only when needed
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN yarn build
# If using npm comment out above and use below instead
# RUN npm run build
# Production image, copy all the files and run next
FROM node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_PUBLIC_BASE_URL example --> I'm stating it here. Example is not my value, it just takes space.
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# You only need to copy next.config.js if you are NOT using the default configuration
# COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
docker-compose.yaml
version: '3'
services:
frontend:
image: caneral:test-1
ports:
- '3000:3000'
environment:
- NEXT_PUBLIC_BASE_URL=https://example.com/api
I am building with the following command:
docker build -t caneral:test-1 .
Then I run docker-compose:
docker-compose up -d
While I can access the NEXT_PUBLIC_BASE_URL value on the server side, I cannot access it on the client side. It returns undefined. Shouldn't I reach it because I define it as NEXT_PUBLIC? This is stated in the official documents.
How to get environment variables on client side?
Details, you have:
Your .env file. (i'm not sure how docker files will affect logic)
Your next.config.js file
Server-side has access to these 2 files.
Client-side doesn't have access to .env file.
What you can do:
In your next.config.js file you can declare a variable where value is your process.env value.
const baseTrustFactor = process.env.trustFactor
IMPORTANT: do not expose your private info (keys/tokens etc.) to the client-side.
If you need to compare the tokens you can:
Send them from the backend (From NodeAPI or similar)
Make conditions in next.config.js such as:
const baseTrustFactor = process.env.trustFactor == '21' ? true : false

Deploy docker image of react app to Elastic beanstalk

I am trying to deploy my create-react-app to elastic bean stalk with docker
I have setup codepipeline with codebuild and elastic beanstalk.
I am getting this error
Stop running the command. Error: Dockerfile and Dockerrun.aws.json are both missing, abort deployment
My Dockerfile looks like this
FROM tiangolo/node-frontend:10 as build-stage
# Create app directory
# RUN mkdir -p /usr/src/app
# WORKDIR /usr/src/app
WORKDIR /app
# # fix npm private module
# ARG NPM_TOKEN
# COPY .npmrc /app/
#COPY package.json package.json
COPY package*.json /app/
COPY Dockerrun.aws.json /app/
RUN npm install
COPY ./ /app/
# RUN CI=true npm test
RUN npm run build
# FROM nginx:1.15
FROM nginx:1.13.3-alpine
# Install app dependencies
# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx
COPY --from=build-stage /app/build/ /usr/share/nginx/html
# Copy the default nginx.conf provided by tiangolo/node-frontend
COPY --from=build-stage /nginx.conf /etc/nginx/conf.d/default.conf
RUN ls
EXPOSE 80
I also have a Dockerrun.aws.json
{
"AWSEBDockerrunVersion": "3",
"Image": {
"Name": "something.dkr.ecr.us-east-2.amazonaws.com/subscribili:latest",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "5000"
}
],
"Logging": "/var/log/nginx"
}
my buildspec.yml file looks like this
version: 0.2
phases:
pre_build:
commands:
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- REPOSITORY_URI=something.dkr.ecr.us-east-2.amazonaws.com/subscribili
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- printf '[{"name":"nginx","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
I am sure there is some issue with buildspec file but I am just not sure what.
I have read all the documentation still couldn't figure out how to write the buildspec file Docker.
Is there anything I am missing?
Dockerfile and Dockerrun.aws.json these 2 files need to be in the same directory where the command "COPY Dockerrun.aws.json /app/ " is running. make sure these files exists in that directory and this error should disappear
"eb deploy" command creates a zip file from your code. However, to make it as small as possible, it only takes the file that are commited to git. So, if you did not commit Dockerfile and Dockerrun file, these two files won't be included in the zip.
If you do not want it to behave like this, you can add .ebignore file to your projects root directory. This files commands are the same as the gitignore file; you can copy everything from gitignore to ebignore. If there is a .ebignore, cli will not check if the project is commited to a source control.
Now to check what is included in zip file, watch the .elasticbeanstalk folder after "eb deploy" command. When the zip is prepared, copy it immediately and paste to another folder. Note: the original zip file will be removed after the cli upload that.

React doesnt work with Path and Prefix in Traefik

I have a React App, that I build with the following Dockerfile
# base image
FROM node:latest as builder
# set working directory
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY app/package.json /usr/src/app/package.json
RUN npm install
RUN npm install react-scripts#1.1.1 -g
COPY ./app/usr/src/app
# start app
CMD ["npm", "start"]
# production environment
FROM nginx:alpine
RUN rm -rf /etc/nginx/conf.d
COPY conf /etc/nginx
COPY --from=builder /usr/src/app/build /etc/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Then I run this with the following Docker Compose
build: .
labels:
- "traefik.frontend.rule=Host:www.example.com;PathPrefix:/path"
- "traefik.protocol=http"
- "traefik.frontend.entryPoints=https"
- "traefik.port=80"
- "traefik.enable=true"
restart: always
When calling example.com/path I get a lot of 404 Errors, as the React App is not looking for path, but in the root of example.com.
The App is woking when run without PathPrefix and calling example.com directly.
Your app doesn't know that traefik is adding a prefix.
You need to specify homepage property in package.json file to modify every relative URLs that will be used in your app. After building your app using npm run-script build it should be fine.
{
"homepage": "/path"
}
react documentation
I have arrived to a solution to your problem. Let me explain:
The "default" path in production environments for our project
is normally /sforms
I wanted to serve the built package -without rebuild- from any path
in production environments, so "homepage": "." was mandatory.
Example: /sforms_1.0, /sforms_legacy... etc.
So I have reconfigured the script "start" in package.json in the following way:
"start": "cross-env PUBLIC_URL=/sforms react-scripts start"
In this way I'm able to start my dev environment under /sforms,
avoiding the "magic" of traefik, but keeping the "homepage": ".".
So in Traefik I only have to redirect all the calls starting
with the prefix /sforms to my development server, and all the cases
are covered.
Let me paste here my Traefik configuration for that component. Maybe it could be useful:
http:
routers:
debugging-oe-sl-form:
service: debugging-oe-sl-form-proxy
rule: "PathPrefix(`/sforms`)"
entryPoints:
- web
services:
debugging-oe-sl-form-proxy:
loadBalancer:
servers:
- url: "http://host.docker.internal:3000"

Resources