I want to either pass Vue environment variables to my Vue client with docker compose or tell my client to use a diffenret .env file.
The problem is i cannot access the VUE_APP_ROOT_URL variable nor can I switch between the .env files.
services:
client_test:
build: ./papasmuenzenfrontend/.
container_name: vue_test
restart: always
environment:
- NODE_ENV:test
- VUE_APP_ROOT_URL=localhost:50598
ports:
- '8081:8080'
Dockerfile
FROM node:lts-alpine
RUN npm install -g http-server
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]
I figured it out how to do it:
In my package.json I have the following configuration
"test_build": "vue-cli-service build --mode test",
"production": "vue-cli-service build --mode production",
"development": "vue-cli-service build --mode development"
docker-compose file:
client_test:
args:
- myenv=development
docker file:
ARG myenv RUN npm run $myenv
When building the project the $myenv gets passed to the build in the package.json where it then switches to the different environment files.
Related
I have dockerized the sveltekit app and my issue is that when I am running container
and when I make changes in frontend UI I am able to see them only for 1 second and then
my frontend is looking like before any changes.
I think that problem is about caching in sveltekit.
My Dockerfile:
FROM node:16
WORKDIR /test-app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
ENV PORT 3000
EXPOSE 3000
EXPOSE 24678
CMD ["node", "build"]
My docker-compose.yaml file:
version: '3'
services:
svelte-test:
image: sveltekit-test:node
volumes:
- ./:/test-app/
ports:
- 3000:3000
- 24678:24678
- 5173:5173
tty: true
stdin_open: true
Port 3000 is for sveltekit, 5173 is for sveltekit but in Docker and 24678 is for vite.
My folder structure is:
sveltekit-docker
test-app
-Dockerfile
-docker-compose.yaml
-package-lock.json
-package.json
-svelte.config.js
-tsconfig.json
-vite.config.js
-all sveltekit folders (src, node_modules, static, tests)
If you want to see the changes you need HMR (Hot module reloading) available in dev mode.
You also may need to rebuild esbuild. Try replacing the last line of your Dockerfile with
CMD npm rebuild esbuild && npm run dev -- --host
I created a repo if it helps.
To use it:
docker build --tag sveltekit-test .
docker-compose up
I am having an issue with my docker-compose configuration file. My goal is to run a Next.js app with a docker-compose file and enable hot reload.
Running the Next.js app from its Dockerfile works but hot reload does not work.
Running the Next.js app from the docker-compose file triggers an error: /bin/sh: next: not found and I was not able to figure what's wrong...
Dockerfile: (taken from Next.js' documentation website)
[Notice it's a multistage build however, I am only referencing the builder stage in the docker-compose file.]
# Install dependencies only when needed
FROM node:18-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
# Rebuild the source code only when needed
FROM node:18-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:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
# 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 3001
ENV PORT 3001
CMD ["node", "server.js"]
docker-compose.yml:
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${POSTGRESQL_PASSWORD}
backend:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment:
DATABASE_USERNAME: ${MYAPP_DATABASE_USERNAME}
DATABASE_PASSWORD: ${POSTGRESQL_PASSWORD}
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
target: builder
command: yarn dev
volumes:
- ./frontend:/app
expose:
- "3001"
ports:
- "3001:3001"
depends_on:
- backend
environment:
FRONTEND_BUILD: ${FRONTEND_BUILD}
PORT: 3001
package.json:
{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "^18.1.0",
"react-dom": "^18.1.0"
}
}
When calling yarn dev from docker-compose.yml it actually calls next dev and that's when it triggers the error /bin/sh: next: not found. However, running the container straight from the Dockerfile works and does not lead to this error.
[Update]:
If I remove the volume attribute from my docker-compse.yml file, I don't get the /bin/sh: next: not found error and the container runs however, I now don't get the hot reload feature I am looking for. Any idea why the volume is messing up with the /bin/sh next command?
This is happening because your local filesystem is being mounted over what is in the docker container. Your docker container does build the node modules in the builder stage, but I'm guessing you don't have the node modules available in your local file system.
To see if this is what is happening, on your local file system, you can do a yarn install. Then try running your container via docker again. I'm predicting that this will work, as yarn will have installed next locally, and it is actually your local file system's node modules that will be run in the docker container.
One way to fix this is to volume mount everything except the node modules folder. Details on how to do that: Add a volume to Docker, but exclude a sub-folder
So in your case, I believe you can add a line to your compose file:
frontend:
...
volumes:
- ./frontend:/app
- ./frontend/node_modules # <-- try adding this!
...
That should allow the docker container's node_modules to not be overwritten by any volume mount.
I'm trying to build my React / NodeJS project using Docker and Gitlab CI.
When I build manually my images, I use .env file containing env vars, and everything is fine.
docker build --no-cache -f client/docker/local/Dockerfile . -t espace_client_client:local
docker build --no-cache -f server/docker/local/Dockerfile . -t espace_client_api:local
But when deploying with Gitlab, I can build successfully the image, but when I run it, env vars are empty in the client.
Here is my gitlab CI:
image: node:10.15
variables:
REGISTRY_PACKAGE_CLIENT_NAME: registry.gitlab.com/company/espace_client/client
REGISTRY_PACKAGE_API_NAME: registry.gitlab.com/company/espace_client/api
REGISTRY_URL: https://registry.gitlab.com
DOCKER_DRIVER: overlay
# Client Side
REACT_APP_API_URL: https://api.espace-client.company.fr
REACT_APP_DB_NAME: company
REACT_APP_INFLUX: https://influx-prod.company.fr
REACT_APP_INFLUX_LOGIN: admin
REACT_APP_HOUR_GMT: 2
stages:
- publish
docker-push-client:
stage: publish
before_script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $REGISTRY_URL
image: docker:stable
services:
- docker:dind
script:
- docker build --no-cache -f client/docker/prod/Dockerfile . -t $REGISTRY_PACKAGE_CLIENT_NAME:latest
- docker push $REGISTRY_PACKAGE_CLIENT_NAME:latest
Here is the Dockerfile for the client
FROM node:10.15-alpine
WORKDIR /app
COPY package*.json ./
ENV NODE_ENV production
RUN npm -g install serve && npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD [ "serve", "build", "-l", "3000" ]
Why is there such a difference between the 2 process ?
According to your answer in comments, GitLab CI/CD environment variables doesn't solve your issue. Gitlab CI environment is actual only in context of GitLab Runner that builds and|or deploys your app.
So, if you are going to propagate Env vars to the app, there are several ways to deliver variables from .gitlab-cy.ymlto your app:
ENV instruction Dockerfile
E.g.
FROM node:10.15-alpine
WORKDIR /app
COPY package*.json ./
ENV NODE_ENV production
ENV REACT_APP_API_URL: https://api.espace-client.company.fr
ENV REACT_APP_DB_NAME: company
ENV REACT_APP_INFLUX: https://influx-prod.company.fr
ENV REACT_APP_INFLUX_LOGIN: admin
ENV REACT_APP_HOUR_GMT: 2
RUN npm -g install serve && npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD [ "serve", "build", "-l", "3000" ]
docker-compose environment directive
web:
environment:
- NODE_ENV=production
- REACT_APP_API_URL=https://api.espace-client.company.fr
- REACT_APP_DB_NAME=company
- REACT_APP_INFLUX=https://influx-prod.company.fr
- REACT_APP_INFLUX_LOGIN=admin
- REACT_APP_HOUR_GMT=2
Docker run -e
(Not your case, just for information)
docker -e REACT_APP_DB_NAME="company"
P.S. Try Gitlab CI variables
There is convenient way to store variables outside of your code: Custom environment variables
You can set them up easily from the UI. That can be very powerful as it can be used for scripting without the need to specify the value itself.
(source: gitlab.com)
I'm currently developing a CRA app using Docker. Everything is fine in development. However, when I want to create the production build (I'm using a separate docker-compose.yml file for the production build), it keeps telling me it cannot find the files.
I keep getting Cannot find module: 'lorem.scss'. Make sure this package is installed. It happens right after yarn run build in the building environment.
My Dockerfile:
##############################
# Base Image
##############################
# Ger current Node Alpine Linux image.
FROM node:alpine AS base
# Set working directory.
WORKDIR /home/node/app/
# Copy project content.
COPY package.json ./
##############################
# Development Image
##############################
# Development environment.
FROM base AS development
# Run yarn to install.
RUN yarn
# Copy source code.
COPY ./src/ /home/node/app/src/
COPY ./public/ /home/node/app/public/
# Copy Storybook files.
COPY ./stories/ /home/node/app/stories/
COPY ./.storybook/ /home/node/app/.storybook/
# Run the app.
CMD [ "yarn", "run", "dev" ]
##############################
# Building Environment
##############################
# Building environment set.
FROM base AS builder
# Run yarn to install.
RUN yarn
# Copy source code.
COPY ./src/ /home/node/app/src/
COPY ./public/ /home/node/app/public/
# Run the build.
RUN yarn run build
##############################
# Production Image
##############################
FROM nginx:alpine AS production
# Copy source code.
COPY --from=builder /home/node/app/build /usr/share/nginx/html
# Copy nginx configuration template.
COPY ./nginx.template /etc/nginx/conf.d/
# Set permissions so nginx can serve it.
RUN chown nginx.nginx /usr/share/nginx/html/ -R
My docker-compose.production.yml file:
version: "3.7"
services:
##############################
# Front-End Container
##############################
frontend:
container_name: ${PROJECT_NAME}_frontend
build:
context: ./frontend/
target: production
restart: always
environment:
- PROJECT_NAME=${PROJECT_NAME}
- NODE_PATH=${REACT_NODE_PATH}
- NODE_PORT=${NODE_PORT}
- SASS_PATH=${SASS_PATH}
- NODE_ENV=production
- DOCKER_BUILDKIT=1
command: /bin/ash -c "envsubst < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
expose:
- "80"
ports:
- "80:80"
My variables in the .env file are as follows:
SASS_PATH=node_modules:src/components:src/assets/styles:src/assets/fonts
REACT_NODE_PATH=src/assets/styles/pages:src/assets/images
Your problem is that you are expecting the environment files to be passed to your docker build. While there is nothing like that happening. The environment that you define is only passed to image at run-time as run-time environment.
So you need to either use build arguments or set these environments in your image
Passing environments
##############################
# Building Environment
##############################
# Building environment set.
FROM base AS builder
# Run yarn to install.
RUN yarn
# Copy source code.
COPY ./src/ /home/node/app/src/
COPY ./public/ /home/node/app/public/
# Run the build.
ENV SASS_PATH=node_modules:src/components:src/assets/styles:src/assets/fonts REACT_NODE_PATH=src/assets/styles/pages:src/assets/images
RUN yarn run build
Or you need to use build args
##############################
# Building Environment
##############################
# Building environment set.
FROM base AS builder
# Run yarn to install.
RUN yarn
# Copy source code.
COPY ./src/ /home/node/app/src/
COPY ./public/ /home/node/app/public/
# Run the build.
ARG SASS_PATH
ARG REACT_NODE_PATH
ENV SASS_PATH=${SASS_PATH}
ENV REACT_NODE_PATH=${REACT_NODE_PATH}
RUN yarn run build
And update your compose file like
version: "3.7"
services:
##############################
# Front-End Container
##############################
frontend:
container_name: ${PROJECT_NAME}_frontend
build:
context: ./frontend/
target: production
args:
- REACT_NODE_PATH=${REACT_NODE_PATH}
- SASS_PATH=${SASS_PATH}
restart: always
environment:
- PROJECT_NAME=${PROJECT_NAME}
- NODE_PATH=${REACT_NODE_PATH}
- NODE_PORT=${NODE_PORT}
- SASS_PATH=${SASS_PATH}
- NODE_ENV=production
- DOCKER_BUILDKIT=1
command: /bin/ash -c "envsubst < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
expose:
- "80"
ports:
- "80:80"
Your development layer contains
CMD [ "yarn", "run", "dev" ]
which means that an instance of the final image will run the dev script. You probably want to have something like
FROM base AS development
...
ENTRYPOINT [ "yarn", "run" ]
CMD [ "dev" ]
FROM nginx:alpine AS production
...
CMD [ "prod" ]
The underlying problem is that you try to stuff both a development image and a production image into the same Dockerfile.
Multistage Dockerfiles are usually used to avoid build utilities taking up space (and enlarging the attack surface) of the production image. Also, an intermediate layer that runs all the unit/acceptance tests can make sure that no image is produced if the test fails.
If you need a separate development image, see "Stop at a specific build stage" section of multistage build documentaiton.
I have a docker-compose.yml file comprising of two services (both based on a DockerFile). I have build the images once (using command: docker-compose build) and they were up and running once I ran this command (docker-compose up).
I had to change the source code used for one of the services, however, when I rebuilt the images (docker-compose build), the code changes were not reflected once I ran the services (docker-compose up).
docker-compose.yml
version: '2'
services:
serviceOne:
build:
context: ./ServerOne
args:
PORT: 4000
ports:
- "4000:4000"
env_file:
- ./ServerOne/.env
environment:
- PORT=4000
serviceTwo:
build:
context: ./serviceTwo
args:
PORT: 3000
ports:
- "3000:3000"
env_file:
- ./serviceTwo/.env
environment:
- PORT=3000
- serviceOne_URL=http://serviceOne:4000/
depends_on:
- serviceOne
serviceOne/DockerFile
FROM node:8.10.0
RUN mkdir -p /app
WORKDIR /app
ADD package.json package-lock.json /app/
RUN npm install
COPY . /app/
RUN npm build
EXPOSE ${ACC_PORT}
CMD [ "npm", "start" ]
serviceTwo/DockerFile
FROM node:8.10.0
RUN mkdir -p /app
WORKDIR /app
ADD package.json package-lock.json /app/
RUN npm install
COPY . /app/
RUN npm build
EXPOSE ${ACC_PORT}
CMD [ "npm", "start" ]
Following is the output of the docker-compose when it is ran for the second time.
It is some how using the cached images again when COPY and npm build command are ran.
How could the DockerFile or docker-compose file be changed so that the new source code is deployed?
You can force the build to ignore the cache by adding on the --no-cache option to the docker-compose build