How to configure webpack hot reload to work inside Docker? - node.js

I'm working on a Symfony 4 project for months, and I want to Dockerize it.
I make everything work except Webpack, I use it to compile my .scss and .js files with the npm run watch or npm run dev command.
Actually webpack does not listen changes I do in a .scss or .js file for example.
Here is my config, I surely miss something in my files.
My docker-compose.yml :
version: '3.8'
services:
mysql:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
restart: on-failure
environment:
MYSQL_ROOT_PASSWORD: rootpassword
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: on-failure
depends_on:
- mysql
ports:
- '8004:80'
environment:
PMA_HOSTS: mysql
php:
build:
context: .
dockerfile: php/Dockerfile
volumes:
- '../.:/usr/src/app'
restart: on-failure
env_file:
- .env
nginx:
image: nginx:1.19.0-alpine
restart: on-failure
volumes:
- '../public:/usr/src/app'
- './nginx/default.conf:/etc/nginx/conf.d/default.conf:ro'
ports:
- '80:80'
depends_on:
- php
node:
build:
context: .
dockerfile: node/Dockerfile
volumes:
- '../.:/usr/src/app'
command: npm run watch
My Dockerfile for Node Image :
FROM node:12.10.0
RUN apt-get update && \
apt-get install -y \
curl
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
WORKDIR /usr/src/app
CMD ["npm", "run", "watch"]
My webpack.config.js :
var Encore = require('#symfony/webpack-encore');
var CopyWebpackPlugin = require('copy-webpack-plugin');
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
.setOutputPath('public/build/')
.setPublicPath('/build')
.addEntry('app', './assets/js/app.js')
.splitEntryChunks()
.disableSingleRuntimeChunk()
.enableSassLoader()
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
.enableVersioning(Encore.isProduction())
.configureBabel(() => {}, {
useBuiltIns: 'usage',
corejs: 3
})
.addPlugin(new CopyWebpackPlugin([
{ from: './assets/pictures', to: 'pictures' }
]))
;
module.exports = Encore.getWebpackConfig();
// module.exports = {
// mode: 'development',
// devServer: {
// port: 80,
// host: '0.0.0.0',
// disableHostCheck: true,
// watchOptions: {
// ignored: /node_modules/,
// poll: 1000,
// aggregateTimeout: 1000
// }
// }
// }
As you can see I already tried some thing in webpack.config.js, I saw many things about watchOptions but I didn't get it.
And here is my project's organisation :
project's organisation
I want to be able to launch my Docker with Webpack listening any change I do in real time.
Here is the command console after running docker-compose up:
console command docker-compose up
If you have some advise to improve my Docker environment, I take it all !
Thank you !

i just use this:
docker-compose.yml:
node:
image: node:16-alpine3.13
working_dir: /var/www/app
user: "$USERID"
volumes:
- .:/var/www/app
tty: true
and docker-compose exec node yarn watch
working as expected.

Okay i think i solved my issue,
I followed #Rufinus answer; i had to docker-compose up in a first console command, open a second console command and execute winpty docker-compose exec node yarn watch but for some reason i had issue with node-sass compatibility : i mounted my node_module (windows 10) folder into the container (Linux).
So i opened my node CLI container and execute npm rebuild node-sass to solve this and finally it worked !
But i don't know why, my current solution is to execute npm run watch on my local folders (like i used to do it before Dockerizing all my application) and it re-builds assets when i change .scss or .js file.

Related

Hot Reload HMR Webpack not working on Docker Container WSL2

