Skip to content

Commit

Permalink
Merge pull request #1138 from gafderks/docker-workflow
Browse files Browse the repository at this point in the history
Implement docker workflow for ocd theme
  • Loading branch information
gafderks committed Dec 21, 2023
2 parents eb3ed6a + 7b7b272 commit 906138d
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 82 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ build/
static/
media/
functional_tests/
tests/
**/*.mo
**/*.pyc
.git/
Expand Down
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ updates:
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
75 changes: 75 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Docker build and export

on:
push:
branches:
- "theme/ocd"
pull_request:
branches:
- "theme/ocd"

env:
WEB_TEST_IMAGE: dbase-web:test
WEB_IMAGE: gafderkspersonal/dbase-web
NGINX_TEST_IMAGE: dbase-nginx:test
NGINX_IMAGE: gafderkspersonal/dbase-nginx

jobs:
build:
environment: CI
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set short git commit SHA
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Output git commit SHA
run: echo ${{ steps.vars.outputs.sha_short }}
- name: Build web test image
uses: docker/build-push-action@v5
with:
target: web-test
context: .
load: true
tags: ${{ env.WEB_TEST_IMAGE }}
- name: Test web test image
run: |
docker run \
-e SECRET_KEY="${{ secrets.SECRET_KEY }}" \
-e DATABASE_URL="sqlite:////app/db.sqlite3" \
-e DEBUG=on \
--rm ${{ env.WEB_TEST_IMAGE }} \
python manage.py test --exclude-tag=functional -v 2
- name: Build nginx image
uses: docker/build-push-action@v5
with:
target: nginx
context: .
load: true
tags: ${{ env.NGINX_TEST_IMAGE }}
- name: Publish web image
uses: docker/build-push-action@v5
with:
context: .
push: true
target: runtime
tags: ${{ env.WEB_IMAGE }}:latest-ocd,${{ env.WEB_IMAGE }}:${{ steps.vars.outputs.sha_short }}-ocd
if: github.ref == 'refs/heads/theme/ocd' && github.event_name != 'pull_request'
- name: Publish nginx image
uses: docker/build-push-action@v5
with:
context: .
push: true
target: nginx
tags: ${{ env.NGINX_IMAGE }}:latest-ocd,${{ env.NGINX_IMAGE }}:${{ steps.vars.outputs.sha_short }}-ocd
if: github.ref == 'refs/heads/theme/ocd' && github.event_name != 'pull_request'
42 changes: 29 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ ENV APP_HOME=/app
RUN mkdir -p ${APP_HOME}
WORKDIR ${APP_HOME}

RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl ca-certificates gnupg git
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates gnupg git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Install Node.js
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN mkdir -p /etc/apt/keyrings && \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
NODE_MAJOR=20; echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
apt-get update && apt-get install -y --no-install-recommends nodejs
apt-get update && apt-get install -y --no-install-recommends nodejs \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

RUN npm install -g [email protected]

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DOCKER_BUILD 1
ENV NODE_ENV production

RUN pip install --upgrade --no-cache-dir pipenv==2023.10.24 wheel==0.41.2
COPY ./Pipfile .
Expand All @@ -33,18 +37,18 @@ RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy
COPY ./package-lock.json .
COPY ./package.json .

RUN npm ci && \
RUN npm ci --omit=dev && \
npx update-browserslist-db@latest

COPY . .

RUN SECRET_KEY=dummy pipenv run ./manage.py collectstatic --noinput
RUN SECRET_KEY=dummy pipenv run python ./manage.py collectstatic --noinput

###########
## NGINX ##
###########

FROM nginx:1.25.3@sha256:add4792d930c25dd2abf2ef9ea79de578097a1c175a16ab25814332fe33622de as nginx
FROM nginx:1.25.3@sha256:1c274506e6ef5d92b7df28fd61e35cea64ed0530994bc16b768a69313e6ff74a as nginx
LABEL maintainer="Geert Derks <[email protected]>"

COPY ./config/nginx.conf /etc/nginx/nginx.conf
Expand All @@ -56,10 +60,12 @@ COPY --from=base /app/static /opt/services/dbase/static
## RUNTIME ##
#############

FROM python:3.12-slim@sha256:8e216a21d8df597118b46f3fff477ed1c5c11be81531b6da87790a17851b7f1c as runtime
FROM python:3.12-slim@sha256:41487afa4d11d89b3ec37fdfb652ceb2f2db0c19b2259a24b052e5805bc22197 as runtime
LABEL maintainer="Geert Derks <[email protected]>"

RUN apt-get update && apt-get install -y --no-install-recommends gettext curl
RUN apt-get update && apt-get install -y --no-install-recommends gettext curl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Prevent writing pyc files
ENV PYTHONDONTWRITEBYTECODE 1
Expand All @@ -73,7 +79,8 @@ ENV APP_HOME=/app
RUN groupadd -g 999 appuser && \
useradd -r -u 999 -g appuser appuser

RUN mkdir ${APP_HOME}
RUN mkdir ${APP_HOME} && \
chown appuser:appuser ${APP_HOME}
RUN mkdir ${APP_HOME}/media && \
chown appuser:appuser ${APP_HOME}/media
WORKDIR ${APP_HOME}
Expand All @@ -88,12 +95,21 @@ COPY --chown=appuser:appuser . .

USER 999

ENV PATH="/${APP_HOME}/.venv/bin:$PATH"
ENV PATH="${APP_HOME}/.venv/bin:$PATH"

RUN django-admin compilemessages

ENTRYPOINT [ "./entrypoint.sh" ]

