webpack-dev-server proxy to docker container - docker

I have 2 docker containers managed with docker-compose and can't seem to properly use webpack to proxy some request to the backend api.
docker-compose.yml :
version: '2'
services:
web:
build:
context: ./frontend
ports:
- "80:8080"
volumes:
- ./frontend:/16AGR/frontend:rw
links:
- back:back
back:
build:
context: ./backend
expose:
- "8080"
ports:
- "8081:8080"
volumes:
- ./backend:/16AGR/backend:rw
the service web is a simple react application served by a webpack-dev-server.
the service back is a node application.
I have no problem to access either app from my host :
$ curl localhost
> index.html
$ curl localhost:8081
> Hello World
I can also ping and curl the back service from the web container :
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73ebfef9b250 16agr_web "npm run start" 37 hours ago Up 13 seconds 0.0.0.0:80->8080/tcp 16agr_web_1
a421fc24f8d9 16agr_back "npm start" 37 hours ago Up 15 seconds 0.0.0.0:8081->8080/tcp 16agr_back_1
$ docker exec -it 73e bash
$ root#73ebfef9b250:/16AGR/frontend# curl back:8080
Hello world
However i have a problem with the proxy.
Webpack is started with
webpack-dev-server --display-reasons --display-error-details --history-api-fallback --progress --colors -d --hot --inline --host=0.0.0.0 --port 8080
and the config file is
frontend/webpack.config.js :
var webpack = require('webpack');
var config = module.exports = {
...
devServer: {
//redirect api calls to backend server
proxy: {
'/api': {
target: "back:8080",
secure: false
}
}
}
...
}
When i try to request /api/test with a link in my app for exemple i get a generic error, the link and google did not help much :(
[HPM] Error occurred while trying to proxy request /api/test from localhost to back:8080 (EINVAL) (https://nodejs.org/api/errors.html#errors_common_system_errors)
I suspect some weird thing because the proxy is on the container and the request is on localhost but I don't really have an idea to solve this.

I think I managed to tacle the problem.
Just had to change the webpack configuration with the following
devServer: {
//redirect api calls to backend server
proxy: {
'/api': {
target: {
host: "back",
protocol: 'http:',
port: 8080
},
ignorePath: true,
changeOrigin: true,
secure: false
}
}
}

Related

Dockerize Vue.js: hot-reload is not working for vue/cli#4.5 or later versions

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,

Keycloak LDAP authentication from a dockerized NuxtJS app

I am facing a problem with my authentication with Keycloak. Everything works fine when my Nuxt app is running locally (npm run dev), but when it is inside a Docker container, something goes wrong.
Windows 10
Docker 20.10.11
Docker-compose 1.29.2
nuxt: ^2.15.7
#nuxtjs/auth-next: ^5.0.0-1637745161.ea53f98
#nuxtjs/axios: ^5.13.6
I have a docker service containing Keycloak and Ldap : keycloak:8180 and myad:10389. My Nuxt app is running on port 3000.
On front side, here is my configuration, which is working great when I launch my app locally with "npm run dev" :
server: {
port: 3000,
host: '0.0.0.0'
},
...
auth: {
strategies: {
local: false,
keycloak: {
scheme: 'oauth2',
endpoints: {
authorization: 'http://localhost:8180/auth/realms/<realm>/protocol/openid-connect/auth',
token: 'http://localhost:8180/auth/realms/<realm>/protocol/openid-connect/token',
userInfo: 'http://localhost:8180/auth/realms/<realm>/protocol/openid-connect/userinfo',
logout: 'http://localhost:8180/auth/realms/<realm>/protocol/openid-connect/logout?redirect_uri=' + encodeURIComponent('http://localhost:3000')
},
token: {
property: 'access_token',
type: 'Bearer',
name: 'Authorization',
maxAge: 300
},
refreshToken: {
property: 'refresh_token',
maxAge: 60 * 60 * 24 * 30
},
responseType: 'code',
grantType: 'authorization_code',
clientId: '<client_id>',
scope: ['openid'],
codeChallengeMethod: 'S256'
}
},
redirect: {
login: '/',
logout: '/',
home: '/home'
}
},
router: {
middleware: ['auth']
}
}
And here are my Keycloak and Nuxt docker-compose configurations :
keycloak:
image: quay.io/keycloak/keycloak:latest
container_name: keycloak
hostname: keycloak
environment:
- DB_VENDOR=***
- DB_ADDR=***
- DB_DATABASE=***
- DB_USER=***
- DB_SCHEMA=***
- DB_PASSWORD=***
- KEYCLOAK_USER=***
- KEYCLOAK_PASSWORD=***
- PROXY_ADDRESS_FORWARDING=true
ports:
- "8180:8080"
networks:
- ext_sd_bridge
networks:
ext_sd_bridge:
external:
name: sd_bridge
client_ui:
image: ***
container_name: client_ui
hostname: client_ui
ports:
- "3000:3000"
networks:
- sd_bridge
networks:
sd_bridge:
name: sd_bridge
When my Nuxt app is inside its container, the authentication seems to work, but redirections are acting strange. As you can see I am always redirected to my login page ("/") after my redirection to "/home":
Browser network
Am I missing something or is there something I am doing wrong?
I figured out what my problem was.
So basically, my nuxt.config.js was wrong for a use inside a Docker container. I had to change the auth endpoints to :
endpoints: {
authorization: '/auth/realms/<realm>/protocol/openid-connect/auth',
token: '/auth/realms/<realm>/protocol/openid-connect/token',
userInfo: '/auth/realms/<realm>/protocol/openid-connect/userinfo',
logout: '/auth/realms/<realm>/protocol/openid-connect/logout?redirect_uri=' + encodeURIComponent('http://localhost:3000')
}
And proxy the "/auth" requests to the hostname of my Keycloak Docker container (note that my Keycloak and Nuxt containers are in the same network in my docker-compose files) :
proxy: {
'/auth': 'http://keycloak:8180'
}
At this point, every request was working fine except the "/authenticate" one, because "keycloak:8180/authenticate" is put in the browser URL and of course, it doesn't know "keycloak".
For this to work, I added this environment variable to my Keycloak docker-compose :
KEYCLOAK_FRONTEND_URL=http://localhost:8180/auth
With this variable, the full process of authentication/redirection is working like a charm, with Keycloak and Nuxt in their containers :)
👍