To preface, I am new to Docker.
I created my own docker container for my local development environment for a project I am working on using Intertia.JS + Laravel Jetstream in Ubuntu on WSL 2.
I am having trouble getting the HMR Hot Reloading for webpack to work, when I run npm run hot - it also does not start a proxy server...
When I run docker-compose exec php npm run hot I get the following message:
> # hot /var/www/html
> cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-
dev-server.js --inline --hot --disable-host-check --
config=node_modules/laravel-mix/setup/webpack.config.js
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from http://localhost:8080/
ℹ 「wds」: Content not from webpack is served from /var/www/html/public
ℹ 「wds」: 404s will fallback to /index.html
DONE Compiled successfully in 27200ms
When I try to make a change to a vue template for example, the changes do not get reflected on the website running on Chrome (localhost:8080) - not even if I hard refresh the page. The changes are NEVER updated even though the compilation is successful every time.
I tried to play with my webpack config following other suggestions online, but to no avail.
For example adding hmrOptions and devServer options.
Here is my webpack.mix.js for reference:
const cssImport = require('postcss-import')
const cssNesting = require('postcss-nesting')
const mix = require('laravel-mix')
const path = require('path')
const purgecss = require('#fullhuman/postcss-purgecss')
const tailwindcss = require('tailwindcss')
mix.js('resources/js/app.js', 'public/js')
.postCss('resources/css/app.css', 'public/css/app.css')
.options({
hmrOptions: {
host: 'localhost',
port: '8080',
},
postCss: [
cssImport(),
cssNesting(),
tailwindcss('tailwind.config.js'),
...mix.inProduction() ? [
purgecss({
content: ['./resources/views/**/*.blade.php', './resources/js/**/*.vue'],
defaultExtractor: content => content.match(/[\w-/:.]+(?<!:)/g) || [],
whitelistPatternsChildren: [/nprogress/],
}),
] : [],
],
})
.webpackConfig({
mode: 'development',
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'#': path.resolve('resources/js'),
},
},
devServer: { // I have tried with & without this
proxy: {
host: '0.0.0.0',
port: 8080,
},
watchOptions:{
aggregateTimeout:200,
poll:5000,
},
},
})
if (mix.inProduction()) {
mix.version()
mix.sourceMaps()
}
Here is my docker-compose.yml
version: "3.7"
services:
php:
build:
args:
user: admin
uid: 1000
context: ./
dockerfile: Dockerfile
image: app
container_name: app-php
restart: unless-stopped
working_dir: /var/www/html
volumes:
- ./:/var/www/html
networks:
- app
mysql:
image: mysql:5.7
container_name: app-mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
- nodemodules:/node_modules
networks:
- app
nginx:
image: nginx:alpine
container_name: app-nginx
restart: unless-stopped
ports:
- 8080:80
volumes:
- ./:/var/www/html
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- app
links:
- php
depends_on:
- php
networks:
app:
driver: bridge
volumes:
nodemodules: {}
Here is my Dockerfile
FROM php:7.4-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN curl -sL https://deb.nodesource.com/setup_13.x | bash
RUN apt-get update && \
apt-get install -y -q --no-install-recommends \
nano apt-utils curl zip unzip default-mysql-client nodejs build-essential git \
libcurl4-gnutls-dev libmcrypt-dev libmagickwand-dev \
libwebp-dev libjpeg-dev libpng-dev libxpm-dev \
libonig-dev \
libxml2-dev \
libfreetype6-dev libaio-dev zlib1g-dev libzip-dev && \
echo 'umask 002' >> /root/.bashrc && \
apt-get clean
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www/html
USER $user
EXPOSE 8080
Let me know if you need more information. Thank you!
add following config in your docker config file
ENV CHOKIDAR_USEPOLLING=true
remove node_modules and re-install again

Why NextJS using Docker container did not reload after changed code for dev environment?

I'm trying to run the NextJS on a Docker container using Dockerfile and running via docker-compose, after I changed my code in a JS file (such as index.js) the Next server did not reload.
But when I've tried to run outside without using Docker (by executing the "npm run dev" command directly) the Next server did reload smoothly.
I've also tried to run the server by "nodemon" command (inside a container), it did not make it either.
Dockerfile:
FROM node:10.14.2-alpine
COPY . /home/next_app
WORKDIR /home/next_app
RUN npm install
docker-compose.yml:
version: "3.6"
services:
self_nextjs:
container_name: self_nextjs
build:
context: ./app
dockerfile: Dockerfile
ports:
- 3000:3000
volumes:
- ./app:/home/next_app
- /home/next_app/node_modules
networks:
- zen_frontend
restart: always
command: npm run dev
networks:
zen_frontend:
name: zen_frontend
driver: bridge
Any suggestions would be appreciated.
I had the same issue on Windows 10. I followed some of the instructions in this thread https://github.com/zeit/next.js/issues/6417. Basically, you have to add a next.config.js to poll for changes. I'm not sure if MacOS has the same problem.
module.exports = {
webpackDevMiddleware: config => {
config.watchOptions = {
poll: 800,
aggregateTimeout: 300,
}
return config
},
}
Have you tested by exposing webpack default hot reload port?
add to your Dockerfile
...
EXPOSE 49153
...
and update your docker-compose.yml
version: "3.6"
services:
self_nextjs:
container_name: self_nextjs
build:
context: ./app
dockerfile: Dockerfile
ports:
- 3000:3000
- 49153:49153
volumes:
- ./app:/home/next_app
- /home/next_app/node_modules
networks:
- zen_frontend
restart: always
command: npm run dev
networks:
zen_frontend:
name: zen_frontend
driver: bridge
Hope this help,
Regards
I had to change #davidatthepark solution a little bit to get it to work for me. It looks like webpackDevMiddleware is not supported any more.
module.exports = {
webpack: (config, _) => ({
...config,
watchOptions: {
...config.watchOptions,
poll: 800,
aggregateTimeout: 300,
},
}),
}

