Skip to content

Commit

Permalink
Initial docker deployment setup
Browse files Browse the repository at this point in the history
- add docker-compose
- add nginx docker image and nginx conf for frontend
- remove .env file from backend folder
  - instead make settings default values the ones used for local development
- replace USER_DATABASE_PATH and MILESTONE_DATABASE_PATH with single DATABASE_PATH folder
- add mondey_backend/db folder to use as a default location for databases when running backend locally without docker
- add `/api` root_path to API, forward all /api locations in nginx to the backend
- note that nginx config is only http for now
  • Loading branch information
lkeegan committed Sep 24, 2024
1 parent 3503acb commit 33a8b70
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 23 deletions.
34 changes: 34 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
services:
backend:
image: ghcr.io/ssciwr/mondey_backend:${MONDEY_DOCKER_IMAGE_TAG:-latest}
build: ./mondey_backend
volumes:
- ${STATIC_FILES_PATH:-./static}:/app/static
- ${DATABASE_PATH:-./db}:/app/db
environment:
- SECRET=${SECRET:-}
- STATIC_FILES_PATH=/app/static
- DATABASE_PATH=/app/db
- ENABLE_CORS=${ENABLE_CORS:-false}
- HOST=${HOST:-backend}
- PORT=${PORT:-80}
- RELOAD=${RELOAD:-false}
- LOG_LEVEL=${LOG_LEVEL:-info}
frontend:
image: ghcr.io/ssciwr/mondey_frontend:${MONDEY_DOCKER_IMAGE_TAG:-latest}
build:
context: ./frontend
args:
- MONDEY_API_URL=/api
ports:
- "80:80"
- "443:443"
# volumes:
# - ${MONDEY_SSL_CERT:-./cert.pem}:/MONDEY_ssl_cert.pem
# - ${MONDEY_SSL_KEY:-./key.pem}:/MONDEY_ssl_key.pem
# email:
# image: "boky/postfix"
# environment:
# - ALLOW_EMPTY_SENDER_DOMAINS="true"
# networks:
# - mondey-network
3 changes: 2 additions & 1 deletion frontend/.env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
VITE_MONDEY_API_URL=http://localhost:8000
# api location for local development:
VITE_MONDEY_API_URL=http://localhost:8000/api
26 changes: 26 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM node:22-slim AS builder

LABEL org.opencontainers.image.source=https://github.com/ssciwr/mondey
LABEL org.opencontainers.image.description="MONDEY frontend production image"

ARG MONDEY_API_URL

WORKDIR /app

COPY package*.json ./

RUN npm install -g pnpm

RUN pnpm install

COPY . .

RUN echo "VITE_MONDEY_API_URL=${MONDEY_API_URL}" > .env

RUN pnpm run build

FROM nginx

COPY --from=builder /app/build /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf
48 changes: 48 additions & 0 deletions frontend/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
server {
listen 80;
# listen 443 ssl;
# listen [::]:443 ssl;
http2 on;
server_name localhost;
# ssl_certificate /ssl_cert.pem;
# ssl_certificate_key /ssl_key.pem;

# Maximum file upload size
client_max_body_size 20M;

# Improve HTTPS performance with session resumption
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# Enable server-side protection against BEAST attacks
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";

# Aditional Security Headers
# ref: https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

# ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
add_header X-Frame-Options DENY always;

# ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
add_header X-Content-Type-Options nosniff always;

# ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
add_header X-Xss-Protection "1; mode=block" always;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}

location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend:80;
}
}
1 change: 1 addition & 0 deletions frontend/src/routes/admin/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
}
onMount(async () => {
console.log(import.meta.env.VITE_MONDEY_API_URL);
updateLanguages();
updateIsLoggedIn();
});
Expand Down
9 changes: 0 additions & 9 deletions mondey_backend/.env

This file was deleted.

3 changes: 1 addition & 2 deletions mondey_backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ FROM python:3.12-slim

LABEL org.opencontainers.image.source=https://github.com/ssciwr/mondey-frontend-prototype
LABEL org.opencontainers.image.description="MONDEY backend production image"
LABEL org.opencontainers.image.licenses=MIT

WORKDIR /app

COPY . .

RUN pip install .

CMD ["mondey-backend", "--host", "0.0.0.0", "--port", "80", "--log-level", "info"]
CMD ["mondey-backend"]
1 change: 0 additions & 1 deletion mondey_backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ sqlite> UPDATE user SET is_superuser = 1 WHERE email = '[email protected]

The backend can be configured using environment variables,
which can be set in a `.env` file in the working directory where you start the backend.
Default settings for local development are included in [.env](.env).

## Tests

Expand Down
1 change: 1 addition & 0 deletions mondey_backend/db/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the default folder where the databases will be created and stored when running the backend locally.
2 changes: 1 addition & 1 deletion mondey_backend/src/mondey_backend/databases/milestones.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from ..settings import app_settings

engine = create_engine(
f"sqlite:///{app_settings.MILESTONE_DATABASE_PATH}",
f"sqlite:///{app_settings.DATABASE_PATH}/milestones.db",
connect_args={"check_same_thread": False},
)

Expand Down
4 changes: 3 additions & 1 deletion mondey_backend/src/mondey_backend/databases/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
from ..models.users import User
from ..settings import app_settings

engine = create_async_engine(f"sqlite+aiosqlite:///{app_settings.USER_DATABASE_PATH}")
engine = create_async_engine(
f"sqlite+aiosqlite:///{app_settings.DATABASE_PATH}/users.db"
)
async_session_maker = async_sessionmaker(engine, expire_on_commit=False)


Expand Down
2 changes: 1 addition & 1 deletion mondey_backend/src/mondey_backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async def lifespan(app: FastAPI):

# ensure static files directory exists
pathlib.Path(app_settings.STATIC_FILES_PATH).mkdir(parents=True, exist_ok=True)
app = FastAPI(lifespan=lifespan, title="MONDEY API")
app = FastAPI(lifespan=lifespan, title="MONDEY API", root_path="/api")
app.include_router(milestones.router)
app.include_router(admin.router)
app.include_router(users.router)
Expand Down
13 changes: 6 additions & 7 deletions mondey_backend/src/mondey_backend/settings.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
from __future__ import annotations

import secrets

from pydantic_settings import BaseSettings
from pydantic_settings import SettingsConfigDict


class AppSettings(BaseSettings):
# this will load settings from environment variables or an .env file if present
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
SECRET: str = secrets.token_urlsafe(64)
USER_DATABASE_PATH: str = "users.db"
MILESTONE_DATABASE_PATH: str = "milestones.db"
# these defaults are for local development and are used if the environment variables are not set
SECRET: str = "abc123"
DATABASE_PATH: str = "db"
STATIC_FILES_PATH: str = "static"
ENABLE_CORS: bool = False
ENABLE_CORS: bool = True
HOST: str = "localhost"
PORT: int = 8000
RELOAD: bool = False
RELOAD: bool = True
LOG_LEVEL: str = "info"


Expand Down

0 comments on commit 33a8b70

Please sign in to comment.