web-component-tester cannot bind to port

I have a docker setup with following containers:
selenium-hub
selenium-firefox
selenium-chrome
spring boot app
node/java service for wct tests
All these containers are defined via docker-compose.
The node/java service is created as follows (extract from docker-compose):
wct:
build:
context: ./app/src/main/webapp
args:
ARTIFACTORY: ${DOCKER_REGISTRY}
image: wct
container_name: wct
depends_on:
- selenium-hub
- selenium-chrome
- selenium-firefox
- webapp
The wct tests are run using:
docker-compose run -d --name wct-run wct npm run test
And the wct.conf.js looks like following:
const seleniumGridAddress = process.env.bamboo_selenium_grid_address || 'http://selenium-hub:4444/wd/hub';
const hostname = process.env.FQDN || 'wct';
module.exports = {
activeBrowsers: [{
browserName: "chrome",
url: seleniumGridAddress
}, {
browserName: "firefox",
url: seleniumGridAddress
}],
webserver: {
hostname: hostname
},
plugins: {
local: false,
sauce: false,
}
}
The testrun fails with this stacktrace:
ERROR: Server failed to start: Error: No available ports. Ports tried: [8081,8000,8001,8003,8031,2000,2001,2020,2109,2222,2310,3000,3001,3030,3210,3333,4000,4001,4040,4321,4502,4503,4567,5000,5001,5050,5432,6000,6001,6060,6666,6543,7000,7070,7774,7777,8765,8777,8888,9000,9001,9080,9090,9876,9877,9999,49221,55001]
at /app/node_modules/polymer-cli/node_modules/polyserve/lib/start_server.js:384:15
at Generator.next (<anonymous>)
at fulfilled (/app/node_modules/polymer-cli/node_modules/polyserve/lib/start_server.js:17:58)
I tried to fix it as per: polyserve cannot serve the app but without success.
I also tried setting hostnameto wct as this is the known hostname for the container inside the docker network, but it shows the same error.
I really do not know what to do next.
Any help is appreciated.
The problem was that the hostname was incorrect, so WCT was unable to bind to an unknown hostname.

docker-compose can't connect to adjacent service via service name