Npm install errror during docker container building

I created very simple docker file for my nodejs web application:
FROM node:8.11.4
FROM mysql:latest
WORKDIR /ess-explorer
COPY . .
RUN npm install
RUN cd config && cp config.json.example config.json && cp database.json.example database.json && cd ../
RUN npm run migrate
EXPOSE 3000
CMD ["npm", "dev"]
And docker.yml
version: '3'
services:
essblockexplorer:
container_name: ess-explorer
build: .
depends_on:
- db
privileged: true
ports:
- 3000:3000
- 3010:3010
db:
container_name: mysql
image: mysql
restart: always
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: '123'
volumes:
db-data:
After command docker-compose -f docker.yml build evey time I've got an error
Step 5/9 : RUN npm install
---> Running in d3644d792807
/bin/sh: 1: npm: not found
ERROR: Service 'essblockexplorer' failed to build: The command '/bin/sh -c npm install' returned a non-zero code: 127
What am i doing wrong? I found similar issues but i didnt find the real solution for solving this problem
You shouldn't need the mysql image in your Dockerfile at all; ideally your app container (essblockexplorer) accesses the db container (db) via a NodeJS client. All you need to do is;
Remove the FROM mysql:latest line from your Dockerfile.
Access the MySQL database via a NodeJS client using (db) as the hostname (this is automatically loaded as an alias into your container).

docker-compose up didn't finish npm install.

I'm new to docker-compose and I'd like to use it for my current development.
after I ran docker-compose up -d everything was starting ok and it looks good. But my nodejs application wasn't installed correctly. It seems like npm install wasn't complete and I had to do docker exec -it api bash to run npm i manually inside the container.
Here's my docker-compose.
version: '2'
services:
app:
build: .
container_name: sparrow-api-1
volumes:
- .:/usr/src/app
- $HOME/.aws:/root/.aws
working_dir: /usr/src/app
environment:
- SPARROW_EVENT_QUEUE_URL=amqp://guest:guest#rabbitmq:5672
- REDIS_URL=redis
- NSOLID_APPNAME=sparrow-api
- NSOLID_HUB=registry:4001
- NODE_ENV=local
- REDIS_PORT=6379
- NODE_PORT=8081
- SOCKET_PORT=8002
- ELASTICSEARCH_URL=elasticsearch
- STDIN_OPEN=${STDIN_OPEN}
networks:
- default
depends_on:
- redis
- rabbitmq
- elasticsearch
expose:
- "8081"
ports:
- "8081:8081"
command: bash docker-command.sh
redis:
container_name: redis
image: redis:3.0.7-alpine
networks:
- default
ports:
- "6379:6379"
rabbitmq:
container_name: rabbitmq
image: rabbitmq:3.6.2-management
networks:
- default
ports:
- "15672:15672"
elasticsearch:
container_name: elasticsearch
image: elasticsearch:1.5.2
networks:
- default
ports:
- "9200:9200"
- "9300:9300"
registry:
image: nodesource/nsolid-registry
container_name: registry
networks:
- default
ports:
- 4001:4001
proxy:
image: nodesource/nsolid-hub
container_name: hub
networks:
- default
environment:
- REGISTRY=registry:4001
- NODE_DEBUG=nsolid
console:
image: nodesource/nsolid-console
container_name: console
networks:
- default
environment:
- NODE_DEBUG=nsolid
- NSOLID_APPNAME=console
- NSOLID_HUB=registry:4001
command: --hub hub:9000
ports:
- 3000:3000
# don't forget to create network as well
networks:
default:
driver: bridge
Here's my docker-command.sh
#!/usr/bin/env bash
# link the node modules to the root directory of our app, if not exists
modules_link="/usr/src/app/node_modules"
if [ ! -d "${modules_link}" ]; then
ln -s /usr/lib/app/node_modules ${modules_link}
fi
if [ -n "$STDIN_OPEN" ]; then
# if we want to be interactive with our app container, it needs to run in
# the background
tail -f /dev/null
else
nodemon
fi
Here's my Dockerfile
FROM nodesource/nsolid:latest
RUN mkdir /usr/lib/app
WORKDIR /usr/lib/app
COPY [".npmrc", "package.json", "/usr/lib/app/"]
RUN npm install \
&& npm install -g mocha \
&& npm install -g nodemon \
&& rm -rf package.json .npmrc
In your Dockerfile you are running npm install without any arguments first:
RUN npm install \
&& npm install -g mocha \
This will cause a non-zero exit code and due to the && the following commands are not executed. This should also fail the build though, so I'm guessing you already had a working image and added the npm instructions later. To rebuild the image use docker-compose build or simply docker-compose up --build. Per default docker-compose up will only build the image if it did not exist yet.

