-FROM python:3.8 AS base
+FROM python:3.9-trixie AS base
+
+ARG UID=1000
+ARG GID=1000
RUN apt-get update && apt-get install -y \
git \
calibre \
texlive-xetex texlive-lang-polish \
- libespeak-dev
-
-COPY requirements/requirements.txt requirements.txt
-
-# numpy -> aeneas
-RUN pip install numpy
-RUN pip install aeneas
-
-RUN pip install --no-cache-dir -r requirements.txt
-RUN pip install --no-cache-dir \
- psycopg2-binary \
- django-debug-toolbar==3.2.2 \
- python-bidi
-
-RUN apt-get install -y \
texlive-extra-utils \
texlive-lang-greek \
texlive-lang-other \
fonts-noto-core fonts-noto-extra
+COPY requirements/requirements.txt requirements.txt
+
+RUN pip install --no-cache-dir -r requirements.txt
+RUN pip install --no-cache-dir \
+ psycopg2-binary \
+ django-debug-toolbar==3.2.2
+
+RUN addgroup --gid $GID app && \
+ adduser --gid $GID --home /app --uid $UID app
+
+
# fonts
-RUN cp -a /usr/local/lib/python*/site-packages/librarian/fonts /usr/local/share/fonts
+RUN cp -a /usr/local/lib/python*/site-packages/librarian/fonts /usr/share/fonts
RUN fc-cache
+USER app
+
WORKDIR /app/src
+RUN mkdir /app/.ipython
FROM base AS dev
-.PHONY: deploy test shell
+.PHONY: deploy test up down build shell logs restart
-UID != id -u
-GID != id -g
+UID := $(shell id -u)
+GID := $(shell id -g)
deploy: src/wolnelektury/localsettings.py
rm .coverage
-shell:
- UID=$(UID) GID=$(GID) docker compose run --rm dev bash
+up:
+ UID=$(UID) GID=$(GID) docker compose up --build -d
+down:
+ docker compose down
build:
- docker compose build dev
+ UID=$(UID) GID=$(GID) docker compose build
+
+shell:
+ UID=$(UID) GID=$(GID) docker compose run --rm web bash
+
+logs:
+ docker compose logs -f
+
+restart:
+ docker compose restart
+x-app-base: &app-base
+ build:
+ context: .
+ target: dev
+ args:
+ UID: ${UID:-1000}
+ GID: ${GID:-1000}
+ env_file:
+ - .env
+ volumes:
+ - ./src:/app/src
+ - ./var/media:/app/var/media
+ - ./var/static:/app/var/static
+ - ./var/counters/:/app/var/counters
+ - ipython:/app/.ipython
+ depends_on:
+ - db
+ - redis
+ - memcached
+
services:
- dev:
- build:
- context: .
- target: dev
- user: "${UID}:${GID}"
- volumes:
- - ./src:/app/src
- - ./var/media:/app/var/media
- - ./var/static:/app/var/static
- - ./var/counters/:/app/var/counters
- depends_on:
- - db
- env_file:
- - .env
+ web:
+ <<: *app-base
+ ports:
+ - "8000:8000"
+ command: ./manage.py runserver 0.0.0.0:8000
+
+ celery:
+ <<: *app-base
+ command: celery -A wolnelektury worker -l info
+
db:
- image: postgres:18.0
+ image: postgres:18
container_name: db
env_file:
- .env
volumes:
- ./var/postgresql-data/:/var/lib/postgresql/
+
+ redis:
+ image: redis:8-alpine
+
+ memcached:
+ image: memcached:1.6-alpine
+
+
+volumes:
+ ipython:
\ No newline at end of file
+++ /dev/null
-#!/bin/sh
-export UID=`id -u`
-export GID=`id -g`
-
-if [ "$1" = "runserver" ]
-then
- PORT="$2"
- [ -z "$PORT" ] && PORT=8000
- EXPOSED=127.0.0.1:"$PORT"
- echo "expose as: $EXPOSED"
- exec docker compose run --rm -p "$EXPOSED":"$PORT" dev python $PYARGS manage.py runserver 0.0.0.0:"$PORT"
-else
- exec docker compose run --rm dev python $PYARGS manage.py "$@"
-fi
sorl-thumbnail==12.10.0
# home-brewed & dependencies
-librarian==25.12
+librarian==26.2
# celery tasks
celery[redis]==5.4.0
firebase-admin==6.6.0
Wikidata==0.8.1
+ipython
CACHE_MIDDLEWARE_SECONDS = 3 * 60
+CACHES = {
+ 'default': {
+ 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
+ 'TIMEOUT': 180,
+ 'LOCATION': [
+ 'memcached:11211',
+ ],
+ },
+ 'template_fragments': {
+ 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
+ 'TIMEOUT': 86400,
+ 'LOCATION': [
+ 'memcached:11211',
+ ],
+ },
+}
+
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
# This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
#
+CELERY_BROKER_URL = 'redis://redis'
CELERY_TASK_EAGER_PROPAGATES = True
CELERY_SEND_TASK_ERROR_EMAILS = True
CELERY_ACCEPT_CONTENT = ['pickle']