I have this docker-compose.yml that basically builds my project for e2e test. It's composed of a postgres db, a backend Node app, a frontend Node app, and a spec app which runs the e2e test using cypress.
version: '3'
services:
database:
image: 'postgres'
backend:
build: ./backend
command: /bin/bash -c "sleep 3; yarn backpack dev"
depends_on:
- database
frontend:
build: ./frontend
command: /bin/bash -c "sleep 15; yarn nuxt"
depends_on:
- backend
spec:
build:
context: ./frontend
dockerfile: Dockerfile.e2e
command: /bin/bash -c "sleep 30; yarn cypress run"
depends_on:
- frontend
- backend
The Dockerfiles are just simple Dockerfiles that based off node:8 which copies the project files and run yarn install. In the spec Dockerfile, I pass http://frontend:3000 as FRONTEND_URL.
But this setup fails at the spec command when my cypress runner can't connect to frontend with error:
spec_1 | > Error: connect ECONNREFUSED 172.20.0.4:3000
As you can see, it resolves the hostname frontend to the IP correctly, but it's not able to connect. I'm scratching my head over why can't I connect to the frontend with the service name. If I switch the command on spec to do sleep 30; ping frontend, it's successfully pinging the container. I've tried deleting and let docker-compose recreate the network, I've tried specifying expose and links to the services respectively. All to no success.
I've set up a sample repo here if you wanna try replicating the issue:
https://github.com/afifsohaili/demo-dockercompose-network
Any help is greatly appreciated! Thank you!
Your application is listening on loopback:
$ docker run --rm --net container:demo-dockercompose-network_frontend_1 nicolaka/netshoot ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.11:35233 *:*
LISTEN 0 128 127.0.0.1:3000 *:*
From outside of the container, you cannot connect to ports that are only listening on loopback (127.0.0.1). You need to reconfigure your application to listen on all interfaces (0.0.0.0).
For your app, in the package.json, you can add (according to the nuxt faq):
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "3000"
}
},
Then you should see:
$ docker run --rm --net container:demo-dockercompose-network_frontend_1 nicolaka/netshoot ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:3000 *:*
LISTEN 0 128 127.0.0.11:39195 *:*
And instead of an unreachable error, you'll now get a 500:
...
frontend_1 | response: undefined,
frontend_1 | statusCode: 500,
frontend_1 | name: 'NuxtServerError' }
...
spec_1 | The response we received from your web server was:
spec_1 |
spec_1 | > 500: Server Error

Docker with Mongo and Express

First of all, give thanks for reading my question and try to help me and apologize for my English.
I'm trying to run a docker with a express server project and mongo, but build Dockerfile perfectly but I do:
docker logs -f name
and show next error:
/usr/local/bin/docker-entrypoint-sh line 340: exec: npm not found
And, I think that mongodb doesnt run
Why doesnt recognize npm if I add node?
How can run npm and launch mongo?
I'm using ubuntu 17.10
Here is my Dockerfile:
# Install Node
FROM node:latest
# Install Mongo
FROM mongo:4.0.0-xenial
# Author
MAINTAINER MachineGun
# Create user Ubuntu 17.10 (64 bits)
RUN adduser --disabled-login dockeruser
# Work Directory
WORKDIR /home/expressserver
# Copy express project to docker
COPY expressserver expressserver
# Defaul user
USER dockeruser
# Config cointainer PORT:
# MongoDB listening on port: 27017
# Server listening on port: 8080
EXPOSE 27017 8080
# Exec MongoDB
CMD [mongo]
# Exec server with custom npm start
CMD ["npm", "run", "start:dev"]
Also, in app.js I use mongoose with next uri: mongodb://localhost:27017/ExpressServer, its ok?
mongoose.connection.openUri('mongodb://localhost:27017/ExpressServer', { useNewUrlParser: true }, (err, res) => {
if (err) {
console.log('Error: Database not running on port 27017: \x1b[31m%s\x1b[0m', 'offline');
// console.log('throw err: ', err);
throw err;
}
console.log('Database running on port 27017: \x1b[32m%s\x1b[0m', 'online');
});
I've solved the problem :D
Thanks a lot :D
Finally I used docker compose...
Here is my docker-compose.yml:
version: '2'
services:
server:
container_name: expressserver
build: ./
ports:
- "8080:8080"
links:
- mongo
mongo:
container_name: mongoDB
image: mongo:latest
volumes:
- /var/lib/mongodb:/data/db
ports:
- "27017:27017"
command: mongod --port 27017
Here is my Dockerfile:
FROM node:carbon
MAINTAINER MachineGun
RUN adduser --disabled-login dockeruser
WORKDIR /home/dockeruser
COPY expressserver expressserver
WORKDIR /home/dockeruser/expressserver
RUN npm install
USER dockeruser
EXPOSE 8080 27017
CMD ["npm", "start"]
And in my app.js to connect with mongoose:
const options = {
autoIndex: false, // Don't build indexes
reconnectTries: 30, // Retry up to 30 times
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0
};
// Database connection
const connectWithRetry = () => {
mongoose.connect("mongodb://mongo/expressdb", options)
.then(()=>{
console.log('Database running on port 27017: \x1b[32m%s\x1b[0m', 'online')
})
.catch( (err) => {
console.log('MongoDB connection unsuccessful on port 27017: \x1b[31m%s\x1b[0m', 'offline');
console.log('Retry after 5 seconds.');
setTimeout(connectWithRetry, 5000)
});
}
connectWithRetry();

Resources