I have developed a react app via the includes live-server and deployed it. As a proxy server I am using nginx, which also serves some static and media files for the back- and frontend.
Especially to test the serving of static and media files I would like to have a dockerized local testing environment.
Here is my problem:
In my test environment I do not want to create a new build every time I change the code (npm run build - for create-react-app). Ideally, I would have the ability to hot-reload via a bind mount.
This would mean that I would have to serve the development server via nginx. Is that at all possible? I am biting my nails over this problem for days, looking for a conventional way to do it.
It actually isn't too bad, just use an nginx config like this:
events {}
# assuming you want to serve your app on localhost:8080
# and assuming your webpack dev server runs on port 3000
http {
include /etc/nginx/mime.types;
server {
# assuming you want to serve the app on localhost:8080
listen 8080;
client_max_body_size 50m;
# webpack dev server
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
# use your port for your webpack dev server
proxy_pass http://host.docker.internal:3000/;
}
# this is specifically needed for hot reload with webpack dev server
location /sockjs-node {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
# 'host.docker.internal' is a docker dns record for your host machine's localhost,
# and '3000' should be the port of your webpack dev server
proxy_pass http://host.docker.internal:3000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
access_log /etc/nginx/access.log;
error_log /etc/nginx/error.log debug;
}
And run nginx with a ./nginx.sh that looks like this:
#!/usr/bin/env bash
# path to your app's build directory
APP_BUILD_DIR=/path/to/my-app/build
# path of dir containing your nginx config
NGINX_CONF_DIR=$(pwd)
# name of your nginx conf file, relative to NGINX_CONF_DIR
NGINX_CONF_FILE=nginx.conf
# port at which nginx is serving your app
PORT=8080
# docker run docs: https://docs.docker.com/engine/reference/run/
# this will run an nginx container named 'nginx' as a daemon,
# and will mount NGINX_CONF_DIR in the container
docker run -d --name nginx \
-v=$NGINX_CONF_DIR:/etc/nginx \
-v=$APP_BUILD_DIR:/opt/base/my-app \
-p=$PORT:$PORT nginx \
nginx -c /etc/nginx/$NGINX_CONF_FILE -g "daemon off;"
And also a mime.types file in that directory that looks like this one.
So your directory structure should look like:
dir/
-- nginx.sh
-- nginx.conf
-- mime.types
-- ...
I'm assuming you're running your webpack dev server on your machine, not in a docker container? In my experience, I'd recommend that honestly. npm (or yarn) does its job so well that I haven't found a need to run my React apps in a container locally, even though I serve them through an nginx container.
Bonus: here's an nginx config if you want to run the same app, but serve the static bundle instead of the webpack dev server:
events {}
http {
include /etc/nginx/mime.types;
server {
# assuming you want to serve the app on localhost:8080
listen 8080;
client_max_body_size 50m;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
root /opt/base/my-app;
try_files $uri /index.html;
}
# matches things like http://localhost:8080/build/static/js/2.d63c51de.chunk.js
location /build/static/ {
alias /opt/base/my-app/static/;
try_files $uri $uri/;
}
}
access_log /etc/nginx/access.log;
error_log /etc/nginx/error.log debug;
}
Reference: this SO post
Dockerizing development server with HMR is not a trivial task.
Even preconfigured projects (with HMR and docker-ready) probably won't work at the beggining without additional adjustments. F.e. HMR expects localhost path while you can have app working on another IP/port (CORS problems). Some adjustments can be hard - patching packages on the fly - during build processes.
Try to run ready project before trying to setup your dream config. You can always run different servers for different parts (on different ports).
I'd start with apollo-universal-starter-kit - it contains node.js api/backend parts but can work with external one (configurable).
You can search for other react-HMR-ready solutions on Docker Hub. Try, get inspirations and knowledge ... have fun.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With