# Migrate (separate command, do not want to run this simultaneously if started multiple times.)
#############
## TESTING ##
#############

FROM base as base-test

RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy --dev

FROM runtime as web-test

COPY --from=base-test --chown=appuser:appuser ${APP_HOME}/.venv ./.venv

# TODO: https://snyk.io/blog/best-practices-containerizing-python-docker/#:~:text=5.%20Handle%20unhealthy%20states%20of%20your%20containerized%20Python%20application
5 changes: 2 additions & 3 deletions booking/api/event.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime

from django.http import HttpResponse
from django.utils.translation import gettext as _
from django.utils.timezone import now
from openpyxl import Workbook
from openpyxl.styles import Alignment
from openpyxl.utils import get_column_letter
Expand All @@ -27,7 +26,7 @@ def get(self, request, *args, **kwargs):
if context["current_group"]
else _("All groups"),
downloaded=_("downloaded on"),
date=datetime.now().strftime("%Y-%m-%d"),
date=now().strftime("%Y-%m-%d"),
)

workbook = Workbook()
Expand Down
24 changes: 10 additions & 14 deletions booking/models/event.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from datetime import timedelta, datetime, timezone
from datetime import timedelta

from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now
from rules.contrib.models import RulesModel

from booking import rules
Expand All @@ -20,11 +21,9 @@ def viewable(user):
def editable(user):
query = Event.objects.viewable(user)
if not user.has_perm("booking.can_book_on_locked_events"):
query = query.filter(
locked=False, privileged_booking_end__gt=datetime.now(timezone.utc)
)
query = query.filter(locked=False, privileged_booking_end__gt=now())
if not user.has_perm("booking.can_book_on_privileged_events"):
query = query.filter(booking_end__gt=datetime.now(timezone.utc))
query = query.filter(booking_end__gt=now())
return query


Expand Down Expand Up @@ -110,16 +109,16 @@ class BookingStatus(models.TextChoices):

@property
def booking_status(self):
now = datetime.now(timezone.utc)
_now = now()
if not self.visible:
return self.BookingStatus.HIDDEN
if self.locked:
return self.BookingStatus.LOCKED
if now < self.booking_start:
if _now < self.booking_start:
return self.BookingStatus.NOT_STARTED
if now < self.booking_end:
if _now < self.booking_end:
return self.BookingStatus.OPENED
if now < self.privileged_booking_end:
if _now < self.privileged_booking_end:
return self.BookingStatus.PRIVILEGED
return self.BookingStatus.LOCKED

Expand All @@ -132,10 +131,7 @@ def is_privileged(self):
:return: bool
"""
return (
not self.locked
and self.booking_end
< datetime.now(timezone.utc)
< self.privileged_booking_end
not self.locked and self.booking_end < now() < self.privileged_booking_end
)

@property
Expand All @@ -145,4 +141,4 @@ def is_locked(self):
True or the privileged booking period has ended.
:return: bool
"""
return self.locked or datetime.now(timezone.utc) > self.privileged_booking_end
return self.locked or now() > self.privileged_booking_end
Empty file removed dbase/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion dbase/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"default": {
**env.db(),
"TEST": {
"NAME": BASE_DIR / "db.sqlite3.test",
"NAME": BASE_DIR / "db.test.sqlite3",
},
},
}
Expand Down
6 changes: 5 additions & 1 deletion deploy/kubernetes/deployment/database-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ spec:
- pg_isready
periodSeconds: 90
name: database
resources: {}
resources:
limits:
memory: "52428800"
requests:
memory: "31457280"
ports:
- containerPort: 5432
protocol: TCP
Expand Down
6 changes: 5 additions & 1 deletion deploy/kubernetes/deployment/memcached-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ spec:
ports:
- containerPort: 11211
protocol: TCP
resources: {}
resources:
limits:
memory: "314572800"
requests:
memory: "104857600"
restartPolicy: Always
status: {}
6 changes: 5 additions & 1 deletion deploy/kubernetes/deployment/nginx-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ spec:
ports:
- containerPort: 80
protocol: TCP
resources: {}
resources:
limits:
memory: "52428800"
requests:
memory: "31457280"
volumeMounts:
- mountPath: /opt/services/dbase/media
name: media-volume
Expand Down
6 changes: 5 additions & 1 deletion deploy/kubernetes/deployment/web-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ spec:
ports:
- containerPort: 8000
protocol: TCP
resources: {}
resources:
limits:
memory: "524288e3"
requests:
memory: "262144e3"
volumeMounts:
- mountPath: /app/media
name: media-volume
Expand Down
26 changes: 25 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "3.1"
version: "3.8"

volumes:
postgresql-data:
Expand Down Expand Up @@ -26,6 +26,12 @@ services:
- web
networks:
- backend-network
deploy:
resources:
limits:
memory: 50M
reservations:
memory: 30MB
database:
image: postgres:15.2
volumes:
Expand All @@ -41,6 +47,12 @@ services:
interval: 1m30s
expose:
- 5432
deploy:
resources:
limits:
memory: 50M
reservations:
memory: 30MB
web:
build:
context: .
Expand All @@ -63,12 +75,24 @@ services:
- media-data:/app/media
networks:
- backend-network
deploy:
resources:
limits:
memory: 500M
reservations:
memory: 250M
memcached:
image: memcached:1.6
expose:
- 11211
networks:
- backend-network
deploy:
resources:
limits:
memory: 300M
reservations:
memory: 100M

networks:
backend-network:
Expand Down
Empty file modified entrypoint.sh
100644 → 100755
Empty file.
Loading

0 comments on commit 906138d

Please sign in to comment.