Skip to content

Commit

Permalink
Merge pull request #1127 from open-dynaMIX/docker-setup
Browse files Browse the repository at this point in the history
use multi stage docker build for api and push to registry
  • Loading branch information
winged authored Aug 26, 2024
2 parents 737bef9 + 3b75c3e commit 7e0273f
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 55 deletions.
76 changes: 76 additions & 0 deletions .github/workflows/ghcr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Container image

on:
release:
types: [created]

# Run build for any PRs - we won't push in those however
pull_request:
branches:
- main

# Publish `main` as Docker `dev` image.
push:
branches:
- main

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

env:
IMAGE_NAME: ${{ github.repository }}
REGISTRY: ghcr.io

jobs:
# Push image to GitHub Packages.
# See also https://docs.docker.com/build/ci/github-actions/
container-registry:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- image: ${{ github.repository }}
path: api
- image: ${{ github.repository }}-caluma
path: caluma
permissions:
packages: write
contents: read

steps:
- uses: actions/checkout@v4

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

- name: Log in to the Container registry
uses: docker/login-action@v3
if: github.event_name != 'pull_request'
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image }}
tags: |
type=raw,value=dev,enable={{is_default_branch}}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: "{{defaultContext}}:${{ matrix.path }}"
file: ./Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ jobs:
- uses: actions/checkout@v4
- name: Set UID
run: echo "UID=$(id --user)" > .env
- name: Build the containers
run: docker compose up -d --build api db
- name: Build and run the containers
run: docker compose up -d --build api db
- name: Lint the code
run: make api-lint
- name: Check for missing migrations
run: docker compose exec -T api poetry run ./manage.py makemigrations --check --dry-run --no-input
run: docker compose exec -T api ./manage.py makemigrations --check --dry-run --no-input
- name: Run test suite
run: make api-test
caluma-tests:
Expand Down
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,32 @@ start: ## Start the development server

.PHONY: api-test
api-test: ## Test the backend
@docker compose run --rm api poetry run pytest --no-cov-on-fail --cov -vv
@docker compose run --rm api pytest --no-cov-on-fail --cov -vv

.PHONY: api-lint
api-lint: ## Lint the backend
@docker compose run --rm api sh -c "poetry run ruff format --diff . && poetry run ruff check ."
@docker compose run --rm api sh -c "ruff format --diff . && ruff check ."

.PHONY: api-bash
api-bash: ## Shell into the backend
@docker compose run --rm api bash

.PHONY: api-shell_plus
api-shell_plus: ## Run shell_plus
@docker compose run --rm api poetry run ./manage.py shell_plus
@docker compose run --rm api ./manage.py shell_plus

.PHONY: api-dev-server
api-dev-server: ## Start backend dev server
@docker compose stop api
@docker compose run --user root --use-aliases --service-ports api bash -c 'pip install pdbpp && poetry run ./manage.py runserver 0.0.0.0:8000'
@docker compose run --user root --use-aliases --service-ports api bash -c 'pip install pdbpp && ./manage.py runserver 0.0.0.0:8000'

.PHONY: makemigrations
makemigrations: ## Make django migrations
@docker compose run --rm api poetry run ./manage.py makemigrations
@docker compose run --rm api ./manage.py makemigrations

.PHONY: migrate
migrate: ## Migrate django
@docker compose run --rm api poetry run ./manage.py migrate
@docker compose run --rm api ./manage.py migrate

.PHONY: dbshell
dbshell: ## Start a psql shell
Expand Down
80 changes: 54 additions & 26 deletions api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,38 +1,66 @@
FROM python:3.9
FROM python:3.12-alpine AS base

