I was trying to dockerize my existing simple vue app , following on this tutorial from vue webpage https://v2.vuejs.org/v2/cookbook/dockerize-vuejs-app.html. I successfully created the image and the container. My problem is that when I edit my code like "hello world" in App.vue it will not automatically update or what they called this hot reload ? or should I migrate to the latest Vue so that it will work ?
docker run -it --name=mynicevue -p 8080:8080 mynicevue/app
FROM node:lts-alpine
# install simple http server for serving static content
RUN npm install -g http-server
# make the 'app' folder the current working directory
WORKDIR /app
# copy both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
# install project dependencies
RUN npm install
# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY . .
# build app for production with minification
# RUN npm run build
EXPOSE 8080
CMD [ "http-server", "serve" ]
EDIT:
Still no luck. I comment out the npm run build. I set up also vue.config.js and add this code
module.exports = {
devServer: {
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 300,
poll: 1000,
},
}
};
then I run the container like this
`docker run -it --name=mynicevue -v %cd%:/app -p 8080:8080 mynicevue/app
when the app launches to browser I get this error in terminal and the browser is whitescreen
"GET /" Error (404): "Not found"
Can someone help me please of my Dockerfile what is wrong or missing so that I can play my vue app using docker ?
Thank you in advance.
Okay I tried your project in my local and here's how you do it.
Dockerfile
FROM node:lts-alpine
# bind your app to the gateway IP
ENV HOST=0.0.0.0
# make the 'app' folder the current working directory
WORKDIR /app
# copy both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
# install project dependencies
RUN npm install
# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY . .
EXPOSE 8080
ENTRYPOINT [ "npm", "run", "dev" ]
Use this command to run the docker image after you build it:
docker run -v ${PWD}/src:/app/src -p 8080:8080 -d mynicevue/app
Explanation
It seems that Vue is expecting your app to be bound to your gateway IP when it is served from within a container. Hence ENV HOST=0.0.0.0 inside the Dockerfile.
You need to mount your src directory to the running container's /app/src directory so that the changes in your local filesystem directly reflects and visible in the container itself.
The way in Vue to watch for the file changes is using npm run dev, hence ENTRYPOINT [ "npm", "run", "dev" ] in Dockerfile
if you tried previous answers and still doesn't work , try adding watch:{usePolling: true} to vite.config.js file
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
host: true,
port: 4173,
watch: {
usePolling: true
}
}
})
Related
With the help from SO community I was finally able to dockerize my Sveltekit app and access it from the browser (this was an issue initially). So far so good, but now every time I perform a code change I need to re-build and redeploy my container which obviously is not acceptable. Hot reload is not working, I've been trying multiple things I've found online but none of them have worked so far.
Here's my Dockerfile:
FROM node:19-alpine
# Set the Node environment to development to ensure all packages are installed
ENV NODE_ENV development
# Change our current working directory
WORKDIR /app
# Copy over `package.json` and lock files to optimize the build process
COPY package.json package-lock.json ./
# Install Node modules
RUN npm install
# Copy over rest of the project files
COPY . .
# Perhaps we need to build it for production, but apparently is not needed to run dev script.
# RUN npm run build
# Expose port 3000 for the SvelteKit app and 24678 for Vite's HMR
EXPOSE 3333
EXPOSE 8080
EXPOSE 24678
CMD ["npm", "run", "dev"]
My docker-compose:
version: "3.9"
services:
dmc-web:
build:
context: .
dockerfile: Dockerfile
container_name: dmc-web
restart: always
ports:
- "3000:3000"
- "3010:3010"
- "8080:8080"
- "5050:5050"
- "24678:24678"
volumes:
- ./:/var/www/html
the scripts from my package.json:
"scripts": {
"dev": "vite dev --host 0.0.0.0",
"build": "vite build",
"preview": "vite preview",
"test": "playwright test",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
and my vite.config.js:
import { sveltekit } from '#sveltejs/kit/vite';
import {defineConfig} from "vite";
export default defineConfig({
plugins: [sveltekit()],
server: {
watch: {
usePolling: true,
},
host: true, // needed for the DC port mapping to work
strictPort: true,
port: 8080,
}
});
any idea what am I missing? I can reach my app at http://localhost:8080 but cannot get to reload the app when a code change happens.
Thanks.
Solution
The workspace in question does not work simply because it does not bind-mount the source directory. Other than that, it has no problem whatsoever.
Here's working code at my github:
https://github.com/rabelais88/stackoverflow-answers/tree/main/74680419-svelte-docker-HMR
1. Proper bind mount in docker-compose
The docker-compose.yaml from the question only mounts the result of previous build, not the current source files.
# 🚨wrong
volumes:
- ./:/var/www/html
# ✅answer
volumes:
# it avoids mounting the workspace root
# because it may cause OS specific node_modules folder
# or build folder(.svelte-kit) to be mounted.
# they conflict with the temporary results from docker space.
# this is why many mono repos utilize ./src folder
- ./src:/home/node/app/src
- ./static:/home/node/app/static
- ./vite.config.js:/home/node/app/vite.config.js
- ./tsconfig.json:/home/node/app/tsconfig.json
- ./svelte.config.js:/home/node/app/svelte.config.js
2. dockerfile should not include file copy and command
dockerfile does not always have to include command. it is necessary when 1)the result has to be preserved 2)the process lifecycle is critical to image. In this case 1)the result is not quite certain because the source may not be complete at the moment of booting, 2) the process lifecycle is not really important because the user may manually execute or close the container. The local development environment for VSCode + Docker, a.k.a VSCode devcontainer, also uses sleep infinity command for this reason.
As mentioned above, the code cannot be copied to docker space because it would conflict with bind-mounted files. To avoid both files collide, just remove COPY and CMD command from dockerfile and add more commands at docker-compose.yaml
# dockerfile
# 🚨wrong
COPY package.json package-lock.json ./
RUN npm install
COPY . .
# ...
CMD ["npm", "run", "dev"]
# ✅answer
COPY package*.json ./
RUN npm install
# comment out COPY and CMD
# COPY . .
# ...
# CMD ["npm", "run", "dev"]
and add command to docker-compose
# docker-compose.yaml
services:
svelte:
# ...
command: npm dev
and rest of configs in the question are not necessary. you can check this out from my working demo at Github
Edit
I just did this, but when running it I'm getting Error: Cannot find module '/app/npm dev'.
the answer uses arbitrary settings. the volumes and CMD may has to be changed accordingly.
i.e.)
# docker-compose.yaml
volumes:
- ./src:/$YOUR_APP_DIR/src
- ./static:/$YOUR_APP_DIR/static
# ...
I've used /home/node/app as WORKDIR because /home/node is used as main WORKDIR for official node docker image. However, it is not necessary to use the same folder. If you're going to use /home/node/app, make sure create the folder before use.
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
Why are you using docker for local development? Check this https://stackoverflow.com/a/70159286/3957754
Nodejs works very well even on windows, so my advice is to develop directly in the host with a simple nodejs installation. Your hot reload should work.
Docker is for your test, staging or production servers in which you don't want a hot-reload because reals users are using your web. Hot reload is only for local development.
container process
When the docker starts, is linked to a live and foreground process. If this process ends or is restarted, the entire container will crash. Check this https://stackoverflow.com/a/68593731/3957754
That's why docker goal is not related to hot-reload at source code level
anyway
Anyway, if you have a machine in which to have the workspace (nodejs, git, etc) is so complex, you could use docker with nodejs hot reload following these steps:
Don't use Dockerfile, use directly docker run ubuntu .... You are working with nodejs not with c#, php or similar follies
At the root of your workspace (package.json) execute this
docker run -p 8080:8080 -v $(pwd):/src node:19-alpine bash
The previous sentence will create a container not linked to a tcp process. So you will have new sub-shell, with nodejs 19 and alpine ready to use
Execute the classic
cd /src
npm install
npm run dev
If your app works fine, the hot reload should work. If don't work, try without docker and share us the result
I'm trying to figure why Nodemon is not restarting from within docker when passing in an environment variable. It worked previously when I was not trying pass in an env variable and instead in my Dockerfile the final command was CMD ["npm", "run", "devNoClient"]
I can see Nodemon launching in the terminal but doesn't restart the server when I update a file.
Makefile
node_dev:
echo 'Starting Node dev server in Docker Container'
docker build -t node_dev .
docker run -it --env-file variables.env -p 8080:8080 node_dev
Dockerfile
WORKDIR /chord-app
# copy package.json into the container
COPY package.json /chord-app/
# install dependencies
RUN npm install
# Copy the current directory contents into the container at /chord-app
COPY . /chord-app/
# Make port 8080 available to the world outside this container
EXPOSE 8080
# Env is required to persist variable into built image.
# Docker run can now accept variable and it will be assigned here.
# default is run in dev mode
ENV run_mode_env=devNoClient
# Run the app when the container launches
# Due to variable, CMD syntax must change for this to work https://stackoverflow.com/a/40454758
CMD npm run $run_mode_env
package.json
"scripts": {
"devNoClient": "nodemon --exec babel-node src/server/start.js",
},
I realized it was not working because I don't have any binding volumes to my local machine when starting my docker image. So the container does not what files on my machine to watch for saves so it can restart the server with nodemon.
I created a simple VueJS app with a very basic configuration. I used the webpack configuration to do this.
vue init webpack app
I build this simple Dockerfile
FROM node:lts-alpine
# install simple http server for serving static content
RUN npm install -g http-server
# make the 'app' folder the current working directory
WORKDIR /app
# copy both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
# install project dependencies
RUN npm install
# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY . .
# build app for production with minification
RUN npm run build
EXPOSE 3838
CMD [ "http-server", "dist" ]
This app should run of a plattform which only listens to port 3838. Changing the Dockerfile to EXPOSE 3838 did not work unfortunately.
sudo docker run -it -p 3838:3838 vuetest
Starting up http-server, serving dist
Available on:
http://127.0.0.1:8080
The container runs, but stil on 8080.
I´m quite unfamiliar with both VueJS and deploying, so can anyone help me? I guess the configuration to listen to 8080 might be set in a different file and the Dockerfile ignores it.
Your application server runs by default on 8080
https://www.npmjs.com/package/http-server
Use flag -p 3838 to serve on that port.
Docker is doing its job correctly, adjust in your CMD
CMD [ "http-server", "-p 3838", "dist" ]
You can try just use the port 8080 of the continer and map it to port 3838 of your host.
#Dockerfile: delete the line -> Expose 3838
#Command line : $ sudo docker run -it -p 3838:8080 vuetest
This is an option not to add more lines to the Dockerfile.
Bye
QUESTION: (edited: solution is added at the end of this post)
I have VueJS project (developed in webpack), which I want to docker-size.
My Dockerfile looks like:
FROM node:8.11.1 as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["npm", "run", "dev"]
which is basically following the flow from this post.
I also have a .dockerignore file, where I copied the same files from my .gitignore and it looks like:
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
.git/
I have created a docker image with the command:
docker build -t test/my-image-name .
and then run it into a container with the command:
docker run -it -p 8080:8080 --rm --name my-container-name test/my-image-name
as a result of this last command, I got the same output in the terminal (which is normally showing in cases of debugging with webpack / vuejs) as when I run the app locally:
BUT: at the end, in the browser window the app is not loaded
If I run the commands docker images and docker ps I can see that the image and the container are there, and while creating them, I did not got any error messages.
I found this post and had a few tries for changing the Dockerfile as:
Option 1
FROM node:8.11.1 as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
ENTRYPOINT ["ng", "serve", "-H", "0.0.0.0"]
Option 2
FROM node:8.11.1 as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ENTRYPOINT ["ng", "serve", "-H", "0.0.0.0"]
EXPOSE 8080
CMD ["npm", "run", "dev"]
But it seems none of them is working.
btw. my package.json file looks like:
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js"
}
So I'm wondering: how to make the app to be opened in the browser from the docker image?
SOLUTION: not, sure if this was the reason for the fix, but I did two things. As mentioned, I'm working with the VueJS and webpack, so inside of the file named config/index.js, which initially looked like:
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // <---- this one
port: 8080,
I changed the host property from 'localhost' into '0.0.0.0', removed the EXPOSE 8080 line from the Dockerfile (the initial Docker file from my question above) since I noticed that the port from the config file is used by default and also restarted the installed Docker tool on my local machine.
I have a project developed on nuxt js. Now I want to employ it with docker. But for some reason, I need build it on my local machine of mac os. It would be better to run npm install on local machine. And then employing it on linux server of production environment. Can this task be done?
Sure can be. Build your project normally (via npm install), then, inside your project directory, write a Dockerfile like this:
FROM node:7.8.0-alpine
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
RUN apk update && apk upgrade && apk add git
# Copy your already built project files inside image
COPY . .
ENV HOST 0.0.0.0
EXPOSE 3000
# start command
CMD [ "npm", "start" ]
Make sure your Dockerfile is in the project's root directory where you'd normally run npm start.
Then, in order to create a image with your project, just do:
$ docker build -t myapp .
and run it with:
$ docker run -it -p 3000:3000 myapp