🧑‍💻 Added Docker

This commit is contained in:
Mawoka
2022-03-03 17:02:01 +01:00
parent 781ebfcb52
commit a3f781e610
7 changed files with 226 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
:8080 {
reverse_proxy * http://frontend:3000
reverse_proxy /api* http://api:80
reverse_proxy /openapi.json http://api:80 # Only use if you need to serve the OpenAPI spec
reverse_proxy /docs http://api:80 # Only use if you need to serve the Swagger UI
}
+14
View File
@@ -0,0 +1,14 @@
FROM python:3.10-slim
COPY classquiz/ /app/classquiz/
COPY init_db.py /app/
COPY *start.sh /app/
COPY gunicorn_conf.py /app/
COPY Pipfile* /app/
WORKDIR /app/
RUN pip install pipenv && pipenv install --system
EXPOSE 80
ENV PYTHONPATH=/app
RUN chmod +x start.sh
ENV APP_MODULE=classquiz:app
CMD ["./start.sh"]
+65
View File
@@ -0,0 +1,65 @@
version: "3"
services:
frontend:
restart: always
build:
context: ./frontend
dockerfile: Dockerfile
args:
redis: ""
depends_on:
- redis
- api
environment:
REDIS_URL: redis://redis:6379/0?decode_responses=True
API_URL: http://api:80
api:
build:
context: .
dockerfile: Dockerfile
restart: always
depends_on:
- db
- redis
environment:
DB_URL: "postgresql://postgres:classquiz@db:5432/classquiz"
MAIL_ADDRESS: "email@email@email.email"
MAIL_PASSWORD: "PASSWORT"
MAIL_USERNAME: "email@email@email.email"
MAIL_SERVER: "email@email@email.emai"
MAX_WORKERS: "5" # Very important
MAIL_PORT: "587"
SECRET_KEY: "mysecretkey"
ACCESS_TOKEN_EXPIRE_MINUTES: 30
SKIP_EMAIL_VERIFICATION: True
HCAPTCHA_KEY: "HCAPTCHA_PRIVATE_KEY"
redis:
image: redis:alpine
restart: always
healthcheck:
test: [ "CMD", "redis-cli","ping" ]
db:
image: postgres:alpine
restart: always
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
timeout: 5s
retries: 5
environment:
POSTGRES_PASSWORD: "classquiz"
POSTGRES_DB: "classquiz"
volumes:
- ./db:/var/lib/postgresql/data
proxy:
image: caddy:alpine
restart: unless-stopped
volumes:
- ./Caddyfile-docker:/etc/caddy/Caddyfile
ports:
- "8000:8080"
+39
View File
@@ -0,0 +1,39 @@
### Build Step
# pull the Node.js Docker image
ARG redis
FROM node:16 as builder
# ENV API_URL=http://api:80
ENV API_URL=https://mawoka.eu
ENV REDIS_URL=$REDIS
# change working directory
WORKDIR /usr/src/app
# copy the package.json files from local machine to the workdir in container
COPY package*.json ./
# run npm install in our local machine
RUN apt update && apt install -y curl && curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm && pnpm i
# copy the generated modules and all other files to the container
COPY . .
# build the application
RUN pnpm run build
### Serve Step
# pull the Node.js Docker image
FROM node:16
# change working directory
WORKDIR /app
RUN apt update && apt install -y curl && curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm && apt purge curl -y && apt autoremove -y
# copy files from previous step
COPY --from=builder /usr/src/app/build .
COPY --from=builder /usr/src/app/package.json .
COPY --from=builder /usr/src/app/node_modules ./node_modules
# our app is running on port 3000 within the container, so need to expose it
EXPOSE 3000
# the command that starts our app
CMD ["pnpm", "run", "run:prod"]
+67
View File
@@ -0,0 +1,67 @@
import json
import multiprocessing
import os
workers_per_core_str = os.getenv("WORKERS_PER_CORE", "1")
max_workers_str = os.getenv("MAX_WORKERS")
use_max_workers = None
if max_workers_str:
use_max_workers = int(max_workers_str)
web_concurrency_str = os.getenv("WEB_CONCURRENCY", None)
host = os.getenv("HOST", "0.0.0.0")
port = os.getenv("PORT", "80")
bind_env = os.getenv("BIND", None)
use_loglevel = os.getenv("LOG_LEVEL", "info")
if bind_env:
use_bind = bind_env
else:
use_bind = f"{host}:{port}"
cores = multiprocessing.cpu_count()
workers_per_core = float(workers_per_core_str)
default_web_concurrency = workers_per_core * cores
if web_concurrency_str:
web_concurrency = int(web_concurrency_str)
assert web_concurrency > 0
else:
web_concurrency = max(int(default_web_concurrency), 2)
if use_max_workers:
web_concurrency = min(web_concurrency, use_max_workers)
accesslog_var = os.getenv("ACCESS_LOG", "-")
use_accesslog = accesslog_var or None
proc_name = os.getenv("PROC_NAME", "classquiz_api")
errorlog_var = os.getenv("ERROR_LOG", "-")
use_errorlog = errorlog_var or None
graceful_timeout_str = os.getenv("GRACEFUL_TIMEOUT", "120")
timeout_str = os.getenv("TIMEOUT", "120")
keepalive_str = os.getenv("KEEP_ALIVE", "5")
# Gunicorn config variables
loglevel = use_loglevel
workers = web_concurrency
bind = use_bind
errorlog = use_errorlog
worker_tmp_dir = "/dev/shm"
accesslog = use_accesslog
graceful_timeout = int(graceful_timeout_str)
timeout = int(timeout_str)
keepalive = int(keepalive_str)
# For debugging and testing
log_data = {
"loglevel": loglevel,
"workers": workers,
"bind": bind,
"graceful_timeout": graceful_timeout,
"timeout": timeout,
"keepalive": keepalive,
"errorlog": errorlog,
"accesslog": accesslog,
# Additional, non-gunicorn variables
"workers_per_core": workers_per_core,
"use_max_workers": use_max_workers,
"host": host,
"port": port,
}
print(json.dumps(log_data))
+1
View File
@@ -0,0 +1 @@
python3 init_db.py
Executable
+34
View File
@@ -0,0 +1,34 @@
#! /usr/bin/env sh
set -e
if [ -f /app/app/main.py ]; then
DEFAULT_MODULE_NAME=app.main
elif [ -f /app/main.py ]; then
DEFAULT_MODULE_NAME=main
fi
MODULE_NAME=${MODULE_NAME:-$DEFAULT_MODULE_NAME}
VARIABLE_NAME=${VARIABLE_NAME:-app}
export APP_MODULE=${APP_MODULE:-"$MODULE_NAME:$VARIABLE_NAME"}
if [ -f /app/gunicorn_conf.py ]; then
DEFAULT_GUNICORN_CONF=/app/gunicorn_conf.py
elif [ -f /app/app/gunicorn_conf.py ]; then
DEFAULT_GUNICORN_CONF=/app/app/gunicorn_conf.py
else
DEFAULT_GUNICORN_CONF=/gunicorn_conf.py
fi
export GUNICORN_CONF=${GUNICORN_CONF:-$DEFAULT_GUNICORN_CONF}
export WORKER_CLASS=${WORKER_CLASS:-"uvicorn.workers.UvicornWorker"}
# If there's a prestart.sh script in the /app directory or other path specified, run it before starting
PRE_START_PATH=${PRE_START_PATH:-/app/prestart.sh}
echo "Checking for script in $PRE_START_PATH"
if [ -f $PRE_START_PATH ] ; then
echo "Running script $PRE_START_PATH"
. "$PRE_START_PATH"
else
echo "There is no script $PRE_START_PATH"
fi
# Start Gunicorn
exec gunicorn -k "$WORKER_CLASS" -c "$GUNICORN_CONF" "$APP_MODULE"