Added docker functionality.
This commit is contained in:
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Files/directories to exclude from Docker build context
|
||||||
|
venv
|
||||||
|
node_modules
|
||||||
|
__pycache__
|
||||||
|
*.db
|
||||||
|
*.db.bak
|
||||||
|
image_selections.db*
|
||||||
|
.git
|
||||||
27
Dockerfile
Normal file
27
Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Dockerfile for SWIPER image-swipe application
|
||||||
|
# ------------------------------------------------
|
||||||
|
# This image runs the built-in Python HTTP server provided by server.py.
|
||||||
|
# Pillow needs system libs so we install them via apt.
|
||||||
|
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Install system packages required by Pillow (JPEG, zlib)
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends build-essential libjpeg-dev zlib1g-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set work directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install Python dependencies first (leverages Docker layer caching)
|
||||||
|
COPY requirements.txt ./
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy application source
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose the default port
|
||||||
|
EXPOSE 8888
|
||||||
|
|
||||||
|
# Start the server
|
||||||
|
CMD ["python", "server.py"]
|
||||||
33
README.md
33
README.md
@@ -56,3 +56,36 @@ This will reset and recalculate all `nsfw` flags so that the new filters work co
|
|||||||
- Python 3.x
|
- Python 3.x
|
||||||
- Standard Python libraries (http.server, sqlite3, etc.)
|
- Standard Python libraries (http.server, sqlite3, etc.)
|
||||||
- Web browser with JavaScript enabled
|
- Web browser with JavaScript enabled
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
If you have Docker installed you can build and run the application in an isolated container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build image (only once)
|
||||||
|
docker build -t swiper-app .
|
||||||
|
|
||||||
|
# Run the container on port 8888
|
||||||
|
docker run --rm -p 8888:8888 swiper-app
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open [http://localhost:8888](http://localhost:8888) in your browser.
|
||||||
|
|
||||||
|
The Dockerfile uses a minimal Python 3.11 image, installs the Python dependencies from `requirements.txt`, exposes port 8888 and starts the app with `python server.py`.
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
|
||||||
|
A `docker-compose.yml` file is included so you can run the container with your image folders mounted automatically.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build image (first time or when code changes)
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will:
|
||||||
|
|
||||||
|
- Publish port **8888** on your host → container.
|
||||||
|
- Mount the portrait and landscape image folders (update paths in `docker-compose.yml` as needed) read-only into `/media/Portrait` and `/media/Landscape` inside the container.
|
||||||
|
- Set `IMAGE_DIRS=/media/Portrait:/media/Landscape` so the server finds the images.
|
||||||
|
|
||||||
|
Adjust ports, folders or environment variables by editing `docker-compose.yml`. Remember to rebuild (`docker compose up --build`) after changes.
|
||||||
|
|||||||
29
config.py
29
config.py
@@ -8,22 +8,31 @@ import os
|
|||||||
# Base directory of the repo (this file lives in the project root)
|
# Base directory of the repo (this file lives in the project root)
|
||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
# Paths to the folders that contain source images. Add as many as you like.
|
# Paths to the folders that contain source images. Can be overridden at runtime
|
||||||
IMAGE_DIRS = [
|
# via the IMAGE_DIRS environment variable (colon-separated paths).
|
||||||
"/mnt/secret-items/sd-outputs/Sorted/Images/Portrait",
|
_IMAGE_DIRS_DEFAULT = [
|
||||||
"/mnt/secret-items/sd-outputs/Sorted/Images/Landscape",
|
"/media/Portrait",
|
||||||
|
"/media/Landscape",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Backwards-compatibility: first directory
|
_IMAGE_DIRS_ENV = os.getenv("IMAGE_DIRS")
|
||||||
IMAGE_DIR = IMAGE_DIRS[0]
|
if _IMAGE_DIRS_ENV:
|
||||||
|
IMAGE_DIRS = _IMAGE_DIRS_ENV.split(":")
|
||||||
|
else:
|
||||||
|
IMAGE_DIRS = _IMAGE_DIRS_DEFAULT
|
||||||
|
|
||||||
|
# Backwards-compatibility: first directory
|
||||||
|
IMAGE_DIR = IMAGE_DIRS[0] if IMAGE_DIRS else ""
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
# SQLite database file that stores selections & metadata
|
# Data directory (override with DATA_DIR env var)
|
||||||
DB_PATH = os.path.join(BASE_DIR, "image_selections.db")
|
DATA_DIR = os.getenv("DATA_DIR", BASE_DIR)
|
||||||
|
|
||||||
# Default port for the HTTP server
|
# SQLite database file that stores selections & metadata
|
||||||
PORT = 8000
|
DB_PATH = os.path.join(DATA_DIR, "image_selections.db")
|
||||||
|
|
||||||
|
# Default port for the HTTP server (override with PORT env var)
|
||||||
|
PORT = int(os.getenv("PORT", 8888))
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# NSFW detection configuration
|
# NSFW detection configuration
|
||||||
|
|||||||
@@ -356,7 +356,9 @@ def sync_image_database() -> None:
|
|||||||
|
|
||||||
# Now, parse and store prompt details for the new images
|
# Now, parse and store prompt details for the new images
|
||||||
for row in rows:
|
for row in rows:
|
||||||
rel_path, _, _, _, _, _, prompt = row
|
# row structure: (path, w, h, name, orientation, ts, prompt, nsfw_flag)
|
||||||
|
rel_path = row[0]
|
||||||
|
prompt = row[6]
|
||||||
if prompt:
|
if prompt:
|
||||||
parse_and_store_prompt_details(rel_path, prompt)
|
parse_and_store_prompt_details(rel_path, prompt)
|
||||||
|
|
||||||
|
|||||||
33
docker-compose.yml
Normal file
33
docker-compose.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
services:
|
||||||
|
swiper:
|
||||||
|
build: .
|
||||||
|
container_name: swiper
|
||||||
|
# --- Environment overrides ------------------------------------------------
|
||||||
|
# Set the port and the internal image directories list. The example below
|
||||||
|
# assumes two folders mounted at /media/Portrait and /media/Landscape inside
|
||||||
|
# the container. Adjust IMAGE_DIRS (colon-separated) and the volume mounts
|
||||||
|
# to reflect your own paths.
|
||||||
|
environment:
|
||||||
|
- PORT=8888
|
||||||
|
- IMAGE_DIRS=/media/Portrait:/media/Landscape
|
||||||
|
# Directory inside the container where the SQLite DB will live
|
||||||
|
- DATA_DIR=/data
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Map host port -> container port
|
||||||
|
ports:
|
||||||
|
- "8888:8888"
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Volumes
|
||||||
|
# • Mount the host image folders into /media/<name> inside the container
|
||||||
|
# • Optionally mount a customised config.py to override defaults at build
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
volumes:
|
||||||
|
- /mnt/secret-items/sd-outputs/Sorted/Images/Portrait:/media/Portrait:ro
|
||||||
|
- /mnt/secret-items/sd-outputs/Sorted/Images/Landscape:/media/Landscape:ro
|
||||||
|
# Host data directory → container /data (holds image_selections.db)
|
||||||
|
- ./data:/data
|
||||||
|
# Uncomment the line below if you maintain a custom config.py alongside
|
||||||
|
# the compose file and want to override the image copy at runtime.
|
||||||
|
- ./config.py:/app/config.py:ro
|
||||||
Binary file not shown.
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Python dependencies for SWIPER
|
||||||
|
tqdm==4.66.4
|
||||||
|
Pillow==10.3.0
|
||||||
Reference in New Issue
Block a user