Skip to content

Commit

Permalink
Dockerfile splitted into server and worker targets 😯
Browse files Browse the repository at this point in the history
  • Loading branch information
Sibyx committed Feb 10, 2024
1 parent 8123fe0 commit d554303
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 30 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ REDIS_PORT=6379
RQ_REDIS_DB=0
REDIS_PASSWORD=

GITHUB_TOKEN=
GITHUB_USER=
SECRET_KEY=

BASE_URL=http://127.0.0.1:8000

SENTRY_DSN=''

INSTANCE_NAME=

DJANGO_SETTINGS_MODULE=dbs_tester.settings.development
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
IMAGE_NAME: ${{ github.repository }}-server
DOCKER_BUILDKIT: 1


Expand Down Expand Up @@ -72,3 +72,4 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
target: server
75 changes: 75 additions & 0 deletions .github/workflows/publish-worker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Docker

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
push:
branches: [ master ]
# Publish semver tags as releases.
tags: [ '*.*.*' ]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}-worker
DOCKER_BUILDKIT: 1


jobs:
build:

runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Install poetry
run: |
sudo apt install -y pipx
pipx ensurepath
pipx install poetry
pipx inject poetry poetry-plugin-export
- name: Checkout repository
uses: actions/checkout@v4

- name: Create requirements.txt
run: |
poetry export -f requirements.txt --without-hashes --output requirements.txt
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
target: worker
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

## 1.11.0 : 2024-02-10

Bunch of funky updates into an upcoming summer course! Some attempts were made to make the task result better readable.
Improved scalability moving `worker` outside of the server image and `supervisord` service.
Be a good frogs! 🐸

