From 0aa6134d72100d384fa4d1d4c088af405903bab6 Mon Sep 17 00:00:00 2001 From: JandereDev Date: Sat, 5 Feb 2022 20:17:00 +0100 Subject: [PATCH] dockerize everything, prepare for deployment --- .env.example | 39 +++++++++++++++++++++++ .gitignore | 2 ++ api/Dockerfile | 13 ++++++++ api/package.json | 3 ++ api/yarn.lock | 5 +++ bot/Dockerfile | 2 +- docker-compose.yml.example | 65 ++++++++++++++++++++++++++++++++++++++ web/Dockerfile | 16 ++++++++++ web/src/App.tsx | 8 +++-- web/src/pages/Login.tsx | 4 +-- 10 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 .env.example create mode 100644 api/Dockerfile create mode 100644 docker-compose.yml.example create mode 100644 web/Dockerfile diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f9275b9 --- /dev/null +++ b/.env.example @@ -0,0 +1,39 @@ +# Copy this file to `.env.example` before editing + +### IMPORTANT: ### +# After changing `BOT_PREFIX` or `PUBLIC_API_URL`, +# you need to rebuild the web container: +# "docker-compose build web" + +# Set a secure password for your database. +# Keep in mind that you can't easily change this +# after initializing the database. +DB_PASS= + +# Your bot account's token. +BOT_TOKEN= + +# The default prefix, can be overridden by server owners. +# Leave empty to keep default ("/") +BOT_PREFIX= + +# Private token used by the bot to communicate +# with the API. Keep this private! +INTERNAL_API_TOKEN= + +# Comma separated list of user IDs. +# Be careful with the people you add here - +# They will be able to use /eval and /shell, +# which gives them access to your server! +BOT_OWNERS= + +# Optional: A Discord webhook URL which will be +# used to log certain events (bot started, etc). +LOG_WEBHOOK= + +# The URL from which your API and Web app are +# publicly reachable. Do not add a trailing +# slash to the URLs. + +PUBLIC_API_URL=http://localhost:9000 +PUBLIC_WEB_URL=http://localhost:8080 diff --git a/.gitignore b/.gitignore index a58e32a..0a54c7c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules dist .env yarn-error.log +docker-compose.yml +/db diff --git a/api/Dockerfile b/api/Dockerfile new file mode 100644 index 0000000..e29635c --- /dev/null +++ b/api/Dockerfile @@ -0,0 +1,13 @@ +FROM node:16 as build +WORKDIR /build/ +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +RUN yarn build + +FROM node:16 as prod +WORKDIR /app/ +COPY --from=build /build/package.json /build/yarn.lock ./ +COPY --from=build /build/dist ./dist +RUN yarn install --production --frozen-lockfile +CMD ["yarn", "start"] diff --git a/api/package.json b/api/package.json index 04c7546..87ec9b3 100644 --- a/api/package.json +++ b/api/package.json @@ -21,5 +21,8 @@ "log75": "^2.2.0", "monk": "^7.3.4", "ws": "^8.4.2" + }, + "devDependencies": { + "typescript": "^4.5.5" } } diff --git a/api/yarn.lock b/api/yarn.lock index 62d1e3f..fb6ac4c 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -634,6 +634,11 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typescript@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" diff --git a/bot/Dockerfile b/bot/Dockerfile index 6b4f85d..e29635c 100644 --- a/bot/Dockerfile +++ b/bot/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16 AS build +FROM node:16 as build WORKDIR /build/ COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile diff --git a/docker-compose.yml.example b/docker-compose.yml.example new file mode 100644 index 0000000..41af434 --- /dev/null +++ b/docker-compose.yml.example @@ -0,0 +1,65 @@ +# Copy this file to `docker-compose.yml` and modify it to your liking. +# Copy `.env.example` to `.env` to configure environment variables. + +version: "3.1" + +services: + bot: + build: ./bot + environment: + - DB_HOST=mongo:27017 + - DB_USERNAME=mogus + - DB_PASS + - DB_NAME=admin + - BOT_TOKEN + - BOT_OWNERS + - LOG_WEBHOOK + - NODE_ENV=production + - API_WS_URL=ws://api:9000/internal/ws + - API_WS_TOKEN=${INTERNAL_API_TOKEN} + - WEB_UI_URL=${PUBLIC_WEB_URL} + - BOT_PREFIX + depends_on: + - mongo + - api + restart: unless-stopped + + api: + build: ./api + environment: + - BOT_API_TOKEN=${INTERNAL_API_TOKEN} + - DB_HOST=mongo:27017 + - DB_USERNAME=mogus + - DB_PASS + - DB_NAME=admin + expose: + - 9000 + ports: + - 0.0.0.0:9000:9000 + restart: unless-stopped + + # If you prefer to host the web app on a different + # platform like Vercel, you can remove this part. + web: + build: + context: ./web + args: + - VITE_API_URL=${PUBLIC_API_URL} + - VITE_BOT_PREFIX=${BOT_PREFIX} + ports: + - 0.0.0.0:8080:80 + restart: unless-stopped + + mongo: + image: mongo + environment: + - MONGO_INITDB_ROOT_USERNAME=mogus + - MONGO_INITDB_ROOT_PASSWORD=${DB_PASS} + expose: + - 27017 + # If you want to access the database from outside + #ports: + # - "0.0.0.0:36602:27017" + volumes: + - ./db:/data/db:rw + restart: unless-stopped diff --git a/web/Dockerfile b/web/Dockerfile new file mode 100644 index 0000000..e5ba12c --- /dev/null +++ b/web/Dockerfile @@ -0,0 +1,16 @@ +FROM node:16 as build +ARG VITE_API_URL +ARG VITE_BOT_PREFIX +WORKDIR /build/ +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +RUN yarn build + +FROM node:16 as prod +WORKDIR /app/ +COPY --from=build /build/package.json /build/yarn.lock ./ +COPY --from=build /build/dist ./dist +RUN yarn add --production --frozen-lockfile vite +# Running this with bash -c because it won't exit on ctrl+c otherwise +CMD ["bash", "-c", "yarn preview --port=80 --strictPort=true --clearScreen=false --host"] diff --git a/web/src/App.tsx b/web/src/App.tsx index 56a0279..2180b24 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -7,7 +7,11 @@ import RequireAuth from './components/RequireAuth'; import DashboardHome from './pages/DashboardHome'; import ServerDashboard from './pages/ServerDashboard'; -const API_URL = 'http://localhost:9000'; +const API_URL = import.meta.env.VITE_API_URL?.toString() + || 'http://localhost:9000'; + +const BOT_PREFIX = import.meta.env.VITE_BOT_PREFIX?.toString() + || '/'; function App() { return ( @@ -22,4 +26,4 @@ function App() { } export default App; -export { API_URL } +export { API_URL, BOT_PREFIX } diff --git a/web/src/pages/Login.tsx b/web/src/pages/Login.tsx index a8541d1..2828d2d 100644 --- a/web/src/pages/Login.tsx +++ b/web/src/pages/Login.tsx @@ -5,7 +5,7 @@ import { Button } from '@revoltchat/ui/lib/components/atoms/inputs/Button'; import { InputBox } from '@revoltchat/ui/lib/components/atoms/inputs/InputBox'; import { H1 } from '@revoltchat/ui/lib/components/atoms/heading/H1'; import { H2 } from '@revoltchat/ui/lib/components/atoms/heading/H2'; -import { API_URL } from "../App"; +import { API_URL, BOT_PREFIX } from "../App"; const Login: FunctionComponent = () => { const [username, setUsername] = useState(''); @@ -66,7 +66,7 @@ const Login: FunctionComponent = () => {

Your code: {code}

Run - /login {code} + {BOT_PREFIX}login {code} in any server using AutoMod, then