# needs to be set for users with manually set UID
ENV HOME=/home/mysagw
RUN apk update --no-cache && \
apk upgrade --no-cache && \
apk add wait4ports shadow libpq-dev --no-cache && \
useradd -m -r -u 1001 mysagw && \
apk del shadow && \
rm -rf /var/cache/apk/*

ENV PYTHONUNBUFFERED=1
ENV DJANGO_SETTINGS_MODULE mysagw.settings
ENV APP_HOME=/app
ENV DJANGO_SETTINGS_MODULE=mysagw.settings \
PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100

RUN mkdir -p /app \
&& useradd -u 901 -r mysagw --create-home \
# all project specific folders need to be accessible by newly created user but also for unknown users (when UID is set manually). Such users are in group root.
&& chown -R mysagw:root /home/mysagw \
&& chmod -R 770 /home/mysagw \
&& apt-get update && apt-get install -y --no-install-recommends \
wait-for-it \
# needed for psycopg2
libpq-dev \
&& pip install -U poetry
EXPOSE 8000

USER mysagw
FROM base AS build

WORKDIR $APP_HOME
WORKDIR /app

ARG INSTALL_DEV_DEPENDENCIES=false
COPY pyproject.toml poetry.lock $APP_HOME/
RUN if [ "$INSTALL_DEV_DEPENDENCIES" = "true" ]; then poetry install --with dev; else poetry install; fi
COPY . ./

COPY . $APP_HOME
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_CREATE=false

EXPOSE 8000
RUN pip install -U poetry

FROM build AS wheel

WORKDIR /app

RUN poetry build -f wheel && mv ./dist/*.whl /tmp/ && pip uninstall -y poetry

FROM build AS dev

WORKDIR /app

RUN poetry install --no-root

USER 1001

CMD [\
"/bin/sh", "-c", \
"wait4ports -s 15 tcp://${DATABASE_HOST:-db}:${DATABASE_PORT:-5432} && \
./manage.py migrate --no-input && \
./manage.py runserver 0.0.0.0:8000 -v 3" \
]

FROM base AS prod

COPY manage.py /usr/local/bin
COPY --from=wheel /tmp/*.whl /tmp/

RUN pip install /tmp/*.whl && rm /tmp/*.whl

USER 1001

CMD [\
"/bin/sh", "-c", \
"wait-for-it $DATABASE_HOST:${DATABASE_PORT:-5432} -- \
poetry run ./manage.py migrate && \
exec poetry run gunicorn --workers 10 --access-logfile - --limit-request-line 16384 --bind 0.0.0.0:8000 mysagw.wsgi" \
"wait4ports -s 15 tcp://${DATABASE_HOST:-db}:${DATABASE_PORT:-5432} && \
manage.py migrate --no-input && \
gunicorn --workers 10 --access-logfile - --limit-request-line 16384 --bind :8000 mysagw.wsgi" \
]
5 changes: 3 additions & 2 deletions api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ description = "Application management for SAGW"
repository = "https://github.com/adfinis/mySAGW"
authors = ["Adfinis"]
license = "GPL-3.0-or-later"
readme = "../README.md"

[tool.poetry.dependencies]
python = "^3.9"
Expand Down Expand Up @@ -132,7 +131,9 @@ filterwarnings = [
"ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning", # issue in pytest-freezegun
"ignore:LocalizedAutoSlug is deprecated and will be removed in the next major version:DeprecationWarning",
"ignore:'django_extensions' defines default_app_config:PendingDeprecationWarning", # deprecation in django_extensions
"ignore:CSR support in pyOpenSSL is deprecated. You should use the APIs in cryptography.:DeprecationWarning", # deprecation in mozilla-django-oidc
"ignore:CSR support in pyOpenSSL is deprecated. You should use the APIs in cryptography.:DeprecationWarning", # deprecation in a dependency of mozilla-django-oidc
"ignore:ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead:DeprecationWarning", # deprecation from reportlab
"ignore:.*Use timezone-aware objects to represent datetimes in UTC.*:DeprecationWarning", # deprecation in openpyxl
]

[tool.coverage.run]
Expand Down
10 changes: 1 addition & 9 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
version: "3"
services:
db:
env_file: ./.envs/.local/.postgres

api:
build:
context: ./api/
args:
INSTALL_DEV_DEPENDENCIES: "true"
target: dev
user: "${UID:?Set UID env variable to your user id}"
volumes:
- ./api:/app
ports:
- "8000:8000"
command:
[
"/bin/sh",
"-c",
"wait-for-it db:5432 -- poetry run ./manage.py migrate && poetry run ./manage.py runserver 0.0.0.0:8000",
]
env_file: ./.envs/.local/.api

caluma:
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3"

services:

db:
Expand Down
5 changes: 1 addition & 4 deletions docker-compose.staging.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
version: "3"

services:

db:
env_file: ./.envs/.staging/.postgres
restart: unless-stopped

api:
build:
context: ./api/
image: ghcr.io/adfinis/mysagw:0.1.0
env_file: ./.envs/.staging/.api
restart: unless-stopped

Expand Down
4 changes: 1 addition & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3"

services:

db:
Expand All @@ -11,7 +9,7 @@ services:
- "5432:5432"

api:
image: adfinis-sygroup/mysagw
image: ghcr.io/adfinis/mysagw:latest
environment:
- DATABASE_HOST=db
- DATABASE_PORT=5432
Expand Down

0 comments on commit 7e0273f

Please sign in to comment.