diff --git a/.dockerignore b/.dockerignore index 019c069c..2a27cf2d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -16,3 +16,4 @@ __pycache__ .python-version *.swp .venv +.ruff_cache diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 180d7532..61b55a17 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,7 +19,7 @@ jobs: peotry- - name: Build the project run: | - echo "ENV=dev" > .env + echo -e "ENV=dev\nUID=$UID" > .env docker-compose up -d --build backend - name: Lint the code run: | diff --git a/Dockerfile b/Dockerfile index e3a03d7d..86d39a5b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,61 @@ -FROM python:3.9 +FROM python:3.11-alpine AS base -WORKDIR /app +RUN apk update --no-cache && apk upgrade --no-cache && apk add shadow --no-cache && useradd -m -r -u 1001 timed && apk del shadow && rm -rf /var/cache/apk/* + +RUN mkdir -p /var/www/static && chown timed:timed /var/www/static + +COPY manage.py /usr/local/bin -RUN apt-get update && apt-get install -y --no-install-recommends wait-for-it \ - libpq-dev \ - && rm -rf /var/lib/apt/lists/* \ - && mkdir -p /app +ENV DJANGO_SETTINGS_MODULE=timed.settings \ + PYTHONUNBUFFERED=1 \ + STATIC_ROOT=/var/www/static \ + HURRICANE_REQ_QUEUE_LEN=200 -ENV DJANGO_SETTINGS_MODULE timed.settings -ENV STATIC_ROOT /var/www/static -ENV WAITFORIT_TIMEOUT 0 +EXPOSE 80 + +FROM base AS build -ENV HURRICANE_REQ_QUEUE_LEN 250 +WORKDIR /app + +ENV PYTHONFAULTHANDLER=1 \ + PYTHONHASHSEED=random \ + PYTHONDONTWRITEBYTECODE=1 \ + # pip: + PIP_DISABLE_PIP_VERSION_CHECK=on \ + PIP_DEFAULT_TIMEOUT=100 \ + # poetry: + POETRY_NO_INTERACTION=1 RUN pip install -U poetry -ARG INSTALL_DEV_DEPENDENCIES=false -COPY pyproject.toml poetry.lock /app/ -RUN poetry config virtualenvs.create false \ - && if [ "$INSTALL_DEV_DEPENDENCIES" = "true" ]; then poetry install; else poetry install --no-dev; fi +COPY . ./ -COPY . /app +FROM build as build-prod -RUN mkdir -p /var/www/static +WORKDIR /app -EXPOSE 80 -CMD ./cmd.sh +RUN poetry build -f wheel && mv ./dist/*.whl /tmp/ + +FROM build as dev + +WORKDIR /app + +RUN apk update --no-cache && apk add wait4ports --no-cache + +RUN apk add gcc python3-dev musl-dev linux-headers && poetry config virtualenvs.create false && poetry install && apk del gcc python3-dev musl-dev linux-headers --no-cache + +USER 1001 + +CMD ["sh", "-c", "wait4ports -s 15 tcp://${DJANGO_DATABASE_HOST:db}:${DJANGO_DATABASE_PORT:5432}; ./cmd.sh --autoreload --static"] + +FROM base as prod + +COPY --from=build-prod /tmp/*.whl /tmp/ + +COPY cmd.sh /usr/local/bin + +RUN apk add gcc python3-dev musl-dev linux-headers --no-cache && pip install /tmp/*.whl --no-cache-dir && rm /tmp/*.whl && apk del gcc python3-dev musl-dev linux-headers --no-cache + +USER 1001 + +CMD ["cmd.sh"] \ No newline at end of file diff --git a/Makefile b/Makefile index a737e19b..20bff931 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ format-code: ## Format the backend code .PHONY: test test: ## Test the project - @docker-compose run --rm backend sh -c "ruff format . && ruff lint . --fix && pytest --no-cov-on-fail --cov" + @docker-compose run --rm backend sh -c "ruff format . && ruff check . --fix && pytest --no-cov-on-fail --cov" .PHONY: bash bash: ## Shell into the backend diff --git a/cmd.sh b/cmd.sh index a83e61a3..dd155770 100755 --- a/cmd.sh +++ b/cmd.sh @@ -4,10 +4,9 @@ set -x -./manage.py collectstatic --noinput +manage.py collectstatic --noinput set -e -wait-for-it "${DJANGO_DATABASE_HOST}":"${DJANGO_DATABASE_PORT}" -t "${WAITFORIT_TIMEOUT}" -./manage.py migrate --no-input -./manage.py serve --static --port 80 --req-queue-len "${HURRICANE_REQ_QUEUE_LEN:-250}" "$@" +manage.py migrate --no-input +manage.py serve --static --port 80 --req-queue-len "${HURRICANE_REQ_QUEUE_LEN:-250}" "$@" \ No newline at end of file diff --git a/docker-compose.override.yml b/compose.override.yaml similarity index 81% rename from docker-compose.override.yml rename to compose.override.yaml index 6c364ba1..21ef053d 100644 --- a/docker-compose.override.yml +++ b/compose.override.yaml @@ -2,19 +2,18 @@ version: "3.7" services: backend: + user: "${UID:?Set UID env variable to your user id}" build: context: . - args: - INSTALL_DEV_DEPENDENCIES: "true" + target: dev depends_on: - mailhog environment: - - PYTHONDONTWRITEBYTECODE=1 + - ENV=dev - EMAIL_URL=smtp://mailhog:1025 - DJANGO_OIDC_USERNAME_CLAIM=preferred_username volumes: - ./:/app - command: /bin/sh cmd.sh --autoreload --static ports: - "81:81" networks: @@ -31,7 +30,7 @@ services: - timed.local keycloak: - image: jboss/keycloak:10.0.1 + image: quay.io/keycloak/keycloak:10.0.1 volumes: - ./dev-config/keycloak-config.json:/etc/keycloak/keycloak-config.json:rw depends_on: @@ -47,7 +46,14 @@ services: - KEYCLOAK_PASSWORD=admin # start keycloak with the following command to perform an export of the `timed` realm. #command: ["-Dkeycloak.migration.action=export", "-Dkeycloak.migration.realmName=timed", "-Dkeycloak.migration.provider=singleFile", "-Dkeycloak.migration.file=/etc/keycloak/keycloak-config.json", "-b", "0.0.0.0"] - command: ["-Dkeycloak.migration.action=import", "-Dkeycloak.migration.provider=singleFile", "-Dkeycloak.migration.file=/etc/keycloak/keycloak-config.json", "-b", "0.0.0.0"] + command: + [ + "-Dkeycloak.migration.action=import", + "-Dkeycloak.migration.provider=singleFile", + "-Dkeycloak.migration.file=/etc/keycloak/keycloak-config.json", + "-b", + "0.0.0.0", + ] networks: - timed.local diff --git a/docker-compose.yml b/compose.yaml similarity index 100% rename from docker-compose.yml rename to compose.yaml diff --git a/pyproject.toml b/pyproject.toml index 1a728ce0..bbc44fdd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "timed-backend" +name = "timed" version = "3.0.7" description = "Timetracking software" repository = "https://github.com/adfinis/timed-backend"