**Refactor Docker and Compose for enhanced compatibility and efficiency**

- Restructured `Dockerfile` to include a dedicated frontend build stage and improved runtime configurations.
- Added new health checks and adjusted environment variables for better container management.
- Updated cron job configurations to leverage `/opt/venv` and align with new paths.
- Refined `docker-compose` files for multi-service setups, including better volume and environment variable handling.
- Migrated `cbwebreader-cron` service setup and improved restart policies across the board.
- Enhanced `.gitea` CI workflow to use updated tools (`uv`), streamline buildx processes, and ensure proper version extraction from metadata.
This commit is contained in:
ajurna committed 2026-10-13 10:25:07 +01:00
1 parent 9b9db755e6
commit 147a3a54ef
9 files changed
+122 -92

No files matched your search

-2
View File
@@ -3,7 +3,6 @@
!cbreader !cbreader
!comic !comic
!comic_auth
!static !static
!manage.py !manage.py
!pyproject.toml !pyproject.toml
@@ -14,6 +13,5 @@
!package-lock.json !package-lock.json
!package.json !package.json
!frontend !frontend
!uv.lock
/frontend/node_modules /frontend/node_modules
/frontend/dist /frontend/dist
+5 -3
View File
@@ -15,8 +15,10 @@ DB_DATABASE=cbwebreader
# https://github.com/jacobian/dj-database-url # https://github.com/jacobian/dj-database-url
DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_DATABASE} DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_DATABASE}
#Path to your comics. # Path to your comics *inside* the container. Keep this as a container path.
COMIC_BOOK_VOLUME=/media/plex/comics COMIC_BOOK_VOLUME=/comics
# Host path that is mounted to the path above.
COMIC_BOOK_HOST_PATH=/media/plex/comics
STATIC_ROOT='/static' STATIC_ROOT='/static'
@@ -32,4 +34,4 @@ MEDIA_ROOT='/media'
# DJANGO_RECAPTCHA_PUBLIC_KEY = '' # DJANGO_RECAPTCHA_PUBLIC_KEY = ''
# Comment the following if not using a reverse proxy. # Comment the following if not using a reverse proxy.
USE_X_FORWARDED_HOST=True USE_X_FORWARDED_HOST=True
+5 -3
View File
@@ -15,8 +15,10 @@ DB_DATABASE=cbwebreader
# https://github.com/jacobian/dj-database-url # https://github.com/jacobian/dj-database-url
DATABASE_URL='postgres://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_DATABASE}' DATABASE_URL='postgres://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_DATABASE}'
# Path to your comics. # Path to your comics *inside* the container. Keep this as a container path.
COMIC_BOOK_VOLUME=/path/to/comic/folder COMIC_BOOK_VOLUME=/comics
# Host path that is mounted to the path above (this is the one that varies per machine).
COMIC_BOOK_HOST_PATH=/path/to/comic/folder
# Usually fine tp leave as is. # Usually fine tp leave as is.
STATIC_ROOT=/static STATIC_ROOT=/static
@@ -29,4 +31,4 @@ MEDIA_ROOT='/media'
# UNRAR_TOOL = 'unrar.exe' # UNRAR_TOOL = 'unrar.exe'
# Comment the following if not using a reverse proxy. # Comment the following if not using a reverse proxy.
USE_X_FORWARDED_HOST=True USE_X_FORWARDED_HOST=True
+8 -12
View File
@@ -12,25 +12,21 @@ jobs:
run: curl -fsSL https://get.docker.com | sh run: curl -fsSL https://get.docker.com | sh
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx - name: Set up Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v2 uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: install pip - uses: actions/checkout@v4
run: apt update && apt install -y python3-pip - name: Install uv
- uses: abatilo/actions-poetry@v2 run: pip install uv
with: # Extract version from the project metadata
poetry-version: "1.6.1"
- uses: actions/setup-node@v3
- uses: actions/checkout@v3
# Extract version from Poetry
- name: Get version - name: Get version
run: echo "POETRY_VERSION=$(poetry version --short)" >> $GITHUB_ENV run: echo "PROJECT_VERSION=$(uv version --short)" >> $GITHUB_ENV
- name: Build and push Docker image - name: Build and push Docker image
run: | run: |
docker build -t ajurna/cbwebreader:latest -t ajurna/cbwebreader:${{ env.POETRY_VERSION }} . docker build -t ajurna/cbwebreader:latest -t ajurna/cbwebreader:${{ env.PROJECT_VERSION }} .
docker push ajurna/cbwebreader:${{ env.POETRY_VERSION }} docker push ajurna/cbwebreader:${{ env.PROJECT_VERSION }}
docker push ajurna/cbwebreader:latest docker push ajurna/cbwebreader:latest
+42 -21
View File
@@ -1,36 +1,57 @@
FROM python:3.14-slim-trixie # ---------------------------------------------------------------------------
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Frontend build stage
ENV PYTHONFAULTHANDLER=1 \ # ---------------------------------------------------------------------------
PYTHONHASHSEED=random \ FROM node:22-slim AS frontend
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_DEFAULT_TIMEOUT=100 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1
ENV PATH="${PATH}:/root/.local/bin"
RUN mkdir /src
RUN mkdir /static
WORKDIR /src WORKDIR /src
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
RUN echo "deb http://ftp.uk.debian.org/debian trixie non-free non-free-firmware" > /etc/apt/sources.list.d/non-free.list # ---------------------------------------------------------------------------
# Runtime stage
# ---------------------------------------------------------------------------
FROM python:3.14-slim-trixie
RUN apt update \ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
&& apt install -y npm cron unrar libmariadb-dev libpq-dev pkg-config swig curl
COPY . /src/ ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
ENV UV_PROJECT_ENVIRONMENT=/opt/venv
ENV PATH="/opt/venv/bin:$PATH"
# unrar lives in the non-free component; resolve the codename from the base image
# instead of hardcoding it.
RUN . /etc/os-release \
&& echo "deb http://deb.debian.org/debian ${VERSION_CODENAME} non-free non-free-firmware" \
> /etc/apt/sources.list.d/non-free.list \
&& apt update \
&& apt install -y --no-install-recommends cron unrar libmariadb-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
# Lockfiles first so dependency installation is cached independently of the source.
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev RUN uv sync --frozen --no-dev
RUN cd frontend \ COPY . /src/
&& npm install \ COPY --from=frontend /src/dist /src/frontend/dist
&& npm run build \ COPY --from=frontend /src/webpack-stats.json /src/frontend/webpack-stats.json
&& rm -r node_modules
RUN mkdir -p /static /media
RUN cat /src/cbreader/crontab >> /etc/crontab RUN cat /src/cbreader/crontab >> /etc/crontab
EXPOSE 8000 EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/')" || exit 1
CMD ["sh", "entrypoint.sh"]
+1 -1
View File
@@ -1 +1 @@
*/15 * * * * root /src/.venv/bin/python /src/manage.py scan_comics --settings=cbreader.settings.base */15 * * * * root /opt/venv/bin/python /src/manage.py scan_comics --settings=cbreader.settings.base
+24 -19
View File
@@ -1,64 +1,69 @@
version: "2.4"
services: services:
cbwebreader: cbwebreader:
build: ../
image: ajurna/cbwebreader image: ajurna/cbwebreader
env_file: .env env_file: .env
links:
- database
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
expose: expose:
- 8000 - 8000
volumes: volumes:
- ${COMIC_BOOK_VOLUME}:${COMIC_BOOK_VOLUME} # COMIC_BOOK_VOLUME is the path *inside* the container; the host path is
# a separate variable so a Windows host path is not passed to Django.
- ${COMIC_BOOK_HOST_PATH}:${COMIC_BOOK_VOLUME}
- static_files:/static - static_files:/static
- media_files:/media - media_files:/media
- .env:/src/.env - .env:/src/.env
command: /bin/bash entrypoint.sh command: sh entrypoint.sh
restart: unless-stopped
cbwebreader-cron: cbwebreader-cron:
build: ../
image: ajurna/cbwebreader image: ajurna/cbwebreader
env_file: .env env_file: .env
links:
- database
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
volumes: volumes:
- ${COMIC_BOOK_VOLUME}:${COMIC_BOOK_VOLUME} - ${COMIC_BOOK_HOST_PATH}:${COMIC_BOOK_VOLUME}
- media_files:/media - media_files:/media
- .env:/src/.env - .env:/src/.env
command: /bin/bash entrypoint-cron.sh command: sh entrypoint-cron.sh
restart: unless-stopped
database: database:
image: postgres:18-alpine image: postgres:16-alpine
expose: expose:
- 5432 - 5432
volumes: volumes:
- ./data:/var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U $DB_USER -d $DB_DATABASE"] test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s interval: 5s
timeout: 10s timeout: 10s
retries: 3 retries: 3
environment: environment:
- POSTGRES_USER=${DB_USER} POSTGRES_USER: ${DB_USER}
- POSTGRES_PASSWORD=${DB_PASS} POSTGRES_PASSWORD: ${DB_PASS}
- POSTGRES_DB=${DB_DATABASE} POSTGRES_DB: ${DB_DATABASE}
restart: unless-stopped
nginx: nginx:
image: nginx image: nginx:1-alpine
volumes: volumes:
- static_files:/static - static_files:/static
- media_files:/media - media_files:/media
- ./nginx.conf:/etc/nginx/conf.d/default.conf - ./nginx.conf:/etc/nginx/conf.d/default.conf
ports: ports:
- 1337:80 - "${WEB_PORT:-8337}:80"
depends_on: depends_on:
- cbwebreader cbwebreader:
condition: service_healthy
restart: unless-stopped
volumes: volumes:
static_files: static_files:
media_files: media_files:
postgres_data:
+32 -28
View File
@@ -1,65 +1,69 @@
version: "2.4"
services: services:
cbwebreader: cbwebreader:
build: . build: .
image: ajurna/cbwebreader
env_file: .env env_file: .env
links:
- database
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
expose: expose:
- 8000 - 8000
volumes: volumes:
# - ${COMIC_BOOK_VOLUME}:/comics # COMIC_BOOK_VOLUME is the path *inside* the container; the host path is
- c:/comics:/comics # a separate variable so a Windows host path is not passed to Django.
- ${COMIC_BOOK_HOST_PATH}:${COMIC_BOOK_VOLUME}
- static_files:/static - static_files:/static
- media_files:/media - media_files:/media
- .env:/src/.env - .env:/src/.env
command: /bin/bash /src/entrypoint.sh command: sh entrypoint.sh
restart: unless-stopped
# cbwebreader-cron: cbwebreader-cron:
# build: . build: .
# env_file: .env image: ajurna/cbwebreader
# links: env_file: .env
# - database depends_on:
# depends_on: database:
# database: condition: service_healthy
# condition: service_healthy volumes:
# volumes: - ${COMIC_BOOK_HOST_PATH}:${COMIC_BOOK_VOLUME}
# - ${COMIC_BOOK_VOLUME}:${COMIC_BOOK_VOLUME} - media_files:/media
# - media_files:/media - .env:/src/.env
# - .env:/src/.env command: sh entrypoint-cron.sh
# command: /bin/bash entrypoint-cron.sh restart: unless-stopped
database: database:
image: postgres:16-alpine image: postgres:16-alpine
expose: expose:
- 5432 - 5432
volumes: volumes:
- /var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U $DB_USER -d $DB_DATABASE"] test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s interval: 5s
timeout: 10s timeout: 10s
retries: 3 retries: 3
environment: environment:
- POSTGRES_USER=${DB_USER} POSTGRES_USER: ${DB_USER}
- POSTGRES_PASSWORD=${DB_PASS} POSTGRES_PASSWORD: ${DB_PASS}
- POSTGRES_DB=${DB_DATABASE} POSTGRES_DB: ${DB_DATABASE}
restart: unless-stopped
nginx: nginx:
image: nginx image: nginx:1-alpine
volumes: volumes:
- static_files:/static - static_files:/static
- media_files:/media - media_files:/media
- ./cbreader/settings/nginx.conf:/etc/nginx/conf.d/default.conf - ./cbreader/settings/nginx.conf:/etc/nginx/conf.d/default.conf
ports: ports:
- 8337:80 - "${WEB_PORT:-8337}:80"
depends_on: depends_on:
- cbwebreader cbwebreader:
condition: service_healthy
restart: unless-stopped
volumes: volumes:
static_files: static_files:
media_files: media_files:
postgres_data:
+5 -3
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env sh #!/usr/bin/env sh
uv run manage.py migrate --settings=cbreader.settings.base set -e
uv run manage.py collectstatic --settings=cbreader.settings.base --noinput --clear python manage.py migrate --settings=cbreader.settings.base
uv run gunicorn --workers 3 --bind 0.0.0.0:8000 cbreader.wsgi:application python manage.py collectstatic --settings=cbreader.settings.base --noinput --clear
exec gunicorn --workers 3 --bind 0.0.0.0:8000 cbreader.wsgi:application