Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial docker deployment setup #85

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: docker containers
on:
push:
branches:
- main
pull_request:
branches:
- main

concurrency:
group: docker-${{ github.ref }}
cancel-in-progress: true

jobs:
docker:
runs-on: ubuntu-latest
name: "Docker"
steps:
- uses: actions/checkout@v4
- run: docker compose build
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- run: |
echo $MONDEY_DOCKER_IMAGE_TAG
docker compose build
docker compose push
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
MONDEY_DOCKER_IMAGE_TAG: ${{ github.sha }}
- run: |
echo $MONDEY_DOCKER_IMAGE_TAG
docker compose build
docker compose push
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
MONDEY_DOCKER_IMAGE_TAG: "latest"
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
22 changes: 22 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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 && pnpm install

COPY . .

RUN echo "VITE_MONDEY_API_URL=${MONDEY_API_URL}" > .env && pnpm run build

FROM nginx:1.27.1

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