I built a QR Code generator and I want to dockerize it. The frontend of the app I built it with Vuetify, so it uses Vite and Vue3. Inside the frontend I have a .env file with the api url and the port the app should start on. The problem that I’m having is that when I pass the env variables through docker compose the frontend service doesn’t use the values from docker-compose but it uses the values from it’s own .env file.
My project structure looks like this:
qr-code-generator
|----frontend
| |----src
| |----Dockerfile
| |----.dockerignore
| |----.env # only has the frontend variables (VITE_API_URL, VITE_APP_PORT)
| |----...
|----backend # works fine
| |----src
| |----Dockerfile
| |----.dockerignore
| |----.env # only has the backend variables (PORT, MAX_CACHE_SIZE, CACHE_EXPIRATION_TIME)
| |----...
|----docker-compose.yml
|----.env
The variables for the backend work perfectly fine. They use the values that I pass from docker-compose.
For example, this is my docker-compose.yml (to run it I use docker-compose up -d
):
services:
backend:
container_name: backend
image: alflyingwhale/qr-code-generator-backend:1.0
volumes:
- ./qr-code-generator-backend/logs:/var/server/logs
ports:
- "${BACKEND_PORT}:${BACKEND_PORT}"
environment:
- PORT=${BACKEND_PORT}
- CACHE_EXPIRATION_TIME=${CACHE_EXPIRATION_TIME}
- MAX_CACHE_SIZE=${MAX_CACHE_SIZE}
env_file:
- .env
frontend:
container_name: frontend
image: alflyingwhale/qr-code-generator-frontend:1.0
ports:
- "${VITE_APP_PORT}:${VITE_APP_PORT}"
environment:
- VITE_APP_PORT=${VITE_APP_PORT}
- VITE_API_URL=${VITE_API_URL}
env_file:
- .env
And this is the Dockerfile of my frontend service:
# Use the official Node.js image
FROM node:20-alpine
# Create and change to the app directory
WORKDIR /usr/src/app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the application
RUN npm run build
# Expose the port the app runs on
EXPOSE 3000
# Start the application
CMD ["npm", "run", "preview", "--host", "0.0.0.0"]
The .env file that the docker-compose file uses looks like this:
VITE_APP_PORT=5000
VITE_API_URL=http://pedro2:8080/api/generate?
BACKEND_PORT=8080
CACHE_EXPIRATION_TIME=3600
MAX_CACHE_SIZE=100
And if I run docker exec -it {id} sh
and then use env
. I get the following result:
...
VITE_APP_PORT=5000
VITE_API_URL=http://pedro2:8080/api/generate?
Which means the variables are in the container. However, in my frontend image I have a .env file with the same variables but the following values:
VITE_APP_PORT=3000
VITE_API_URL=http://localhost:8080/api/generate?
In the frontend I’m accessing the variables like this: import.meta.env.VITE_API_URL
.
Now, when I do a console.log in the frontend, I get PORT=3000
and API_URL=http://localhost:8080/api/generate?
.
However, in the vite.config.mts file, I have this setup, and the app starts in the port that I setup in the docker-compose env variable:
export default defineConfig({
plugins: [
Vue({
template: { transformAssetUrls },
}),
// https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin#readme
Vuetify(),
Components(),
ViteFonts({
google: {
families: [{
name: 'Roboto',
styles: 'wght@100;300;400;500;700;900',
}],
},
}),
],
define: { 'process.env': {} }, # Should I write the variables here?
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
extensions: [
'.js',
'.json',
'.jsx',
'.mjs',
'.ts',
'.tsx',
'.vue',
],
},
server: {
port: parseInt(process.env.VITE_APP_PORT), # This properly sets it to port 5000 from docker-compose
},
preview: {
port: parseInt(process.env.VITE_APP_PORT), # This properly sets it to port 5000 from docker-compose
},
})
So the problem that I’m having is with the VITE_API_URL variable.
The app works with the url “http://localhost:8080/api/generate?” however if I want to deploy it on kubernetes I can’t use localhost, so I need to pass the url through an env variable
I’ve been trying to solve this issue for a while now,
Should I include ENV variables in the Dockerfile?
Should I remove the .env file from the frontend service with .dockerignore so it only has the env variables from docker-compose?
Things I’ve tried:
-
I tried removing the .env file from the frontend, leaving only the env variables from the frontend, however then when I use console.log in the frontend or when I try to call my API the variables return undefined.
-
I’m only really having trouble with the VITE_API_URL variable, the ones for the backend work correctly and the VITE_APP_PORT variable works fine. This is my .env file:
VITE_APP_PORT=5000
VITE_API_URL=http://pedro2:8080/api/generate?
BACKEND_PORT=2000
CACHE_EXPIRATION_TIME=3600
MAX_CACHE_SIZE=100
Which leads me to believe that vite.config.mts is receiving the correct values from docker-compose, but when I try to use the env variables inside a component like this: import.meta.env.VITE_API_URL
then it only uses the values from the .env file inside the frontend and no the ones from docker-compose.
- If I run
docker exec -it {frontend container id} sh
and then useenv
. I get the correct values from the docker-compose. However if I do a console.log inside a component of the vue app, I get the values from the .env file inside of the frontend directory.
user26346048 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.