Skip to content

Commit

Permalink
Merge pull request #21 from SELab-2/9-continuous-deployment
Browse files Browse the repository at this point in the history
9 continuous deployment hotfix debug switch
  • Loading branch information
robinpdev authored Feb 29, 2024
2 parents 72baa6a + 8fcb01c commit 0b46b2f
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 8 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Continous deployment of the app

name: CD

on:
push:
branches: ["develop"]

jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3

- name: Run deploy script
run: bash /home/selab2/hosting/UGent-1/deploy.sh
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ venv/

# development environment
.idea/
.vscode/
.vscode/

#deploy
letsencrypt
.env.prod
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
start:
docker compose up -d --build

stop:
docker compose down

lint:
docker exec pigeonhole-backend flake8 .
docker exec pigeonhole-frontend npm run lint
73 changes: 73 additions & 0 deletions backend/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
###########
# BUILDER #
###########

# pull official base image
FROM python:3.11.7-alpine as builder

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
&& apk add postgresql-dev gcc python3-dev musl-dev

# lint
RUN pip install --upgrade pip
COPY . .

# install dependencies
COPY requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt


#########
# FINAL #
#########

# pull official base image
FROM python:3.11.7-alpine

# create directory for the app user
RUN mkdir -p /home/app

# create the app user
RUN addgroup -S app && adduser -S app -G app

# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/static
RUN mkdir $APP_HOME/uploads
WORKDIR $APP_HOME

# install dependencies
RUN apk update && apk add libpq
COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --no-cache /wheels/*

# copy entrypoint.prod.sh
COPY ./entrypoint.prod.sh .
RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh
RUN chmod +x $APP_HOME/entrypoint.prod.sh

# copy project
COPY . $APP_HOME

RUN chmod +x $APP_HOME/entrypoint.prod.sh


# chown all the files to the app user
RUN chown -R app:app $APP_HOME/

# change to the app user
USER app

# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
14 changes: 14 additions & 0 deletions backend/entrypoint.prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."

while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done

echo "PostgreSQL started"
fi

exec "$@"
28 changes: 21 additions & 7 deletions backend/pigeonhole/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-_lgysrd7c-9-_^7l8@(yhe%_3q7*jqtp_gw^rbdtsupp@4k!w&'
SECRET_KEY = os.environ.get("SECRET_KEY", default="foo")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []
DEBUG = int(os.environ.get("DEBUG", default=0))

ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", default="127.0.0.1").split(" ")

if not DEBUG:
USE_X_FORWARDED_HOST = True
FORCE_SCRIPT_NAME = "/api"

# Application definition

Expand Down Expand Up @@ -55,11 +59,18 @@
"django.middleware.common.CommonMiddleware",
]

CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000",
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
]

CORS_ORIGIN_ALLOW_ALL = True # For now
CORS_ALLOW_CREDENTIALS = True

ROOT_URLCONF = 'pigeonhole.urls'

TEMPLATES = [
Expand Down Expand Up @@ -134,8 +145,11 @@

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/

STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / "static"

MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'uploads'

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
Expand Down
8 changes: 8 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

cd /home/selab2/hosting/UGent-1

set -a
source ./.env.prod
docker compose -f docker-compose.prod.yml --env-file .env.prod build
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --force-recreate --remove-orphans
105 changes: 105 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
version: '3.8'

services:
database:
container_name: pigeonhole-database
image: postgres:13.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=${SQL_USER}
- POSTGRES_PASSWORD=${SQL_PASSWORD}
- POSTGRES_DB=${SQL_DATABASE}
env_file:
- .env.prod

backend:
container_name: pigeonhole-backend
build:
dockerfile: Dockerfile.prod
context: ./backend
command: python manage.py runserver 0.0.0.0:8000
volumes:
#- static_volume:/home/app/web/static
- media_volume:/home/app/web/uploads
expose:
- 8000
env_file:
- .env.prod
depends_on:
- database
restart: always
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=Host(`sel2-1.ugent.be`) && PathPrefix(`/api`)"
- "traefik.http.routers.backend.middlewares=backend-stripprefix"
- "traefik.http.middlewares.backend-stripprefix.stripprefix.prefixes=/api"
- "traefik.http.routers.backend.entrypoints=websecure"
- "traefik.http.routers.backend.tls.certresolver=myresolver"

static:
container_name: statics
image: nginx:alpine
restart: always
volumes:
#- static_volume:/srv
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- backend
ports:
- 5000:80
labels:
- "traefik.enable=true"
- "traefik.http.routers.static.rule=Host(`sel2-1.ugent.be`) && PathPrefix(`/static`)"
- "traefik.http.routers.static.entrypoints=websecure"
- "traefik.http.routers.static.tls.certresolver=myresolver"

frontend:
container_name: pigeonhole-frontend
build:
dockerfile: Dockerfile.prod
context: ./frontend
target: runner
command: npm run start
ports:
- 3000:3000
depends_on:
- backend
env_file:
- .env.prod
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`sel2-1.ugent.be`)"
- "traefik.http.routers.frontend.entrypoints=websecure"
- "traefik.http.routers.frontend.tls.certresolver=myresolver"

traefik:
image: "traefik:v2.11"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=robin.paret@ugent.be"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"


volumes:
postgres_data:
static_volume:
media_volume:
1 change: 1 addition & 0 deletions down-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docker compose -f docker-compose.prod.yml down
47 changes: 47 additions & 0 deletions frontend/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
################
# DEPENDENCIES #
################

FROM node:18-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /usr/src/app

COPY package.json package-lock.json ./
RUN npm install

###########
# BUILDER #
###########

FROM node:18-alpine AS builder
WORKDIR /usr/src/app
COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY . .

ENV NEXT_TELEMETRY_DISABLED 1

RUN npm run build

###########
# FINAL #
###########

FROM node:18-alpine AS runner
WORKDIR /usr/src/app

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder --chown=nextjs:nodejs /usr/src/app/.next ./.next
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/package.json ./package.json
COPY --from=builder /usr/src/app/public ./public

USER nextjs

EXPOSE 3000

ENV PORT 3000
10 changes: 10 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
server{
listen 80;
server_name _;

location /static {
root /srv;
# Activate the next line if you want to list files
# autoindex on;
}
}

0 comments on commit 0b46b2f

Please sign in to comment.