简体   繁体   中英

Docker-Compose, NGINX, and Hot Reload Configuration

I have a functional fullstack application running through docker-compose. Works like a charm. Only problem is that the team has to rebuild the entire application to reflect changes. That means bringing the entire thing down with docker-compose down .

I'm looking for help to update the file(s) below to allow for either hot reloads OR simply enable browser refreshes to pickup UI changes

NOTES:

  • I have "dev" and "prod" npm scripts. Both behave as they were prod (currently produce a static build folder and point to it)

Any help would be greatly appreciated:)

package.json

{
  "name": "politicore",
  "version": "1.0.1",
  "description": "Redacted",
  "repository": "Redacted",
  "author": "Redacted",
  "license": "LicenseRef-LICENSE.MD",
  "private": true,
  "engines": {
    "node": "10.16.3",
    "yarn": "YARN NO LONGER USED - use npm instead."
  },
  "scripts": {
    "dev": "docker-compose up",
    "dev-force": "docker-compose up --build --force-recreate",
    "dev-force-d": "docker-compose up --build --force-recreate -d",
    "prod-up": "docker-compose -f docker-compose-prod.yml up",
    "prod-up-force": "docker-compose -f docker-compose-prod.yml up --build --force-recreate",
    "prod-up-force-d": "docker-compose -f docker-compose-prod.yml up --build --force-recreate -d", 
    "dev-down": "docker-compose down",
    "dev-down-remove": "docker-compose down --remove-orphans",
    "prod-down": "docker-compose down",
    "prod-down-remove": "docker-compose down --remove-orphans"
  }
}

nginx dev config file

server {

  listen 80;
  listen 443;

  server_name MyUrl.com www.MyUrl.com;
  
  server_tokens off;
  proxy_hide_header X-Powered-By;
  proxy_hide_header Server;
  add_header X-XSS-Protection "1; mode=block";
  add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
  add_header X-Frame-Options DENY;
  add_header X-Content-Type-Options nosniff;
  add_header X-Permitted-Cross-Domain-Policies master-only;
  add_header Referrer-Policy same-origin;
  add_header Expect-CT 'max-age=60';
  add_header Feature-Policy "accelerometer none; ambient-light-sensor none; battery none; camera none; gyroscope none;";
  
  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  location /graphql {
    proxy_set_header  Host $host;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Host $server_name;
    proxy_pass        http://api:5000;
    proxy_redirect    default;
  }

}

docker-compose dev file

version: '3.6'

services:
  api:
    build:
      context: ./services/api
      dockerfile: Dockerfile-dev
    restart: always
    volumes:
      - './services/api:/usr/src/app'
      - '/usr/src/app/node_modules'
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING=true
    env_file: 
      - common/.env

  client:
    build:
      context: ./services/client
      dockerfile: Dockerfile-dev
    restart: always
    volumes:
      - './services/client:/usr/src/app'
      - '/usr/src/app/node_modules' 
    ports:
     - 80:80
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING=true
    depends_on:
      - api
    stdin_open: true

Client Service dockerfile

FROM node:10 as builder
WORKDIR /usr/src/app

COPY package.json /usr/src/app/package.json

RUN npm install

COPY . .

RUN npm run build

FROM nginx:alpine

COPY --from=builder /usr/src/app/build /usr/share/nginx/html

COPY nginx/dev.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

API dockerfile (dev & prod)

FROM node:10

WORKDIR /usr/src/app

COPY package.json /usr/src/app/package.json

RUN npm install

CMD ["npm", "start"]

Filetree Picture

在此处输入图像描述

As I understand it, your nginx file defines 2 areas to serve: location / and location /graphql .

The first ( location / ) is serving up static files from /usr/share/nginx/html inside the container. Those files are created during your docker build. Since those are produced in a multi-stage docker build, you will need to change your strategy up. Here are several options that may help guide you.

Option 1

One option is to build local and mount a volume.

  • Perform npm run build on your box (perhaps even with a filewatcher to perform builds any time *.js files change
  • Add -./build:/usr/share/nginx/html to list of volumes for client service

The trade-off here is that you have to forego a fully dockerized build (if that's something that matters heavily to you and your team).

Option 2

Utilize a hot-reloading node server for local development and build a docker image for production environments. It's hard to tell from the files whether the client is react, angular, vuejs, etc., but typically they have a pattern from running local dev servers.

The trade-off here is that you run locally differently than running in production.

Option 3

Combine nginx and nodejs into one docker image with hot reloading inside.

  • Build a local docker image that contains nodejs and nginx
  • (You already have a volume mount into client of your app src files)
  • Set up the image to run npm run build inside the container every time a file changes in that mounted volume

The trade-off here is that you may have more than 1 process running in a docker container (a big no-no).

Option 4

A variation of option 3 where you run 2 docker containers.

  • Declare a top-level volume client_build
    •  volumes: - client_build:
  • Create a docker service in docker-compose with 2 volumes
    • -./services/client:/usr/src/app
    • - client_build:/usr/src/app/build
  • Add the build volume to your client service: - client_build:/usr/share/nginx/html
  • Make sure nginx hot-reloads when that dir changes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM