Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 0b46b2f

Browse files
authored
Merge pull request #21 from SELab-2/9-continuous-deployment
9 continuous deployment hotfix debug switch
2 parents 72baa6a + 8fcb01c commit 0b46b2f

11 files changed

+309
-8
lines changed

.github/workflows/deploy.yml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Continous deployment of the app
2+
3+
name: CD
4+
5+
on:
6+
push:
7+
branches: ["develop"]
8+
9+
jobs:
10+
build:
11+
runs-on: self-hosted
12+
steps:
13+
- uses: actions/checkout@v3
14+
15+
- name: Run deploy script
16+
run: bash /home/selab2/hosting/UGent-1/deploy.sh

.gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ venv/
55

66
# development environment
77
.idea/
8-
.vscode/
8+
.vscode/
9+
10+
#deploy
11+
letsencrypt
12+
.env.prod

Makefile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
start:
2+
docker compose up -d --build
3+
4+
stop:
5+
docker compose down
6+
7+
lint:
8+
docker exec pigeonhole-backend flake8 .
9+
docker exec pigeonhole-frontend npm run lint

backend/Dockerfile.prod

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
###########
2+
# BUILDER #
3+
###########
4+
5+
# pull official base image
6+
FROM python:3.11.7-alpine as builder
7+
8+
# set work directory
9+
WORKDIR /usr/src/app
10+
11+
# set environment variables
12+
ENV PYTHONDONTWRITEBYTECODE 1
13+
ENV PYTHONUNBUFFERED 1
14+
15+
# install psycopg2 dependencies
16+
RUN apk update \
17+
&& apk add postgresql-dev gcc python3-dev musl-dev
18+
19+
# lint
20+
RUN pip install --upgrade pip
21+
COPY . .
22+
23+
# install dependencies
24+
COPY requirements.txt .
25+
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
26+
27+
28+
#########
29+
# FINAL #
30+
#########
31+
32+
# pull official base image
33+
FROM python:3.11.7-alpine
34+
35+
# create directory for the app user
36+
RUN mkdir -p /home/app
37+
38+
# create the app user
39+
RUN addgroup -S app && adduser -S app -G app
40+
41+
# create the appropriate directories
42+
ENV HOME=/home/app
43+
ENV APP_HOME=/home/app/web
44+
RUN mkdir $APP_HOME
45+
RUN mkdir $APP_HOME/static
46+
RUN mkdir $APP_HOME/uploads
47+
WORKDIR $APP_HOME
48+
49+
# install dependencies
50+
RUN apk update && apk add libpq
51+
COPY --from=builder /usr/src/app/wheels /wheels
52+
COPY --from=builder /usr/src/app/requirements.txt .
53+
RUN pip install --no-cache /wheels/*
54+
55+
# copy entrypoint.prod.sh
56+
COPY ./entrypoint.prod.sh .
57+
RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh
58+
RUN chmod +x $APP_HOME/entrypoint.prod.sh
59+
60+
# copy project
61+
COPY . $APP_HOME
62+
63+
RUN chmod +x $APP_HOME/entrypoint.prod.sh
64+
65+
66+
# chown all the files to the app user
67+
RUN chown -R app:app $APP_HOME/
68+
69+
# change to the app user
70+
USER app
71+
72+
# run entrypoint.prod.sh
73+
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]

backend/entrypoint.prod.sh

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/sh
2+
3+
if [ "$DATABASE" = "postgres" ]
4+
then
5+
echo "Waiting for postgres..."
6+
7+
while ! nc -z $SQL_HOST $SQL_PORT; do
8+
sleep 0.1
9+
done
10+
11+
echo "PostgreSQL started"
12+
fi
13+
14+
exec "$@"

backend/pigeonhole/settings.py

+21-7
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@
2121
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
2222

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

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

29-
ALLOWED_HOSTS = []
28+
DEBUG = int(os.environ.get("DEBUG", default=0))
3029

30+
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", default="127.0.0.1").split(" ")
31+
32+
if not DEBUG:
33+
USE_X_FORWARDED_HOST = True
34+
FORCE_SCRIPT_NAME = "/api"
3135

3236
# Application definition
3337

@@ -55,11 +59,18 @@
5559
"django.middleware.common.CommonMiddleware",
5660
]
5761

58-
CORS_ALLOWED_ORIGINS = [
59-
"http://localhost:3000",
60-
"http://127.0.0.1:3000",
62+
CORS_ALLOW_METHODS = [
63+
"DELETE",
64+
"GET",
65+
"OPTIONS",
66+
"PATCH",
67+
"POST",
68+
"PUT",
6169
]
6270

71+
CORS_ORIGIN_ALLOW_ALL = True # For now
72+
CORS_ALLOW_CREDENTIALS = True
73+
6374
ROOT_URLCONF = 'pigeonhole.urls'
6475

6576
TEMPLATES = [
@@ -134,8 +145,11 @@
134145

135146
# Static files (CSS, JavaScript, Images)
136147
# https://docs.djangoproject.com/en/5.0/howto/static-files/
137-
138148
STATIC_URL = 'static/'
149+
STATIC_ROOT = BASE_DIR / "static"
150+
151+
MEDIA_URL = 'media/'
152+
MEDIA_ROOT = BASE_DIR / 'uploads'
139153

140154
# Default primary key field type
141155
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

deploy.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
cd /home/selab2/hosting/UGent-1
4+
5+
set -a
6+
source ./.env.prod
7+
docker compose -f docker-compose.prod.yml --env-file .env.prod build
8+
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --force-recreate --remove-orphans

docker-compose.prod.yml

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
version: '3.8'
2+
3+
services:
4+
database:
5+
container_name: pigeonhole-database
6+
image: postgres:13.0-alpine
7+
volumes:
8+
- postgres_data:/var/lib/postgresql/data/
9+
environment:
10+
- POSTGRES_USER=${SQL_USER}
11+
- POSTGRES_PASSWORD=${SQL_PASSWORD}
12+
- POSTGRES_DB=${SQL_DATABASE}
13+
env_file:
14+
- .env.prod
15+
16+
backend:
17+
container_name: pigeonhole-backend
18+
build:
19+
dockerfile: Dockerfile.prod
20+
context: ./backend
21+
command: python manage.py runserver 0.0.0.0:8000
22+
volumes:
23+
#- static_volume:/home/app/web/static
24+
- media_volume:/home/app/web/uploads
25+
expose:
26+
- 8000
27+
env_file:
28+
- .env.prod
29+
depends_on:
30+
- database
31+
restart: always
32+
labels:
33+
- "traefik.enable=true"
34+
- "traefik.http.routers.backend.rule=Host(`sel2-1.ugent.be`) && PathPrefix(`/api`)"
35+
- "traefik.http.routers.backend.middlewares=backend-stripprefix"
36+
- "traefik.http.middlewares.backend-stripprefix.stripprefix.prefixes=/api"
37+
- "traefik.http.routers.backend.entrypoints=websecure"
38+
- "traefik.http.routers.backend.tls.certresolver=myresolver"
39+
40+
static:
41+
container_name: statics
42+
image: nginx:alpine
43+
restart: always
44+
volumes:
45+
#- static_volume:/srv
46+
- ./nginx.conf:/etc/nginx/conf.d/default.conf
47+
depends_on:
48+
- backend
49+
ports:
50+
- 5000:80
51+
labels:
52+
- "traefik.enable=true"
53+
- "traefik.http.routers.static.rule=Host(`sel2-1.ugent.be`) && PathPrefix(`/static`)"
54+
- "traefik.http.routers.static.entrypoints=websecure"
55+
- "traefik.http.routers.static.tls.certresolver=myresolver"
56+
57+
frontend:
58+
container_name: pigeonhole-frontend
59+
build:
60+
dockerfile: Dockerfile.prod
61+
context: ./frontend
62+
target: runner
63+
command: npm run start
64+
ports:
65+
- 3000:3000
66+
depends_on:
67+
- backend
68+
env_file:
69+
- .env.prod
70+
labels:
71+
- "traefik.enable=true"
72+
- "traefik.http.routers.frontend.rule=Host(`sel2-1.ugent.be`)"
73+
- "traefik.http.routers.frontend.entrypoints=websecure"
74+
- "traefik.http.routers.frontend.tls.certresolver=myresolver"
75+
76+
traefik:
77+
image: "traefik:v2.11"
78+
container_name: "traefik"
79+
command:
80+
- "--log.level=DEBUG"
81+
- "--api.insecure=true"
82+
- "--providers.docker=true"
83+
- "--providers.docker.exposedbydefault=false"
84+
- "--entrypoints.web.address=:80"
85+
- "--entrypoints.websecure.address=:443"
86+
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
87+
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
88+
- "--certificatesresolvers.myresolver.acme.email=robin.paret@ugent.be"
89+
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
90+
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
91+
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
92+
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
93+
ports:
94+
- "80:80"
95+
- "443:443"
96+
- "8080:8080"
97+
volumes:
98+
- "./letsencrypt:/letsencrypt"
99+
- "/var/run/docker.sock:/var/run/docker.sock:ro"
100+
101+
102+
volumes:
103+
postgres_data:
104+
static_volume:
105+
media_volume:

down-deploy.sh

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docker compose -f docker-compose.prod.yml down

frontend/Dockerfile.prod

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
################
2+
# DEPENDENCIES #
3+
################
4+
5+
FROM node:18-alpine AS deps
6+
RUN apk add --no-cache libc6-compat
7+
WORKDIR /usr/src/app
8+
9+
COPY package.json package-lock.json ./
10+
RUN npm install
11+
12+
###########
13+
# BUILDER #
14+
###########
15+
16+
FROM node:18-alpine AS builder
17+
WORKDIR /usr/src/app
18+
COPY --from=deps /usr/src/app/node_modules ./node_modules
19+
COPY . .
20+
21+
ENV NEXT_TELEMETRY_DISABLED 1
22+
23+
RUN npm run build
24+
25+
###########
26+
# FINAL #
27+
###########
28+
29+
FROM node:18-alpine AS runner
30+
WORKDIR /usr/src/app
31+
32+
ENV NODE_ENV production
33+
ENV NEXT_TELEMETRY_DISABLED 1
34+
35+
RUN addgroup --system --gid 1001 nodejs
36+
RUN adduser --system --uid 1001 nextjs
37+
38+
COPY --from=builder --chown=nextjs:nodejs /usr/src/app/.next ./.next
39+
COPY --from=builder /usr/src/app/node_modules ./node_modules
40+
COPY --from=builder /usr/src/app/package.json ./package.json
41+
COPY --from=builder /usr/src/app/public ./public
42+
43+
USER nextjs
44+
45+
EXPOSE 3000
46+
47+
ENV PORT 3000

nginx.conf

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
server{
2+
listen 80;
3+
server_name _;
4+
5+
location /static {
6+
root /srv;
7+
# Activate the next line if you want to list files
8+
# autoindex on;
9+
}
10+
}

0 commit comments

Comments
 (0)