Dockerized Vue app loads normally to the browser, when applying changes to the code are not reflected without refresh.
Dockerfile
FROM node:14-alpine
# make the 'app' folder the current working directory
WORKDIR /app
# copy 'package.json'
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
CMD ["npm", "run", "serve"]
docker-compose.yml
version: '3.9'
services:
frontend:
container_name: 'frontend'
build: ./
stdin_open: true
tty: true
ports:
- '8080:8080'
volumes:
- ./:/app
- /app/node_modules
environment:
- HOST=0.0.0.0
- CHOKIDAR_USEPOLLING=true
package.json
{
"name": "project",
"version": "1.6.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
},
"dependencies": {
"vue": "^2.6.12",
"vue-axios": "^3.2.2",
"vuetify": "2.3.18",
"vuex": "^3.6.0",
},
"devDependencies": {
"#vue/cli-plugin-babel": "^4.5.10",
"#vue/cli-plugin-eslint": "^4.5.11",
"#vue/cli-plugin-router": "^4.5.10",
"#vue/cli-plugin-unit-jest": "^4.5.10",
"#vue/cli-plugin-vuex": "^4.5.10",
"#vue/cli-service": "^4.5.10",
"#vue/eslint-config-prettier": "^6.0.0",
"#vue/test-utils": "1.1.2",
"babel-eslint": "^10.1.0",
"node-sass": "^5.0.0",
"sass": "^1.32.4",
"sass-loader": "^10.1.1",
"vuetify-loader": "^1.6.0",
"webpack": "^4.46.0"
}
}
When I'm running the project locally, the hot reload works great!
Any idea what might be the issue on the docker?
EDIT Since this is a docker for development purposes, I have tried as well to remove the COPY . . without result.
After many days I managed to add hot reload by adding in the webpack configuration file this config:
devServer: {
public: '0.0.0.0:8080'
}
After digging to the official vue js repo, specifically to serve.js file found the public option which:
specify the public network URL for the HMR client
If you do not want to edit your webpack config, you can do this directly from docker-compose file in the command:
command: npm run serve -- --public 0.0.0.0:8080
The issue can be also in your vue.config.js file.
module.exports = defineConfig({
configureWebpack: {
entry: "./src/main.js",
devServer: {
hot: true,
},
watch: true,
watchOptions: {
ignored: /node_modules/,
poll: 1000,
},
},
transpileDependencies: true,
});
Your template looks very close to this Docker Vue Hot-Reload template that works fine.
The only difference is the HOST=0.0.0.0 is set inside Dockerfile in the mentioned template. Maybe doing a fresh build would work.
PS: I created this template.
Related
I greatly appreciate your effort and the time to solve unresponsive hot-reload function when trying to run Vue.js app on Docker container using Docker engine on Windows 10 while WSL2 active, please take a look at below configurations:
Vue.Setup.Dockerfile
FROM node:17-alpine
EXPOSE 8080
WORKDIR /app/frontend
RUN npm --force install -g #vue/cli#4.5.15
COPY /frontend /app/frontend
ENV PATH /app/frontend/node_modules/.bin:$PATH
CMD [ "npm", "run", "serve" ]
docker-compose.yml
version: "3.8"
services:
vue:
build:
context: .
dockerfile: dockerfiles/Vue.Setup.Dockerfile
restart: always
ports:
- "127.0.0.1:8080:8080"
container_name: vue_ui
volumes:
- ./frontend/:/app/frontend/
- /app/frontend/node_modules
environment:
- CHOKIDAR_USEPOLLING=true
vue.config.js
module.exports = {
publicPath:
process.env.NODE_ENV === "production"
? "/static/dist/"
: "http://127.0.0.1:8080",
pages: {
index: {
entry: 'src/main.js',
template: 'public/index.html',
filename: 'index.html',
title: 'QuestionTime',
chunks: ['chunk-vendors', 'chunk-common', 'index']
},
},
// Webpack configuration
devServer: {
host: "0.0.0.0",
port: "8080",
hot: true,
headers: {"Access-Control-Allow-Origin": "*"},
devMiddleware: {
publicPath: "http://127.0.0.1:8080",
writeToDisk: (filePath) => filePath.endsWith("index.html"),
},
static: {
watch: {
ignored: "/node_modules/",
usePolling: true,
},
},
client: {
webSocketURL: {
/* You need to config this option, otherwise the below error will occur
in your browser console when trying to connect to development server
from another Docker container:
WebSocket connection to 'ws://127.0.0.1:<port-number>/ws' failed
*/
hostname: "0.0.0.0",
pathname: "/ws",
port: 8080,
},
},
},
};
Note: When run the command:
docker-compose up
The below message will show:
It seems you are running Vue CLI inside a container.
Since you are using a non-root publicPath, the hot-reload socket
will not be able to infer the correct URL to connect. You should
explicitly specify the URL via devServer.public.
Access the dev server via http://localhost:<your container's
external mapped port>
FYI: the option:
devServer.public
is no longer available in Vue/cli#4 or later versions.
WORKAROUND
solution
Thanks,
My problem is as follows.
I made a project with Next.js. My project works fine on Local, Local Docker, Heroku and Vercel. However, I have a problem when I go to production environment and publish Docker under the domain. When the address is entered from the browser, the page corresponding to the Router gives 404. But when I navigate through the menu, I don't have a problem. In other words, when the URL is entered directly, it does not render. How can i solve this problem. Domain for those who want to review. Original URL: https://beta.ardictech.com/ and this is Vercel URL: https://ardic-web.vercel.app/
For example, it gives 404 when directly entered with the URL, but when you click on the logo in the upper left and go to the "/" address, the page can be rendered. Or, the pages are rendered while navigating the menu, but if you enter the same address directly or press F5, it does not render.
next.config.js
module.exports = {
webpackDevMiddleware: (config) => {
config.watchOptions = {
polls: 1000,
aggregateTimeout: 300,
};
return config;
},
async headers() {
return [
{
// matching all API routes
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
{
key: "Access-Control-Allow-Methods",
value: "GET,OPTIONS,PATCH,DELETE,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value:
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
},
],
},
];
},
trailingSlash: true,
reactStrictMode: true,
generateEtags: false,
i18n: {
locales: ["en", "tr"],
defaultLocale: "en",
localeDetection: false,
},
env: {
VERSION: process.env.VERSION,
MODE: process.env.MODE,
APP_NAME: process.env.APP_NAME,
HOST: process.env.HOST,
BASE_URL: process.env.BASE_URL,
HOSTNAME: process.env.HOSTNAME,
PORT: process.env.PORT,
GA_TRACKING_ID: process.env.GA_TRACKING_ID,
},
generateBuildId: async() => {
return new Date().toDateString();
},
eslint: {
ignoreDuringBuilds: false,
},
};
docker-compose.yml
version: "2"
services:
ui:
container_name: beta.ardictech.com
hostname: beta.ardictech.com
restart: always
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
volumes:
- ./:/app
- /app/node_modules
- /app/.next
env_file:
- .env
Dockerfile
FROM node:current-alpine as base
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
FROM base AS build
ENV NODE_ENV=production
WORKDIR /build
COPY --from=base /app ./
RUN npm run build
FROM node:current-alpine AS production
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /build/package*.json ./
COPY --from=build /build/.next ./.next
COPY --from=build /build/public ./public
RUN npm install
EXPOSE 3000
CMD npm run start
My problem is:
I made a simple web page with Next.js. I take some content from /pages/api/ endpoints with JSON format and show it in pages and components. Compiling locally (npm run dev or npm run start) is fine. When I run it on Docker on Windows 10, I don't have a problem again. And this is working on Heroku and Vercel. The point I'm having trouble with is: I gave the project to the Devops team and they ran it on Docker. They also directed a domain to this project. But the api endpoints are meaninglessly trying to access an ID URL. When I look from Chrome Devtools it looks like this:
http://013cfdde4910:3000/api/en/brands
I get the following errors as console message.
​Mixed Content: The page at 'https://beta..com/technologies' was loaded over HTTPS, but requested an insecure resource 'http://013cfdde4910:3000/api/en/menu'. This request has been blocked; the content must be served over HTTPS.
Actually it should be http://localhost:3000/api/en/brands. I don't understand where 013cfdde4910 here is coming from and why.
I checked to see if it is among the codes. I looked at the Source of the project that is live, that is, published by the Devops team, from Google Devtools.
_next/static > chunk > pages > _app-eac17e226e00cc01a313.js
When I searched here, I found 013cfdde4910 String in 3 places. Why did it come here when it was built?
For example, the minified code continues as follows.
.... return(0,u.useEffect)((function(){fetch("".concat("http://013cfdde4910:3000","/api/").concat(t.locale,"/) brands")).....
I can see it as localhost in my local build and when I publish it in Windows 10 Docker and look there. So what is causing the localhost -> 013cfdde4910 conversion and how can I solve it?
Dockerfile I use:
FROM node:current-alpine as base
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
FROM base AS build
ENV NODE_ENV=production
WORKDIR /build
COPY --from=base /app ./
RUN npm run build
FROM node:current-alpine AS production
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /build/package*.json ./
COPY --from=build /build/.next ./.next
COPY --from=build /build/public ./public
RUN npm install
EXPOSE 3000
CMD npm run start
I use docker-compose.yml
version: "3"
services:
ui:
container_name: web
restart: always
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
volumes:
- ./:/app
- /app/node_modules
- /app/.next
env_file:
- .env
And this is next.config.js
module.exports = {
webpackDevMiddleware: (config) => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
};
return config;
},
async headers() {
return [
{
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
{
key: "Access-Control-Allow-Methods",
value: "GET,OPTIONS,PATCH,DELETE,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value:
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
},
],
},
];
},
reactStrictMode: true,
generateEtags: false,
i18n: {
locales: ["en", "tr"],
defaultLocale: "en",
localeDetection: false,
},
env: {
VERSION: process.env.VERSION,
MODE: process.env.MODE,
APP_NAME: process.env.APP_NAME,
HOST: process.env.HOST,
HOSTNAME: process.env.HOSTNAME,
PORT: process.env.PORT,
GA_TRACKING_ID: process.env.GA_TRACKING_ID,
},
generateBuildId: async () => {
return new Date().toDateString();
},
eslint: {
ignoreDuringBuilds: false,
},
};
Thanks for posting the config, it appears the hostname is grabbed as the docker container ID - You do not post the actual fetch code but my guess is - this environment variable is used.
`HOSTNAME: process.env.HOSTNAME`
It is either passed as a environment variable or interpreted to be the container ID, you need a way to create a domain:3000/api/brands which could be part of the Docker deploy, maybe a nginx proxy.
I just Dockerised my first NuxtJS app using Docker and Docker-compose.
All run smoothly except that when I make a change on my local, the running docker does not reflect the changes I've made.
How do I configure the Docker container to listen to local changes in my code? Thanks:
Dockerfile:
# Dockerfile
FROM node:11.13.0-alpine
# create destination directory
RUN mkdir /myapp
WORKDIR /myapp
# Add current directory code to working directory
ADD . /myapp/
# update and install dependency
RUN apk update && apk upgrade
RUN apk add git
RUN npm install
EXPOSE 3000
ENV NUXT_HOST=0.0.0.0
ENV NUXT_PORT=3000
CMD gunicorn myapp.wsgi:application --bind $NUXT_HOST:$NUXT_PORT
Docker-compose:
version: "3"
services:
nuxt:
build: .
command: npm run dev
ports:
- "3000:3000"
environment:
- NUXT_HOST=0.0.0.0
- NUXT_PORT=3000
volumes:
- /myapp/
Nuxt.config.js:
export default {
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
title: 'myapp',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
// Global CSS (https://go.nuxtjs.dev/config-css)
css: [],
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
plugins: [],
// Auto import components (https://go.nuxtjs.dev/config-components)
components: true,
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
buildModules: [
// https://go.nuxtjs.dev/eslint
'#nuxtjs/eslint-module',
// https://go.nuxtjs.dev/stylelint
'#nuxtjs/stylelint-module',
],
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
// https://go.nuxtjs.dev/buefy
'nuxt-buefy',
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'#nuxtjs/pwa',
// https://go.nuxtjs.dev/content
'#nuxt/content',
],
// Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: {},
// Content module configuration (https://go.nuxtjs.dev/config-content)
content: {},
// Build Configuration (https://go.nuxtjs.dev/config-build)
build: {},
watchers: {
webpack: {
poll: true
}
},
}
I am relatively new to nextjs and react space of development, trying my hand over this, please pardon if anything straight forward and i am not seeing it.
So i am trying to call some API which gives some data which i want to render on UI. So far on local it was giving corrs issue so i have added express js middleware to bypass this issue.
Now i want to deploy this app on docker using Dockerfile. So i have got things right and UI compiles successfully but middleware API calls are failing. Below is the Dockerfile, docker-compose file i am using to start the app.
client Dockerfile:
FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
EXPOSE 3000
CMD [ "npm" , "run", "dev" ]
server Dockerfile
FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
EXPOSE 5000
CMD [ "npm", "run" , "start" ]
docker-compose file
version: "3"
services:
frontend:
container_name: awesome_web
build:
context: ./
dockerfile: Dockerfile
image: apaliwal/awesome_web
ports:
- "3000:3000"
volumes:
- ./:/usr/src/app
backend:
container_name: awesome_server
build:
context: ./server
dockerfile: Dockerfile
image: apaliwal/awesome_server
ports:
- "8080:8080"
volumes:
- ./server:/usr/src/app
client package.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_TLS_REJECT_UNAUTHORIZED='0' node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"node-fetch": "^2.6.0"
}
}
client package.json
{
"name": "project_name",
"version": "1.0.0",
"main": "pages/index.js",
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
[dependecies]
...
...
...
server.js
const express = require('express');
const http = require('http');
const fetch = require('node-fetch');
const app = express();
const server = http.createServer(app);
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
next();
});
app.get('/issues/:projectID', (req, res) => {
fetch(`[url]`, {
headers: [auth],
compress: false
})
.then(async (response) => {
console.log(response.status);
if(response.status >= 200 && response.status < 400) {
const jsonResponse = await response.text();
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(jsonResponse);
}
})
.catch((err) => {
console.error(err);
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end("Error occurred! Data not found/internal server error");
});
})
server.listen(8080, '127.0.0.1' , err => console.log( err || "Your server is listening on "+'127.0.0.1'+" port "+'8080'));
Please help with this, tried many things exposing port to 8080.
docker-compose up --build does work below are the console logs for it as well, it just in network logs the getting:
(failed)net::ERR_SOCKET_NOT_CONNECTED