From 1e267507dd2f0508d3a54c212fd8d6ab979871c0 Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Sun, 6 Feb 2022 03:03:58 -0300 Subject: [PATCH 1/7] Build frontend in docker for production using nginx --- frontend/.docker/nginx/conf.d/default.conf | 4 ++++ .../.docker/nginx/include.d/allcache.conf | 3 +++ frontend/.docker/nginx/include.d/nocache.conf | 5 ++++ frontend/.docker/nginx/include.d/root.conf | 16 +++++++++++++ frontend/.docker/nginx/include.d/spa.conf | 19 +++++++++++++++ frontend/Dockerfile | 24 +++++++++++++++++++ 6 files changed, 71 insertions(+) create mode 100755 frontend/.docker/nginx/conf.d/default.conf create mode 100755 frontend/.docker/nginx/include.d/allcache.conf create mode 100755 frontend/.docker/nginx/include.d/nocache.conf create mode 100755 frontend/.docker/nginx/include.d/root.conf create mode 100755 frontend/.docker/nginx/include.d/spa.conf create mode 100644 frontend/Dockerfile diff --git a/frontend/.docker/nginx/conf.d/default.conf b/frontend/.docker/nginx/conf.d/default.conf new file mode 100755 index 0000000..5e91aa8 --- /dev/null +++ b/frontend/.docker/nginx/conf.d/default.conf @@ -0,0 +1,4 @@ +server { + server_name _; + include include.d/spa.conf; +} diff --git a/frontend/.docker/nginx/include.d/allcache.conf b/frontend/.docker/nginx/include.d/allcache.conf new file mode 100755 index 0000000..36aa6d2 --- /dev/null +++ b/frontend/.docker/nginx/include.d/allcache.conf @@ -0,0 +1,3 @@ +expires 1y; +add_header Cache-Control "public"; +access_log off; diff --git a/frontend/.docker/nginx/include.d/nocache.conf b/frontend/.docker/nginx/include.d/nocache.conf new file mode 100755 index 0000000..d2f4f9d --- /dev/null +++ b/frontend/.docker/nginx/include.d/nocache.conf @@ -0,0 +1,5 @@ +add_header Last-Modified $date_gmt; +add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; +if_modified_since off; +expires off; +etag off; \ No newline at end of file diff --git a/frontend/.docker/nginx/include.d/root.conf b/frontend/.docker/nginx/include.d/root.conf new file mode 100755 index 0000000..09aac30 --- /dev/null +++ b/frontend/.docker/nginx/include.d/root.conf @@ -0,0 +1,16 @@ +# X-Frame-Options is to prevent from clickJacking attack +add_header X-Frame-Options SAMEORIGIN; + +# disable content-type sniffing on some browsers. +add_header X-Content-Type-Options nosniff; + +# This header enables the Cross-site scripting (XSS) filter +add_header X-XSS-Protection "1; mode=block"; + +# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack +add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; + +add_header Referrer-Policy "no-referrer-when-downgrade"; + +# Enables response header of "Vary: Accept-Encoding" +gzip_vary on; \ No newline at end of file diff --git a/frontend/.docker/nginx/include.d/spa.conf b/frontend/.docker/nginx/include.d/spa.conf new file mode 100755 index 0000000..a2147f0 --- /dev/null +++ b/frontend/.docker/nginx/include.d/spa.conf @@ -0,0 +1,19 @@ +listen 80; +index index.html; +root /var/www/public/; + +location /{{ default .Env.FOLDER_BACKEND "api" }}/ { + proxy_pass {{ .Env.URL_BACKEND }}; +} + +location / { + try_files $uri $uri/ /index.html; + include include.d/nocache.conf; +} + +location /static { + alias /var/www/public/static/; + include include.d/allcache.conf; +} + +include include.d/root.conf; \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..e1db5d4 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,24 @@ +FROM node:14-alpine as build-deps +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm install +COPY .env* ./ +COPY src/ ./src/ +COPY public/ ./public/ +RUN echo "REACT_APP_BACKEND_URL=/api/" > .env.production +RUN npm run build + +FROM nginx:alpine + +RUN apk add --no-cache openssl +ENV DOCKERIZE_VERSION v0.6.1 +RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +COPY .docker/nginx /etc/nginx/ +COPY --from=build-deps /usr/src/app/build /var/www/public/ +EXPOSE 80 + +RUN echo "dockerize -template /etc/nginx/include.d/spa.conf:/etc/nginx/include.d/spa.conf" > /docker-entrypoint.d/01-change-url-backend.sh \ + && chmod +x /docker-entrypoint.d/01-change-url-backend.sh \ No newline at end of file From 9a54297efd040efc9345103f30fbea0d492f7b86 Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Sun, 6 Feb 2022 15:02:04 -0300 Subject: [PATCH 2/7] Build backend in docker for production with env vars --- .gitignore | 1 + backend/.dockerignore | 5 ++++ backend/Dockerfile | 23 +++++++++++++++++ backend/src/libs/wbot.ts | 4 ++- docker-compose.yaml | 56 ++++++++++++++++++++++++++++++++++++++++ frontend/.dockerignore | 5 ++++ 6 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 backend/.dockerignore create mode 100644 backend/Dockerfile create mode 100644 docker-compose.yaml create mode 100644 frontend/.dockerignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d90cb51 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.docker/data/ \ No newline at end of file diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..0d40646 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,5 @@ +.git +*Dockerfile* +*docker-compose* +node_modules +dist \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..f416a29 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,23 @@ +FROM node:14 as build-deps + +WORKDIR /usr/src/app +COPY package*.json ./ +RUN npm install + +COPY . . +RUN npm run build + +RUN apt-get update && apt-get install -y wget +ENV DOCKERIZE_VERSION v0.6.1 +RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +ENV NODE_ENV=production +ENV PORT=3000 + +EXPOSE 3000 + +ENTRYPOINT dockerize -wait tcp://${DB_HOST}:3306 \ + && npx sequelize db:migrate \ + && node dist/server.js \ No newline at end of file diff --git a/backend/src/libs/wbot.ts b/backend/src/libs/wbot.ts index 4febef7..b50f7bf 100644 --- a/backend/src/libs/wbot.ts +++ b/backend/src/libs/wbot.ts @@ -46,7 +46,9 @@ export const initWbot = async (whatsapp: Whatsapp): Promise => { const wbot: Session = new Client({ session: sessionCfg, puppeteer: { - executablePath: process.env.CHROME_BIN || undefined + executablePath: process.env.CHROME_BIN || undefined, + // @ts-ignore + browserWSEndpoint: process.env.CHROME_WS || undefined } }); diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..198889b --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,56 @@ +version: '3' + +networks: + whaticket: + +services: + + backend: + build: + context: ./backend + dockerfile: ./Dockerfile + environment: + - DB_HOST=mysql + - DB_USER=root + - DB_PASS=${MYSQL_ROOT_PASSWORD:-strongpassword} + - DB_NAME=${MYSQL_DATABASE:-whaticket} + - JWT_SECRET=${JWT_SECRET:-3123123213123} + - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-75756756756} + - CHROME_WS=ws://chrome:3000 + ports: + - 8080:3000 + networks: + - whaticket + + frontend: + ports: + - 3000:80 + build: + context: ./frontend + dockerfile: ./Dockerfile + environment: + - URL_BACKEND=http://backend:3000/ + networks: + - whaticket + + mysql: + image: mariadb:latest + command: --character-set-server=utf8mb4 --collation-server=utf8mb4_bin + ports: + - 3306:3306 + volumes: + - ./.docker/data/:/var/lib/mysql + environment: + - MYSQL_DATABASE=${MYSQL_DATABASE:-whaticket} + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-strongpassword} + - TZ=${TZ:-America/Fortaleza} + restart: always + networks: + - whaticket + + chrome: + image: browserless/chrome:latest + environment: + - MAX_CONCURRENT_SESSIONS=10 + networks: + - whaticket \ No newline at end of file diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..b5f3ce1 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,5 @@ +.git +*Dockerfile* +*docker-compose* +node_modules +build \ No newline at end of file From a74241307c68bf0d3d630829b9002e6524d4d6fb Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Sun, 6 Feb 2022 15:24:15 -0300 Subject: [PATCH 3/7] Adjusting environment variables and adding .env.example --- .env.example | 6 ++++++ .gitignore | 3 ++- docker-compose.yaml | 16 ++++++---------- 3 files changed, 14 insertions(+), 11 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..75a62c7 --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +MYSQL_ROOT_PASSWORD=strongpassword +MYSQL_DATABASE=whaticket +JWT_SECRET=3123123213123 +JWT_REFRESH_SECRET=75756756756 +FRONTEND_PORT=3000 +TZ=America/Fortaleza \ No newline at end of file diff --git a/.gitignore b/.gitignore index d90cb51..9f89ea2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.docker/data/ \ No newline at end of file +.docker/data/ +.env \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 198889b..f0d01d8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -17,14 +17,12 @@ services: - JWT_SECRET=${JWT_SECRET:-3123123213123} - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-75756756756} - CHROME_WS=ws://chrome:3000 - ports: - - 8080:3000 networks: - whaticket frontend: ports: - - 3000:80 + - ${FRONTEND_PORT:-3000}:80 build: context: ./frontend dockerfile: ./Dockerfile @@ -36,17 +34,15 @@ services: mysql: image: mariadb:latest command: --character-set-server=utf8mb4 --collation-server=utf8mb4_bin - ports: - - 3306:3306 volumes: - - ./.docker/data/:/var/lib/mysql + - ./.docker/data/:/var/lib/mysql environment: - - MYSQL_DATABASE=${MYSQL_DATABASE:-whaticket} - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-strongpassword} - - TZ=${TZ:-America/Fortaleza} + - MYSQL_DATABASE=${MYSQL_DATABASE:-whaticket} + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-strongpassword} + - TZ=${TZ:-America/Fortaleza} restart: always networks: - - whaticket + - whaticket chrome: image: browserless/chrome:latest From e640bb7ccbb790886d1b2d4bb549b5dc4e09b125 Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Sun, 6 Feb 2022 15:24:54 -0300 Subject: [PATCH 4/7] Using alpine image to backend --- backend/Dockerfile | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index f416a29..4fbbe18 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:14 as build-deps +FROM node:14-alpine as build-deps WORKDIR /usr/src/app COPY package*.json ./ @@ -7,11 +7,19 @@ RUN npm install COPY . . RUN npm run build -RUN apt-get update && apt-get install -y wget +FROM node:14-alpine + +RUN apk add --no-cache openssl + ENV DOCKERIZE_VERSION v0.6.1 -RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ - && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ - && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz +RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +WORKDIR /usr/src/app +COPY --from=build-deps /usr/src/app/node_modules/ ./node_modules/ +COPY --from=build-deps /usr/src/app/dist/ ./dist/ +COPY .sequelizerc . ENV NODE_ENV=production ENV PORT=3000 From dad4fb83b86d6b7dcb9a0952405245e6a4e0ea64 Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Mon, 7 Feb 2022 09:05:52 -0300 Subject: [PATCH 5/7] Setting max chrome connections and exposing mysql port --- .env.example | 3 ++- docker-compose.yaml | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 75a62c7..28d690e 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,5 @@ MYSQL_DATABASE=whaticket JWT_SECRET=3123123213123 JWT_REFRESH_SECRET=75756756756 FRONTEND_PORT=3000 -TZ=America/Fortaleza \ No newline at end of file +TZ=America/Fortaleza +MAX_CONCURRENT_SESSIONS=1 \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index f0d01d8..fdc0032 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -40,6 +40,8 @@ services: - MYSQL_DATABASE=${MYSQL_DATABASE:-whaticket} - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-strongpassword} - TZ=${TZ:-America/Fortaleza} + ports: + - 3306:3306 restart: always networks: - whaticket @@ -47,6 +49,6 @@ services: chrome: image: browserless/chrome:latest environment: - - MAX_CONCURRENT_SESSIONS=10 + - MAX_CONCURRENT_SESSIONS=${MAX_CONCURRENT_SESSIONS:-1} networks: - whaticket \ No newline at end of file From 9792f81e1e410b58d9b0f981c191d16106c6be9b Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Tue, 8 Feb 2022 11:51:12 -0300 Subject: [PATCH 6/7] Add reverse proxy in nginx for socket.io --- frontend/.docker/nginx/include.d/spa.conf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/.docker/nginx/include.d/spa.conf b/frontend/.docker/nginx/include.d/spa.conf index a2147f0..3889442 100755 --- a/frontend/.docker/nginx/include.d/spa.conf +++ b/frontend/.docker/nginx/include.d/spa.conf @@ -6,6 +6,15 @@ location /{{ default .Env.FOLDER_BACKEND "api" }}/ { proxy_pass {{ .Env.URL_BACKEND }}; } +location /socket.io/ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_pass {{ .Env.URL_BACKEND }}socket.io/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; +} + location / { try_files $uri $uri/ /index.html; include include.d/nocache.conf; From c78d826a8f77106d6d8b63b8bf355c2c3a5a7954 Mon Sep 17 00:00:00 2001 From: Ricardo Paes Date: Tue, 8 Feb 2022 14:19:31 -0300 Subject: [PATCH 7/7] Remove browserless and add chrome in docker image --- backend/Dockerfile | 41 ++++++++++++++++++++------------- backend/src/libs/wbot.ts | 5 +++- docker-compose-browserless.yaml | 17 ++++++++++++++ docker-compose.yaml | 11 +++------ 4 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 docker-compose-browserless.yaml diff --git a/backend/Dockerfile b/backend/Dockerfile index 4fbbe18..0353bb5 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,25 @@ -FROM node:14-alpine as build-deps +FROM node:14 as build-deps + +RUN apt-get update && apt-get install -y wget + +ENV DOCKERIZE_VERSION v0.6.1 +RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +RUN apt-get update \ + && apt-get install -y wget gnupg \ + && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ + && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ + && apt-get update \ + && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.1/dumb-init_1.2.1_amd64 /usr/local/bin/dumb-init +RUN chmod +x /usr/local/bin/dumb-init + +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true WORKDIR /usr/src/app COPY package*.json ./ @@ -7,25 +28,13 @@ RUN npm install COPY . . RUN npm run build -FROM node:14-alpine - -RUN apk add --no-cache openssl - -ENV DOCKERIZE_VERSION v0.6.1 -RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ - && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ - && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz - -WORKDIR /usr/src/app -COPY --from=build-deps /usr/src/app/node_modules/ ./node_modules/ -COPY --from=build-deps /usr/src/app/dist/ ./dist/ -COPY .sequelizerc . - ENV NODE_ENV=production ENV PORT=3000 +ENV CHROME_BIN=google-chrome-stable EXPOSE 3000 -ENTRYPOINT dockerize -wait tcp://${DB_HOST}:3306 \ +ENTRYPOINT ["dumb-init", "--"] +CMD dockerize -wait tcp://${DB_HOST}:3306 \ && npx sequelize db:migrate \ && node dist/server.js \ No newline at end of file diff --git a/backend/src/libs/wbot.ts b/backend/src/libs/wbot.ts index b50f7bf..f58830b 100644 --- a/backend/src/libs/wbot.ts +++ b/backend/src/libs/wbot.ts @@ -43,12 +43,15 @@ export const initWbot = async (whatsapp: Whatsapp): Promise => { sessionCfg = JSON.parse(whatsapp.session); } + const args:String = process.env.CHROME_ARGS || ""; + const wbot: Session = new Client({ session: sessionCfg, puppeteer: { executablePath: process.env.CHROME_BIN || undefined, // @ts-ignore - browserWSEndpoint: process.env.CHROME_WS || undefined + browserWSEndpoint: process.env.CHROME_WS || undefined, + args: args.split(' ') } }); diff --git a/docker-compose-browserless.yaml b/docker-compose-browserless.yaml new file mode 100644 index 0000000..5206683 --- /dev/null +++ b/docker-compose-browserless.yaml @@ -0,0 +1,17 @@ +version: '3' + +networks: + whaticket: + +services: + + backend: + environment: + - CHROME_WS=ws://chrome:3000 + + chrome: + image: browserless/chrome:latest + environment: + - MAX_CONCURRENT_SESSIONS=${MAX_CONCURRENT_SESSIONS:-1} + networks: + - whaticket \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index fdc0032..8a3f503 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -16,7 +16,9 @@ services: - DB_NAME=${MYSQL_DATABASE:-whaticket} - JWT_SECRET=${JWT_SECRET:-3123123213123} - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-75756756756} - - CHROME_WS=ws://chrome:3000 + - BACKEND_URL=${BACKEND_URL:-http://localhost:3000/api} + - FRONTEND_URL=${BACKEND_URL:-http://localhost:3000} + - CHROME_ARGS=--no-sandbox --disable-setuid-sandbox networks: - whaticket @@ -43,12 +45,5 @@ services: ports: - 3306:3306 restart: always - networks: - - whaticket - - chrome: - image: browserless/chrome:latest - environment: - - MAX_CONCURRENT_SESSIONS=${MAX_CONCURRENT_SESSIONS:-1} networks: - whaticket \ No newline at end of file