Simplify dev docker setup
This commit is contained in:
parent
b655085115
commit
ce2255b6b7
13 changed files with 65 additions and 97 deletions
25
.env.example
25
.env.example
|
@ -1,36 +1,39 @@
|
||||||
KEY=32_character_encryption_key
|
# 32 character encryption key
|
||||||
|
KEY=
|
||||||
|
|
||||||
|
# Values from the Discord developer portal
|
||||||
CLIENT_ID=
|
CLIENT_ID=
|
||||||
CLIENT_SECRET=
|
CLIENT_SECRET=
|
||||||
BOT_TOKEN=
|
BOT_TOKEN=
|
||||||
|
|
||||||
OAUTH_CALLBACK_URL=
|
DASHBOARD_URL=https://localhost:3300
|
||||||
DASHBOARD_DOMAIN=
|
API_URL=https://localhost:3300/api
|
||||||
API_DOMAIN=
|
|
||||||
|
# When using the Docker-based development environment, this is only used internally. The API will be available at localhost:DOCKER_DEV_WEB_PORT/api.
|
||||||
API_PORT=3000
|
API_PORT=3000
|
||||||
|
|
||||||
|
# Only required if relevant feature is used
|
||||||
|
#PHISHERMAN_API_KEY=
|
||||||
|
|
||||||
#
|
#
|
||||||
# DOCKER (DEVELOPMENT)
|
# DOCKER (DEVELOPMENT)
|
||||||
#
|
#
|
||||||
|
|
||||||
DOCKER_WEB_PORT=443
|
DOCKER_DEV_WEB_PORT=3300
|
||||||
|
|
||||||
# The MySQL database running in the container is exposed to the host on this port,
|
# The MySQL database running in the container is exposed to the host on this port,
|
||||||
# allowing access with database tools such as DBeaver
|
# allowing access with database tools such as DBeaver
|
||||||
DOCKER_MYSQL_PORT=3001
|
DOCKER_DEV_MYSQL_PORT=3001
|
||||||
# Password for the Zeppelin database user
|
# Password for the Zeppelin database user
|
||||||
DOCKER_MYSQL_PASSWORD=
|
DOCKER_DEV_MYSQL_PASSWORD=
|
||||||
# Password for the MySQL root user
|
# Password for the MySQL root user
|
||||||
DOCKER_MYSQL_ROOT_PASSWORD=
|
DOCKER_DEV_MYSQL_ROOT_PASSWORD=
|
||||||
|
|
||||||
# The development environment container has an SSH server that you can connect to.
|
# The development environment container has an SSH server that you can connect to.
|
||||||
# This is the port that server is exposed to the host on.
|
# This is the port that server is exposed to the host on.
|
||||||
DOCKER_DEV_SSH_PORT=3002
|
DOCKER_DEV_SSH_PORT=3002
|
||||||
DOCKER_DEV_SSH_PASSWORD=password
|
DOCKER_DEV_SSH_PASSWORD=password
|
||||||
|
|
||||||
# Only required if relevant feature is used
|
|
||||||
#PHISHERMAN_API_KEY=
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# PRODUCTION
|
# PRODUCTION
|
||||||
#
|
#
|
||||||
|
|
|
@ -88,7 +88,7 @@ export function initAuth(app: express.Express) {
|
||||||
tokenURL: "https://discord.com/api/oauth2/token",
|
tokenURL: "https://discord.com/api/oauth2/token",
|
||||||
clientID: env.CLIENT_ID,
|
clientID: env.CLIENT_ID,
|
||||||
clientSecret: env.CLIENT_SECRET,
|
clientSecret: env.CLIENT_SECRET,
|
||||||
callbackURL: env.OAUTH_CALLBACK_URL,
|
callbackURL: `${env.API_URL}/auth/oauth-callback`,
|
||||||
scope: ["identify"],
|
scope: ["identify"],
|
||||||
},
|
},
|
||||||
async (accessToken, refreshToken, profile, cb) => {
|
async (accessToken, refreshToken, profile, cb) => {
|
||||||
|
@ -117,9 +117,9 @@ export function initAuth(app: express.Express) {
|
||||||
passport.authenticate("oauth2", { failureRedirect: "/", session: false }),
|
passport.authenticate("oauth2", { failureRedirect: "/", session: false }),
|
||||||
(req: Request, res: Response) => {
|
(req: Request, res: Response) => {
|
||||||
if (req.user && req.user.apiKey) {
|
if (req.user && req.user.apiKey) {
|
||||||
res.redirect(`https://${env.DASHBOARD_DOMAIN}/login-callback/?apiKey=${req.user.apiKey}`);
|
res.redirect(`${env.DASHBOARD_URL}/login-callback/?apiKey=${req.user.apiKey}`);
|
||||||
} else {
|
} else {
|
||||||
res.redirect(`https://${env.DASHBOARD_DOMAIN}/login-callback/?error=noAccess`);
|
res.redirect(`${env.DASHBOARD_URL}/login-callback/?error=noAccess`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -14,7 +14,7 @@ const app = express();
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
cors({
|
cors({
|
||||||
origin: `https://${env.DASHBOARD_DOMAIN}`,
|
origin: env.DASHBOARD_URL,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
app.use(
|
app.use(
|
||||||
|
|
|
@ -11,17 +11,15 @@ const envType = z.object({
|
||||||
CLIENT_SECRET: z.string().length(32),
|
CLIENT_SECRET: z.string().length(32),
|
||||||
BOT_TOKEN: z.string().min(50),
|
BOT_TOKEN: z.string().min(50),
|
||||||
|
|
||||||
OAUTH_CALLBACK_URL: z.string().url(),
|
DASHBOARD_URL: z.string().url(),
|
||||||
DASHBOARD_DOMAIN: z.string(),
|
API_URL: z.string().url(),
|
||||||
API_DOMAIN: z.string(),
|
API_PORT: z.preprocess((v) => Number(v), z.number().min(1).max(65535)).default(3000),
|
||||||
|
|
||||||
STAFF: z.preprocess((v) => String(v).split(","), z.array(z.string())).optional(),
|
STAFF: z.preprocess((v) => String(v).split(","), z.array(z.string())).optional(),
|
||||||
|
|
||||||
PHISHERMAN_API_KEY: z.string().optional(),
|
PHISHERMAN_API_KEY: z.string().optional(),
|
||||||
|
|
||||||
API_PORT: z.preprocess((v) => Number(v), z.number().min(1).max(65535)),
|
DOCKER_DEV_MYSQL_PASSWORD: z.string().optional(), // Included here for the DB_PASSWORD default in development
|
||||||
|
|
||||||
DOCKER_MYSQL_PASSWORD: z.string().optional(), // Included here for the DB_PASSWORD default in development
|
|
||||||
|
|
||||||
DB_HOST: z.string().optional().default("mysql"),
|
DB_HOST: z.string().optional().default("mysql"),
|
||||||
DB_PORT: z
|
DB_PORT: z
|
||||||
|
@ -42,6 +40,6 @@ if (fs.existsSync(envPath)) {
|
||||||
|
|
||||||
export const env = envType.parse(toValidate);
|
export const env = envType.parse(toValidate);
|
||||||
|
|
||||||
if (env.DOCKER_MYSQL_PASSWORD && !env.DB_PASSWORD) {
|
if (env.DOCKER_DEV_MYSQL_PASSWORD && !env.DB_PASSWORD) {
|
||||||
env.DB_PASSWORD = env.DOCKER_MYSQL_PASSWORD;
|
env.DB_PASSWORD = env.DOCKER_DEV_MYSQL_PASSWORD;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { RootStore } from "./store";
|
import { RootStore } from "./store";
|
||||||
const apiUrl = `https://${process.env.API_DOMAIN}`;
|
const apiUrl = process.env.API_URL;
|
||||||
|
|
||||||
type QueryParamObject = { [key: string]: string | null };
|
type QueryParamObject = { [key: string]: string | null };
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ const isAuthenticated = async () => {
|
||||||
|
|
||||||
export const authGuard: NavigationGuard = async (to, from, next) => {
|
export const authGuard: NavigationGuard = async (to, from, next) => {
|
||||||
if (await isAuthenticated()) return next();
|
if (await isAuthenticated()) return next();
|
||||||
window.location.href = `https://${process.env.API_DOMAIN}/auth/login`;
|
window.location.href = `${process.env.API_URL}/auth/login`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loginCallbackGuard: NavigationGuard = async (to, from, next) => {
|
export const loginCallbackGuard: NavigationGuard = async (to, from, next) => {
|
||||||
|
@ -25,5 +25,5 @@ export const loginCallbackGuard: NavigationGuard = async (to, from, next) => {
|
||||||
|
|
||||||
export const authRedirectGuard: NavigationGuard = async (to, form, next) => {
|
export const authRedirectGuard: NavigationGuard = async (to, form, next) => {
|
||||||
if (await isAuthenticated()) return next("/dashboard");
|
if (await isAuthenticated()) return next("/dashboard");
|
||||||
window.location.href = `https://${process.env.API_DOMAIN}/auth/login`;
|
window.location.href = `${process.env.API_URL}/auth/login`;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ Vue.mixin({
|
||||||
return {
|
return {
|
||||||
get env() {
|
get env() {
|
||||||
return Object.freeze({
|
return Object.freeze({
|
||||||
API_URL: `https://${process.env.API_DOMAIN}`,
|
API_URL: process.env.API_URL,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
DOCKER_UID="$(id -u)" DOCKER_GID="$(id -g)" docker-compose --env-file ./.env -f ./docker/development/docker-compose.yml "$@"
|
DOCKER_UID="$(id -u)" DOCKER_STAY_RUNNING=1 docker-compose --env-file ./.env -f ./docker/development/docker-compose.yml "$@"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
## Connecting with VSCode
|
## Connecting with VSCode
|
||||||
1. Install the `Remote - SSH` plugin
|
1. Install the `Remote - SSH` plugin
|
||||||
2. Run `Remote-SSH: Connect to Host...`
|
2. Run `Remote-SSH: Connect to Host...`
|
||||||
* As the address, use `ubuntu@127.0.0.1:3002` where `3002` matches `DOCKER_DEV_SSH_PORT` in `.env`
|
* As the address, use `ubuntu@127.0.0.1:3002` (where `3002` matches `DOCKER_DEV_SSH_PORT` in `.env`)
|
||||||
* Use the password specified in `.env` as `DOCKER_DEV_SSH_PASSWORD`
|
* Use the password specified in `.env` as `DOCKER_DEV_SSH_PASSWORD`
|
||||||
3. Once connected, click `Open folder...` and select `/home/ubuntu/zeppelin`
|
3. Once connected, click `Open folder...` and select `/home/ubuntu/zeppelin`
|
||||||
|
|
||||||
|
@ -25,3 +25,6 @@ These commands are run inside the dev container. You should be able to just open
|
||||||
1. `cd ~/zeppelin/dashboard`
|
1. `cd ~/zeppelin/dashboard`
|
||||||
2. `npm ci`
|
2. `npm ci`
|
||||||
3. `npm run watch-build`
|
3. `npm run watch-build`
|
||||||
|
|
||||||
|
## Opening the dashboard
|
||||||
|
Browse to https://localhost:3300 to view the dashboard
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FROM ubuntu:20.04
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
ARG DOCKER_UID
|
ARG DOCKER_UID=1000
|
||||||
ARG DOCKER_DEV_SSH_PASSWORD
|
ARG DOCKER_DEV_SSH_PASSWORD
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
@ -13,7 +13,7 @@ RUN apt-get install -y sudo git curl
|
||||||
# Set up SSH access
|
# Set up SSH access
|
||||||
RUN apt-get install -y openssh-server iptables
|
RUN apt-get install -y openssh-server iptables
|
||||||
RUN mkdir /var/run/sshd
|
RUN mkdir /var/run/sshd
|
||||||
RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u "${DOCKER_UID}" ubuntu
|
RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u $DOCKER_UID ubuntu
|
||||||
RUN echo "ubuntu:${DOCKER_DEV_SSH_PASSWORD}" | chpasswd
|
RUN echo "ubuntu:${DOCKER_DEV_SSH_PASSWORD}" | chpasswd
|
||||||
|
|
||||||
# Set up proper permissions for volumes
|
# Set up proper permissions for volumes
|
||||||
|
|
|
@ -9,54 +9,33 @@ services:
|
||||||
build:
|
build:
|
||||||
context: ./nginx
|
context: ./nginx
|
||||||
args:
|
args:
|
||||||
API_DOMAIN: ${API_DOMAIN:?Missing API_DOMAIN}
|
DOCKER_DEV_WEB_PORT: ${DOCKER_DEV_WEB_PORT:?Missing DOCKER_DEV_WEB_PORT}
|
||||||
API_PORT: ${API_PORT:?Missing API_PORT}
|
API_PORT: ${API_PORT:?Missing API_PORT}
|
||||||
DASHBOARD_DOMAIN: ${DASHBOARD_DOMAIN:?Missing DASHBOARD_DOMAIN}
|
|
||||||
ports:
|
ports:
|
||||||
- ${DOCKER_WEB_PORT:?Missing DOCKER_WEB_PORT}:443
|
- "${DOCKER_DEV_WEB_PORT:?Missing DOCKER_DEV_WEB_PORT}:443"
|
||||||
volumes:
|
volumes:
|
||||||
- ../../:/zeppelin
|
- ../../:/zeppelin
|
||||||
|
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql:8.0
|
image: mysql:8.0
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: ${DOCKER_MYSQL_ROOT_PASSWORD?:Missing DOCKER_MYSQL_ROOT_PASSWORD}
|
MYSQL_ROOT_PASSWORD: ${DOCKER_DEV_MYSQL_ROOT_PASSWORD?:Missing DOCKER_DEV_MYSQL_ROOT_PASSWORD}
|
||||||
MYSQL_DATABASE: zeppelin
|
MYSQL_DATABASE: zeppelin
|
||||||
MYSQL_USER: zeppelin
|
MYSQL_USER: zeppelin
|
||||||
MYSQL_PASSWORD: ${DOCKER_MYSQL_PASSWORD?:Missing DOCKER_MYSQL_PASSWORD}
|
MYSQL_PASSWORD: ${DOCKER_DEV_MYSQL_PASSWORD?:Missing DOCKER_DEV_MYSQL_PASSWORD}
|
||||||
ports:
|
ports:
|
||||||
- ${DOCKER_MYSQL_PORT:?Missing DOCKER_MYSQL_PORT}:3306
|
- ${DOCKER_DEV_MYSQL_PORT:?Missing DOCKER_DEV_MYSQL_PORT}:3306
|
||||||
volumes:
|
volumes:
|
||||||
- mysql-data:/var/lib/mysql
|
- mysql-data:/var/lib/mysql
|
||||||
command: --authentication-policy=mysql_native_password
|
command: --authentication-policy=mysql_native_password
|
||||||
#
|
|
||||||
# backend:
|
|
||||||
# image: node:16
|
|
||||||
# user: "${UID:?Missing UID}:${GID:?Missing GID}"
|
|
||||||
# working_dir: /zeppelin/backend
|
|
||||||
# restart: always
|
|
||||||
# depends_on:
|
|
||||||
# - mysql
|
|
||||||
# volumes:
|
|
||||||
# - ./:/zeppelin
|
|
||||||
# command: sh -c "npm run migrate-dev && npm run watch"
|
|
||||||
#
|
|
||||||
# dashboard:
|
|
||||||
# image: node:16
|
|
||||||
# user: "${UID:?Missing UID}:${GID:?Missing GID}"
|
|
||||||
# working_dir: /zeppelin/dashboard
|
|
||||||
# restart: always
|
|
||||||
# volumes:
|
|
||||||
# - ./:/zeppelin
|
|
||||||
# command: sh -c "npm run watch-build"
|
|
||||||
|
|
||||||
devenv:
|
devenv:
|
||||||
build:
|
build:
|
||||||
context: ./devenv
|
context: ./devenv
|
||||||
args:
|
args:
|
||||||
DOCKER_UID: ${DOCKER_UID:?Missing DOCKER_UID}
|
|
||||||
DOCKER_GID: ${DOCKER_GID:?Missing DOCKER_GID}
|
|
||||||
DOCKER_DEV_SSH_PASSWORD: ${DOCKER_DEV_SSH_PASSWORD:?Missing DOCKER_DEV_SSH_PASSWORD}
|
DOCKER_DEV_SSH_PASSWORD: ${DOCKER_DEV_SSH_PASSWORD:?Missing DOCKER_DEV_SSH_PASSWORD}
|
||||||
|
DOCKER_UID: ${DOCKER_UID:?Missing DOCKER_UID}
|
||||||
|
DOCKER_STAY_RUNNING: ${DOCKER_STAY_RUNNING}
|
||||||
ports:
|
ports:
|
||||||
- "${DOCKER_DEV_SSH_PORT:?Missing DOCKER_DEV_SSH_PORT}:22"
|
- "${DOCKER_DEV_SSH_PORT:?Missing DOCKER_DEV_SSH_PORT}:22"
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
FROM nginx
|
FROM nginx
|
||||||
|
|
||||||
ARG API_DOMAIN
|
|
||||||
ARG DASHBOARD_DOMAIN
|
|
||||||
ARG API_PORT
|
ARG API_PORT
|
||||||
|
ARG DOCKER_DEV_API_PORT
|
||||||
|
ARG DOCKER_DEV_DASHBOARD_PORT
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y openssl
|
RUN apt-get update && apt-get install -y openssl
|
||||||
RUN openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/api-cert.key -out /etc/ssl/certs/api-cert.pem -days 3650 -subj '/CN=*.${API_DOMAIN}' -nodes
|
RUN openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/localhost-cert.key -out /etc/ssl/certs/localhost-cert.pem -days 3650 -subj '/CN=localhost' -nodes
|
||||||
RUN openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/dashboard-cert.key -out /etc/ssl/certs/dashboard-cert.pem -days 3650 -subj '/CN=*.${DASHBOARD_DOMAIN}' -nodes
|
|
||||||
|
|
||||||
COPY ./default.conf /etc/nginx/conf.d/default.conf
|
COPY ./default.conf /etc/nginx/conf.d/default.conf
|
||||||
RUN sed -ir "s/_API_DOMAIN_/$(echo ${API_DOMAIN} | sed 's/\./\\./g')/g" /etc/nginx/conf.d/default.conf
|
|
||||||
RUN sed -ir "s/_DASHBOARD_DOMAIN_/$(echo ${DASHBOARD_DOMAIN} | sed 's/\./\\./g')/g" /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/_API_PORT_/${API_PORT}/g" /etc/nginx/conf.d/default.conf
|
||||||
|
|
|
@ -1,36 +1,7 @@
|
||||||
server {
|
server {
|
||||||
listen 443 ssl http2;
|
listen 443 ssl http2;
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:443 ssl http2;
|
||||||
server_name _API_DOMAIN_;
|
server_name localhost;
|
||||||
|
|
||||||
|
|
||||||
location / {
|
|
||||||
# Using a variable here stops nginx from crashing if the dev container is restarted or becomes otherwise unavailable
|
|
||||||
set $backend_upstream "http://devenv:_API_PORT_";
|
|
||||||
# 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;
|
|
||||||
|
|
||||||
client_max_body_size 200M;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssl_certificate /etc/ssl/certs/api-cert.pem;
|
|
||||||
ssl_certificate_key /etc/ssl/private/api-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;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
listen [::]:443 ssl http2;
|
|
||||||
server_name _DASHBOARD_DOMAIN_;
|
|
||||||
|
|
||||||
root /zeppelin/dashboard/dist;
|
root /zeppelin/dashboard/dist;
|
||||||
|
|
||||||
|
@ -39,8 +10,25 @@ server {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/ssl/certs/dashboard-cert.pem;
|
# Using a variable here stops nginx from crashing if the dev container is restarted or becomes otherwise unavailable
|
||||||
ssl_certificate_key /etc/ssl/private/dashboard-cert.key;
|
set $backend_upstream "http://devenv:_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/localhost-cert.pem;
|
||||||
|
ssl_certificate_key /etc/ssl/private/localhost-cert.key;
|
||||||
|
|
||||||
ssl_session_timeout 1d;
|
ssl_session_timeout 1d;
|
||||||
ssl_session_cache shared:MozSSL:10m;
|
ssl_session_cache shared:MozSSL:10m;
|
||||||
|
|
Loading…
Add table
Reference in a new issue