Docker Compose : NodeJS + MongoDB

I can't make my docker compose work.
Here's my dockerfile:
FROM node:0.12
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD . /myapp
RUN npm install
My docker-compose.yml
db:
image: mongo
ports:
- 27017
web:
build: .
command: npm start
volumes:
- .:/myapp
ports:
- 3000:3000
links:
- db
environment:
PORT: 3000
And in server.js:
var MONGO_DB;
var DOCKER_DB = process.env.DB_1_PORT;
if ( DOCKER_DB ) {
MONGO_DB = DOCKER_DB.replace( "tcp", "mongodb" ) + "/dev_db";
} else {
MONGO_DB = process.env.MONGODB;
}
mongoose.connect(MONGO_DB);
as from duplicated from this repo: https://github.com/projectweekend/Node-Backend-Seed
but process.env.DB_1_PORT is empty. How can I add it?
Thanks
Sorry #gettho.child, I accepted your answer too quickly. I thought it was working but it wasn't. I'll report here my final solution since I have been struggling quite some to achieve it.
Dockerfile:
FROM node:0.12
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev libkrb5-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD package.json /myapp/package.json
RUN npm install
ADD . /myapp
docker-compose.yml:
db:
image: mongo
ports:
- "27017:27017"
command: "--smallfiles --logpath=/dev/null"
web:
build: .
command: node app.js
volumes:
- .:/myapp
ports:
- "3000:3000"
links:
- db
environment:
PORT: 3000 # this is optional, allows express to use process.env.PORT instead of a raw 3000
And the interesting app.js extracts:
var MONGO_DB;
var DOCKER_DB = process.env.DB_PORT;
if ( DOCKER_DB ) {
MONGO_DB = DOCKER_DB.replace( 'tcp', 'mongodb' ) + '/myapp';
} else {
MONGO_DB = process.env.MONGODB;
}
var retry = 0;
mongoose.connect(MONGO_DB);
app.listen(process.env.PORT || 3000);
Regarding the process.env.DB_PORT I've tried many things around. If it doesn't work out-of-the-box, I suggest to console.log(process.env); and look for mongo's IP.
The final URL should look like: mongodb://172.17.0.76:27017/myapp
Good luck, it is worth it, Docker's awesome!
EDIT:
If the above works, I now found a techno-agnostic workflow by running:
docker-compose run web /bin/bash
and in there running printenv
I hope this is not too much self promotion but I wrote a double article on the topic which may help some of the readers: https://augustin-riedinger.fr/en/resources/using-docker-as-a-development-environment-part-1/
Cheers
Make sure that mongoDB IP (and port) in your 'Server.js' file is set to 'PORT_27017_TCP_ADDR' (check port too) - can be found when running 'docker exec {web app container id} env'.
Since we use docker-compose.yml and for reliable connection web service with db (mondoDB in this case) the final MONGO_DB connection string should look like (without authorization and additional args) as the following:
mongodb://db:27017/myapp
where:
db - name of the docker-composer MongoDB service
myapp - name of the mongoDB database
More see here
Your docker-compose should be
environment:
- MONGODB=3000
See this link for more information on mapping environment variables. You are declaring the environment variable as PORT instead of MONGODB.

Resources