This commit is contained in:
8
docker/BUILD.md
Normal file
8
docker/BUILD.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Build locally
|
||||
|
||||
From root directoy:
|
||||
|
||||
```
|
||||
docker buildx build --progress=plain --no-cache -t monkeytype/monkeytype-backend:latest . -f ./docker/backend/Dockerfile
|
||||
docker buildx build --progress=plain --no-cache -t monkeytype/monkeytype-frontend:latest . -f ./docker/frontend/Dockerfile
|
||||
```
|
||||
19
docker/backend-configuration.json
Normal file
19
docker/backend-configuration.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"configuration": {
|
||||
"results": {
|
||||
"savingEnabled": true
|
||||
},
|
||||
"users": {
|
||||
"signUp": false,
|
||||
"profiles": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"dailyLeaderboards": {
|
||||
"enabled": false
|
||||
},
|
||||
"leaderboards": {
|
||||
"minTimeTyping": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
52
docker/backend/Dockerfile
Normal file
52
docker/backend/Dockerfile
Normal file
@@ -0,0 +1,52 @@
|
||||
FROM node:24.11.0-alpine3.22 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
#copy
|
||||
COPY ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "turbo.json", "./"]
|
||||
COPY packages packages
|
||||
COPY backend backend
|
||||
|
||||
#gimme pnpm + build
|
||||
RUN npm i -g pnpm@10.28.1 && \
|
||||
pnpm i --frozen-lockfile && \
|
||||
npm run build
|
||||
|
||||
#deploy (install all non-dev dependencies in a single node_module folder)
|
||||
RUN pnpm deploy --legacy --filter backend --prod /prod/backend
|
||||
|
||||
#---------------------------------
|
||||
|
||||
## target image
|
||||
FROM node:24.11.0-alpine3.22
|
||||
|
||||
## get server_version from build-arg, default to UNKNOWN
|
||||
ARG server_version=UNKNOWN
|
||||
|
||||
# COPY to target
|
||||
COPY --from=builder /prod/backend/node_modules /app/backend/node_modules
|
||||
COPY --from=builder /prod/backend/dist /app/backend/dist
|
||||
COPY --from=builder /prod/backend/email-templates /app/backend/email-templates
|
||||
COPY --from=builder /prod/backend/redis-scripts /app/backend/redis-scripts
|
||||
COPY --from=builder /prod/backend/private /app/backend/private
|
||||
|
||||
## to build directory
|
||||
WORKDIR /app/backend/dist
|
||||
|
||||
## logs
|
||||
RUN mkdir -p /app/backend/dist/logs
|
||||
|
||||
COPY ["docker/backend/entry-point.sh", "./"]
|
||||
|
||||
RUN echo "${server_version}" > /app/backend/dist/server.version
|
||||
|
||||
#run in prod mode, but don't require anti-cheat, email client or firebase
|
||||
ENV MODE=prod
|
||||
ENV BYPASS_ANTICHEAT=true
|
||||
ENV BYPASS_EMAILCLIENT=true
|
||||
ENV BYPASS_FIREBASE=true
|
||||
|
||||
EXPOSE 5005
|
||||
USER node
|
||||
|
||||
CMD [ "/bin/sh", "./entry-point.sh" ]
|
||||
2
docker/backend/entry-point.sh
Normal file
2
docker/backend/entry-point.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
node server.js
|
||||
101
docker/docker-compose.yml
Normal file
101
docker/docker-compose.yml
Normal file
@@ -0,0 +1,101 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
monkeytype-frontend:
|
||||
container_name: monkeytype-frontend
|
||||
image: monkeytype/monkeytype-frontend:latest
|
||||
ports:
|
||||
- "${HTTP_PORT:-8080}:80"
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
monkeytype-backend:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- path: ./.env
|
||||
required: true
|
||||
environment:
|
||||
- FIREBASE_APIKEY=${FIREBASE_APIKEY:-}
|
||||
- FIREBASE_AUTHDOMAIN=${FIREBASE_AUTHDOMAIN:-}
|
||||
- FIREBASE_PROJECTID=${FIREBASE_PROJECTID:-}
|
||||
- FIREBASE_STORAGEBUCKET=${FIREBASE_STORAGEBUCKET:-}
|
||||
- FIREBASE_MESSAGINGSENDERID=${FIREBASE_MESSAGINGSENDERID:-}
|
||||
- FIREBASE_APPID=${FIREBASE_APPID:-}
|
||||
- MONKEYTYPE_BACKENDURL=${MONKEYTYPE_BACKENDURL}
|
||||
- RECAPTCHA_SITE_KEY=${RECAPTCHA_SITE_KEY:-}
|
||||
|
||||
monkeytype-backend:
|
||||
container_name: monkeytype-backend
|
||||
image: monkeytype/monkeytype-backend:latest
|
||||
ports:
|
||||
- "${BACKEND_PORT:-5005}:5005"
|
||||
restart: on-failure
|
||||
environment:
|
||||
- DB_NAME=monkeytype
|
||||
- DB_URI=mongodb://monkeytype-mongodb:27017
|
||||
- REDIS_URI=redis://monkeytype-redis:6379
|
||||
- FRONTEND_URL=${MONKEYTYPE_FRONTENDURL}
|
||||
- RECAPTCHA_SECRET=${RECAPTCHA_SECRET:-}
|
||||
- EMAIL_HOST=${EMAIL_HOST:-}
|
||||
- EMAIL_PORT=${EMAIL_PORT:-}
|
||||
- EMAIL_USER=${EMAIL_USER:-}
|
||||
- EMAIL_PASS=${EMAIL_PASS:-}
|
||||
- EMAIL_FROM=${EMAIL_FROM:-}
|
||||
volumes:
|
||||
#uncomment to enable the account system, check the SELF_HOSTING.md file
|
||||
#- type: bind
|
||||
# source: ./serviceAccountKey.json
|
||||
# target: /app/backend/src/credentials/serviceAccountKey.json
|
||||
# read_only: true
|
||||
- type: bind
|
||||
source: ./backend-configuration.json
|
||||
target: /app/backend/dist/backend-configuration.json
|
||||
read_only: true
|
||||
depends_on:
|
||||
monkeytype-redis:
|
||||
condition: service_healthy
|
||||
monkeytype-mongodb:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "nc", "-z", "-v", "localhost", "5005"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
start_period: 5s
|
||||
|
||||
monkeytype-redis:
|
||||
container_name: monkeytype-redis
|
||||
image: redis:6.2.6
|
||||
#uncomment if you want to expose the redis server
|
||||
#ports:
|
||||
# - "${REDIS_PORT:-6379}:6379"
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
start_period: 10s
|
||||
|
||||
monkeytype-mongodb:
|
||||
container_name: monkeytype-mongodb
|
||||
image: mongo:5.0.13
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- mongo-data:/data/db
|
||||
#uncomment if you want to expose the mongodb server
|
||||
#ports:
|
||||
# - "${MONGO_PORT:-27017}:27017"
|
||||
healthcheck:
|
||||
test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
mongo-data:
|
||||
name: monkeytype_mongo_data
|
||||
redis-data:
|
||||
name: monkeytype_redis_data
|
||||
44
docker/example.env
Normal file
44
docker/example.env
Normal file
@@ -0,0 +1,44 @@
|
||||
# Copy this file to `.env` before starting the containers
|
||||
|
||||
### === Required Config ===
|
||||
|
||||
# URL of the frontend (accessible by browser)
|
||||
MONKEYTYPE_FRONTENDURL=http://myserver:8080
|
||||
|
||||
# URL of the backend (accessible by browser)
|
||||
MONKEYTYPE_BACKENDURL=http://myserver:5005
|
||||
|
||||
### === Optional: Google reCAPTCHA ===
|
||||
|
||||
# Default keys below work for localhost/private instances
|
||||
# RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
# RECAPTCHA_SECRET=6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
|
||||
|
||||
RECAPTCHA_SITE_KEY=
|
||||
RECAPTCHA_SECRET=
|
||||
|
||||
### === Optional: Firebase ===
|
||||
|
||||
# Uncomment if using user accounts
|
||||
# FIREBASE_APIKEY=AIzaSy********
|
||||
# FIREBASE_AUTHDOMAIN=your-app.firebaseapp.com
|
||||
# FIREBASE_PROJECTID=your-app
|
||||
# FIREBASE_STORAGEBUCKET=your-app.appspot.com
|
||||
# FIREBASE_MESSAGINGSENDERID=1234567890
|
||||
# FIREBASE_APPID=1:1234567890:web:abcdef123456
|
||||
|
||||
### === Optional: Email Server ===
|
||||
# Enables email (e.g. password reset)
|
||||
|
||||
# EMAIL_HOST=smtp.mailserver.com
|
||||
# EMAIL_USER=your@email.com
|
||||
# EMAIL_PASS=password
|
||||
# EMAIL_PORT=465
|
||||
# EMAIL_FROM="Support <noreply@yourdomain.com>"
|
||||
|
||||
### === Optional: Custom Ports ===
|
||||
|
||||
# HTTP_PORT=8080
|
||||
# BACKEND_PORT=5005
|
||||
# REDIS_PORT=6379
|
||||
# MONGO_PORT=27017
|
||||
29
docker/frontend/Dockerfile
Normal file
29
docker/frontend/Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
||||
FROM node:24.11.0-alpine3.22 AS builder
|
||||
WORKDIR /app
|
||||
|
||||
#ENV
|
||||
ENV BACKEND_URL=###MONKEYTYPE_BACKENDURL### RECAPTCHA_SITE_KEY=###RECAPTCHA_SITE_KEY###
|
||||
|
||||
#COPY
|
||||
COPY ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "turbo.json", "./"]
|
||||
COPY packages packages
|
||||
COPY frontend frontend
|
||||
|
||||
COPY docker/frontend/firebase-config-live.ts frontend/src/ts/constants/firebase-config.ts
|
||||
COPY docker/frontend/firebase-config-live.ts frontend/src/ts/constants/firebase-config-live.ts
|
||||
|
||||
#gimme pnpm + build
|
||||
RUN npm i -g pnpm && \
|
||||
pnpm i --frozen-lockfile && \
|
||||
npm run build
|
||||
|
||||
# COPY to target
|
||||
FROM nginx:mainline-alpine
|
||||
|
||||
COPY --from=builder /app/frontend/dist /usr/share/nginx/html
|
||||
COPY docker/frontend/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY docker/frontend/updateConfig.sh /docker-entrypoint.d/updateConfig.sh
|
||||
RUN chmod +x /docker-entrypoint.d/updateConfig.sh
|
||||
|
||||
# entry
|
||||
#CMD ["./entryPoint.sh"]
|
||||
13
docker/frontend/firebase-config-live.ts
Normal file
13
docker/frontend/firebase-config-live.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// To find your config, go to https://console.firebase.google.com/ and select your project
|
||||
// Go to (top left) Settings > Project Settings > General
|
||||
// scroll down to Your apps > Web Apps (if it doesnt exist, create one) > SDK setup and configuration > select npm
|
||||
// your config should be visible there
|
||||
|
||||
export const firebaseConfig = {
|
||||
apiKey: "###FIREBASE_APIKEY###",
|
||||
authDomain: "###FIREBASE_AUTHDOMAIN###",
|
||||
projectId: "###FIREBASE_PROJECTID###",
|
||||
storageBucket: "###FIREBASE_STORAGEBUCKET###",
|
||||
messagingSenderId: "###FIREBASE_MESSAGINGSENDERID###",
|
||||
appId: "###FIREBASE_APPID###",
|
||||
};
|
||||
11
docker/frontend/nginx.conf
Normal file
11
docker/frontend/nginx.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
server_name frontend;
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
}
|
||||
16
docker/frontend/updateConfig.sh
Executable file
16
docker/frontend/updateConfig.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
cd /usr/share/nginx/html
|
||||
echo "replace firebase config appid: ${FIREBASE_APPID}"
|
||||
sed -i "s/###FIREBASE_APIKEY###/${FIREBASE_APIKEY}/g" js/firebase-config-live.*.js
|
||||
sed -i "s/###FIREBASE_AUTHDOMAIN###/${FIREBASE_AUTHDOMAIN}/g" js/firebase-config-live.*.js
|
||||
sed -i "s/###FIREBASE_PROJECTID###/${FIREBASE_PROJECTID}/g" js/firebase-config-live.*.js
|
||||
sed -i "s/###FIREBASE_STORAGEBUCKET###/${FIREBASE_STORAGEBUCKET}/g" js/firebase-config-live.*.js
|
||||
sed -i "s/###FIREBASE_MESSAGINGSENDERID###/${FIREBASE_MESSAGINGSENDERID}/g" js/firebase-config-live.*.js
|
||||
sed -i "s/###FIREBASE_APPID###/${FIREBASE_APPID}/g" js/firebase-config-live.*.js
|
||||
|
||||
|
||||
echo "use backend url ${MONKEYTYPE_BACKENDURL}"
|
||||
sed -i "s/###MONKEYTYPE_BACKENDURL###/${MONKEYTYPE_BACKENDURL//\//\\/}/g" js/*.js
|
||||
|
||||
echo "use recaptcha ${RECAPTCHA_SITE_KEY}"
|
||||
sed -i "s/###RECAPTCHA_SITE_KEY###/${RECAPTCHA_SITE_KEY//\//\\/}/g" js/*.js
|
||||
13
docker/serviceAccountKey-example.json
Normal file
13
docker/serviceAccountKey-example.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "service_account",
|
||||
"project_id": "",
|
||||
"private_key_id": "",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\n\n-----END PRIVATE KEY-----\n",
|
||||
"client_email": "",
|
||||
"client_id": "",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "",
|
||||
"universe_domain": "googleapis.com"
|
||||
}
|
||||
Reference in New Issue
Block a user