Early work on prod container

This commit is contained in:
Dragory 2022-07-16 22:16:34 +03:00
parent 17fa857609
commit 91f54424ed
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
8 changed files with 132 additions and 9 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "Zeppelin Development", "name": "Zeppelin Development",
"dockerComposeFile": "../docker-compose.yml", "dockerComposeFile": "../docker-compose.development.yml",
"service": "devenv", "service": "devenv",
"remoteUser": "ubuntu", "remoteUser": "ubuntu",

View file

@ -38,12 +38,16 @@ DOCKER_DEV_SSH_PASSWORD=password
#DOCKER_DEV_UID=1000 #DOCKER_DEV_UID=1000
# #
# PRODUCTION # DOCKER (PRODUCTION)
# #
# In production, the newest code is pulled from a repository DOCKER_PROD_DOMAIN=
# Specify that repository URL here DOCKER_PROD_WEB_PORT=443
#PRODUCTION_REPOSITORY=https://github.com/ZeppelinBot/Zeppelin.git DOCKER_PROD_MYSQL_PORT=3001
# Password for the Zeppelin database user
DOCKER_PROD_MYSQL_PASSWORD=
# Password for the MySQL root user
DOCKER_PROD_MYSQL_ROOT_PASSWORD=
# You only need to set these if you're running an external database. # You only need to set these if you're running an external database.
# In a standard setup, the database is run in a docker container. # In a standard setup, the database is run in a docker container.

View file

@ -14,9 +14,9 @@
"start-api-prod": "cross-env NODE_ENV=production node -r ./register-tsconfig-paths.js --unhandled-rejections=strict --enable-source-maps --stack-trace-limit=30 dist/backend/src/api/index.js", "start-api-prod": "cross-env NODE_ENV=production node -r ./register-tsconfig-paths.js --unhandled-rejections=strict --enable-source-maps --stack-trace-limit=30 dist/backend/src/api/index.js",
"watch-api": "cross-env NODE_ENV=development tsc-watch --onSuccess \"npm run start-api-dev\"", "watch-api": "cross-env NODE_ENV=development tsc-watch --onSuccess \"npm run start-api-dev\"",
"typeorm": "node -r ./register-tsconfig-paths.js ./node_modules/typeorm/cli.js", "typeorm": "node -r ./register-tsconfig-paths.js ./node_modules/typeorm/cli.js",
"migrate-prod": "npm run typeorm -- migration:run", "migrate-prod": "cross-env NODE_ENV=production npm run typeorm -- migration:run",
"migrate-dev": "npm run build && npm run typeorm -- migration:run", "migrate-dev": "npm run build && npm run typeorm -- migration:run",
"migrate-rollback-prod": "npm run typeorm -- migration:revert", "migrate-rollback-prod": "cross-env NODE_ENV=production npm run typeorm -- migration:revert",
"migrate-rollback-dev": "npm run build && npm run typeorm -- migration:revert", "migrate-rollback-dev": "npm run build && npm run typeorm -- migration:revert",
"test": "npm run build && npm run run-tests", "test": "npm run build && npm run run-tests",
"run-tests": "ava", "run-tests": "ava",

View file