- **Added**: [Save and prefill image on new test #5](https://github.com/FIIT-Databases/tester/issues/5)
- **Added**: Cool FIIT favicon (super important)
- **Added**: Advanced admin filters
- **Added**: [Basic job history](https://github.com/FIIT-Databases/tester/issues/3)
- **Added**: Creator in Evaluation
- **Added**: [Show request method #4](https://github.com/FIIT-Databases/tester/issues/4)
- **Changed**: Dockerfile separated into two targets: `server` and `worker` so `worker` can be scaled
- **Changed**: Evaluations are managed from Django admin now
- **Changed**: Major task record logging refactor (messages introduced)
- **Changed**: Django 5.0 upgrade
Expand Down
25 changes: 18 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ RUN pip install --user -r requirements.txt --no-cache-dir
RUN npm i
RUN npm run build

FROM python:3.12-slim
FROM python:3.12-slim as base

# Dependencies
RUN apt update -y
RUN apt install -y supervisor curl postgresql-client libjpeg-tools argon2 tzdata ldap-utils nginx docker cron
RUN apt install -y postgresql-client libjpeg-tools argon2 tzdata ldap-utils docker.io

WORKDIR /usr/src/app

Expand All @@ -43,20 +43,31 @@ ENV VIRTUAL_ENV=/opt/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV DOCKER=1

# Configuration
FROM base as server

## nginx
RUN apt install -y supervisor curl nginx cron

# nginx
COPY conf/http.conf /etc/nginx/sites-available/tester-dbs.fiit.stuba.sk
COPY conf/nginx.conf /etc/nginx/nginx.conf
RUN ln -s /etc/nginx/sites-available/tester-dbs.fiit.stuba.sk /etc/nginx/sites-enabled/tester-dbs.fiit.stuba.sk
RUN rm -f /etc/nginx/sites-enabled/default

## supervisord
# supervisord
COPY conf/supervisor.conf /etc/supervisor/supervisord.conf

# Health check
HEALTHCHECK CMD curl --fail http://localhost:9000/api/v1/status || exit 1

# Execution
RUN chmod +x conf/entrypoint.sh
CMD ["conf/entrypoint.sh"]
RUN chmod +x conf/server_entrypoint.sh
CMD ["conf/server_entrypoint.sh"]

FROM base as worker

RUN chmod +x conf/worker_entrypoint.sh
RUN chmod +x conf/worker_probe.sh

HEALTHCHECK CMD conf/worker_probe.sh

CMD ["conf/worker_entrypoint.sh"]
18 changes: 6 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,19 @@ Application use these environments variables:

### Docker

Pre-build Docker image is available on GitHub Container registry as
[ghcr.io/fiit-databases/tester:master](https://github.com/FIIT-Databases/tester/pkgs/container/tester).
Dockerfile contains two targets which are pre-build and available on GitHub Container registry:

To run the image as a container you can use command bellow (keep in mind that you have to specify the environment
variables accordingly). The logs from container are present in the `/var/log` so you have to create a volume to access
them (present in the example).
- [ghcr.io/fiit-databases/tester-server:master](https://github.com/FIIT-Databases/tester/pkgs/container/tester-server)
- [ghcr.io/fiit-databases/tester-worker:master](https://github.com/FIIT-Databases/tester/pkgs/container/tester-worker)

The container requires access to the Docker environment that's why you have to create volume, which maps a path to the
Example of configuration is present in `compose.yml`.

The containers require access to the Docker environment that's why you have to create volume, which maps a path to the
Docker socket.

Docker network have to be created and provided to the application using `DBS_DOCKER_NETWORK` environment variable.
Network `dbs` is used in the example

```shell
docker run -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v ./logs:/var/log/ --env BASE_URL= --env ALLOWED_HOSTS= --env DATABASE_HOST= --env DATABASE_NAME= --env DATABASE_PASSWORD= --env DATABASE_PORT= --env DATABASE_USER= --env DJANGO_SETTINGS_MODULE=dbs_tester.settings.production --env REDIS_HOST= --env SECRET_KEY= --env GITHUB_TOKEN= --env GITHUB_USER= --name dbs-tester --network dbs --add-host=host.docker.internal:host-gateway ghcr.io/fiit-databases/tester:master
```

Server started on port 9000.

Repository contains an example of the **systemd unit script** in the `conf/tester-dbs.service`.

### From source
Expand Down
49 changes: 49 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: dbs-tester

services:
server:
build:
context: .
target: server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- private_volume:/usr/local/app/private
environment:
DATABASE_HOST: ${DATABASE_HOST}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_USER: ${DATABASE_USER}
DJANGO_SETTINGS_MODULE: ${DJANGO_SETTINGS_MODULE}
GITHUB_TOKEN: ${GITHUB_TOKEN}
GITHUB_USER: ${GITHUB_USER}
REDIS_HOST: ${REDIS_HOST}
SECRET_KEY: ${SECRET_KEY}
ports:
- 8000:9000
worker:
build:
context: .
target: worker
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
DATABASE_HOST: ${DATABASE_HOST}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_USER: ${DATABASE_USER}
DJANGO_SETTINGS_MODULE: ${DJANGO_SETTINGS_MODULE}
GITHUB_TOKEN: ${GITHUB_TOKEN}
GITHUB_USER: ${GITHUB_USER}
REDIS_HOST: ${REDIS_HOST}
SECRET_KEY: ${SECRET_KEY}
scale: 4
depends_on:
- server
networks:
intranet:
name: dbs
external: true
volumes:
private_volume:
14 changes: 14 additions & 0 deletions conf/server_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

until PGPASSWORD=$DATABASE_PASSWORD psql -h "$DATABASE_HOST" -U "$DATABASE_USER" -c '\q'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done

python3 manage.py collectstatic --no-input
python3 manage.py migrate
python3 manage.py setup

echo "$GITHUB_TOKEN" | docker login ghcr.io -u $GITHUB_USER --password-stdin

supervisord -c /etc/supervisor/supervisord.conf
20 changes: 10 additions & 10 deletions conf/supervisor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ priority=900
stdout_logfile=/var/log/gunicorn.stdout.log
stderr_logfile=/var/log/gunicorn.stderr.log

[program:worker]
directory=/usr/src/app
command=python3 manage.py rqworker default
autostart=true
autorestart=true
priority=900
stdout_logfile=/var/log/rqworker.stdout.log
stderr_logfile=/var/log/rqworker.stderr.log
numprocs=4
process_name=%(program_name)s_%(process_num)02d
;[program:worker]
;directory=/usr/src/app
;command=python3 manage.py rqworker default
;autostart=true
;autorestart=true
;priority=900
;stdout_logfile=/var/log/rqworker.stdout.log
;stderr_logfile=/var/log/rqworker.stderr.log
;numprocs=4
;process_name=%(program_name)s_%(process_num)02d

[program:nginx]
command=/usr/sbin/nginx
Expand Down
10 changes: 10 additions & 0 deletions conf/worker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

until PGPASSWORD=$DATABASE_PASSWORD psql -h "$DATABASE_HOST" -U "$DATABASE_USER" -c '\q'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done

echo "$GITHUB_TOKEN" | docker login ghcr.io -u $GITHUB_USER --password-stdin

python3 manage.py rqworker default
12 changes: 12 additions & 0 deletions conf/worker_probe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

RUNNING_WORKER_PROCESS_COUNT=$(pgrep -f ".*rq" --count)

echo "$RUNNING_WORKER_PROCESS_COUNT/$WORKER_PROCESS_COUNT processes running "

if [ ${RUNNING_WORKER_PROCESS_COUNT} == ${WORKER_PROCESS_COUNT} ]
then
exit 0
else
exit 1
fi

0 comments on commit d554303

Please sign in to comment.