@ -20,6 +20,7 @@ const envType = z.object({
PHISHERMAN_API_KEY: z.string().optional(), PHISHERMAN_API_KEY: z.string().optional(),
DOCKER_DEV_MYSQL_PASSWORD: z.string().optional(), // Included here for the DB_PASSWORD default in development DOCKER_DEV_MYSQL_PASSWORD: z.string().optional(), // Included here for the DB_PASSWORD default in development
DOCKER_PROD_MYSQL_PASSWORD: z.string().optional(), // Included here for the DB_PASSWORD default in production
DB_HOST: z.string().optional().default("mysql"), DB_HOST: z.string().optional().default("mysql"),
DB_PORT: z DB_PORT: z
@ -40,6 +41,10 @@ if (fs.existsSync(envPath)) {
export const env = envType.parse(toValidate); export const env = envType.parse(toValidate);
if (env.DOCKER_DEV_MYSQL_PASSWORD && !env.DB_PASSWORD) { if (!env.DB_PASSWORD) {
if (process.env.NODE_ENV === "production" && env.DOCKER_PROD_MYSQL_PASSWORD) {
env.DB_PASSWORD = env.DOCKER_PROD_MYSQL_PASSWORD;
} else if (env.DOCKER_DEV_MYSQL_PASSWORD) {
env.DB_PASSWORD = env.DOCKER_DEV_MYSQL_PASSWORD; env.DB_PASSWORD = env.DOCKER_DEV_MYSQL_PASSWORD;
} }
}

View file

@ -1,4 +1,5 @@
version: '3' version: '3'
name: zeppelin-dev
volumes: volumes:
mysql-data: {} mysql-data: {}
vscode-remote: {} vscode-remote: {}

View file

@ -0,0 +1,63 @@
version: '3'
name: zeppelin-prod
volumes:
mysql-data: {}
services:
nginx:
build:
context: ./docker/production/nginx
args:
API_PORT: ${API_PORT:?Missing API_PORT}
DOCKER_PROD_DOMAIN: ${DOCKER_PROD_DOMAIN:?Missing DOCKER_PROD_DOMAIN}
ports:
- "${DOCKER_PROD_WEB_PORT:?Missing DOCKER_PROD_WEB_PORT}:443"
volumes:
- ./:/zeppelin
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DOCKER_PROD_MYSQL_ROOT_PASSWORD?:Missing DOCKER_PROD_MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: zeppelin
MYSQL_USER: zeppelin
MYSQL_PASSWORD: ${DOCKER_PROD_MYSQL_PASSWORD?:Missing DOCKER_PROD_MYSQL_PASSWORD}
ports:
- ${DOCKER_PROD_MYSQL_PORT:?Missing DOCKER_PROD_MYSQL_PORT}:3306
volumes:
- mysql-data:/var/lib/mysql
command: --authentication-policy=mysql_native_password
prepare_backend:
image: node:16.16
depends_on:
- mysql
volumes:
- ./:/zeppelin
user: node
command: |-
bash -c "cd /zeppelin/backend && npm ci && npm run build && npm run migrate-prod"
api:
image: node:16.16
restart: on-failure
depends_on:
- prepare_backend
volumes:
- ./:/zeppelin
# Wait for the build_backend container to finish before starting the bot
# See: https://github.com/docker/compose/issues/5007#issuecomment-335815508
user: node
command: |-
bash -c ' \
while ping -c1 prepare_backend &>/dev/null; do sleep 1; done; \
cd /zeppelin/backend && npm run start-api-prod \
'
build_dashboard:
image: node:16.16
volumes:
- ./:/zeppelin
user: node
command: |-
bash -c "cd /zeppelin/dashboard && npm ci && npm run build"

View file

@ -0,0 +1,11 @@
FROM nginx
ARG API_PORT
ARG DOCKER_PROD_DOMAIN
RUN apt-get update && apt-get install -y openssl
RUN openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/zeppelin-self-signed-cert.key -out /etc/ssl/certs/zeppelin-self-signed-cert.pem -days 3650 -subj "/CN=${DOCKER_PROD_DOMAIN}" -nodes
COPY ./default.conf /etc/nginx/conf.d/default.conf
RUN sed -ir "s/_API_PORT_/${API_PORT}/g" /etc/nginx/conf.d/default.conf
RUN sed -ir "s/_DOCKER_PROD_DOMAIN_/${DOCKER_PROD_DOMAIN}/g" /etc/nginx/conf.d/default.conf

View file

@ -0,0 +1,39 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _DOCKER_PROD_DOMAIN_;
root /zeppelin/dashboard/dist;
location / {
index index.html;
try_files $uri $uri/ /index.html;
}
# Using a variable here stops nginx from crashing if the dev container is restarted or becomes otherwise unavailable
set $backend_upstream "http://api:_API_PORT_";
location /api {
# Remove /api/ from the beginning when passing the path to the API process
rewrite /api(/.*)$ $1 break;
# Using a variable in proxy_pass also requires resolver to be set.
# This is the address of the internal docker compose DNS server.
resolver 127.0.0.11;
proxy_pass $backend_upstream$uri$is_args$args;
proxy_redirect off;
client_max_body_size 200M;
}
ssl_certificate /etc/ssl/certs/zeppelin-self-signed-cert.pem;
ssl_certificate_key /etc/ssl/private/zeppelin-self-signed-cert.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
}