diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0d05604 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +jobs/ +www/ +*.img +*.osm +__pycache__/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bd2c394 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +FROM php:8.4-cli-alpine + +ARG MKGMAP_VERSION=r4924 + +# System dependencies (Alpine) +RUN apk add --no-cache \ + openjdk21-jre-headless \ + py3-shapely \ + python3 \ + unzip \ + wget + +# Directory structure that matches the relative paths in the Python scripts: +# script_dir = /srv/src/missing_squadrats/ +# script_dir + ../../jobs/... = /srv/jobs/missing_squadrats/ +# script_dir + ../../www/... = /srv/www/missing_squadrats/ +# Path(__file__).parent^3 / YYYYMMDD = /srv/YYYYMMDD/ (temp build dir) +# logFilePath = /home/users/oranta/ (hardcoded) +RUN mkdir -p \ + /srv/src/ext \ + /srv/src/missing_squadrats \ + /srv/jobs/missing_squadrats \ + /srv/www/missing_squadrats/img \ + /home/users/oranta/python3/venv/bin \ + /var/www/10/oranta/sites/oranta.kapsi.fi + +# Download mkgmap and symlink to the version hardcoded in missing_squadrats.py +RUN wget -q "https://www.mkgmap.org.uk/download/mkgmap-${MKGMAP_VERSION}.zip" \ + && unzip -q "mkgmap-${MKGMAP_VERSION}.zip" -d /srv/src/ext/ \ + && rm "mkgmap-${MKGMAP_VERSION}.zip" \ + && ln -s "/srv/src/ext/mkgmap-${MKGMAP_VERSION}" /srv/src/ext/mkgmap-r4916 + +# Symlinks for the two hardcoded absolute paths in the Python scripts +RUN ln -s /srv/jobs /var/www/10/oranta/sites/oranta.kapsi.fi/jobs \ + && ln -s /usr/bin/python3 /home/users/oranta/python3/venv/bin/python3 + +# Seed mapName.txt so the script has a valid starting map number +RUN echo "2026-01-01 00:00:00,17,0,63040001" > /home/users/oranta/mapName.txt \ + && touch /home/users/oranta/missingSquadrats.log + +EXPOSE 8000 + +COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/README.md b/README.md index abad842..bd5cc9c 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,50 @@ Create a Garmin compatible map image from the [Squadrats.com](http://www.squadrats.com/) kml file. # Getting Started -## Prerequisites -You need a working python installation to run the script. -## Installation +## Docker + +The easiest way to run the project is with Docker. + +### Prerequisites +- [Docker](https://docs.docker.com/get-docker/) with the Compose plugin + +### Run +``` +git clone https://github.com/rankka74/Missing_squadrats.git +cd Missing_squadrats +docker compose up --build +``` + +Open http://localhost:8000 in your browser. + +### How it works inside Docker +- **Web GUI** is served by the PHP built-in server on port 8000. +- Submitting the form uploads the KML file and runs `missing_squadrats.py` synchronously — the page shows "Done!" when the `.img` file is ready. +- Generated `.img` files, the job queue, and the log are stored in named Docker volumes so they survive container restarts. + +### Volumes +| Volume | Contents | +|---|---| +| `img-files` | Generated Garmin `.img` files | +| `job-queue` | Pending and in-progress jobs | +| `oranta-data` | Log file and map-number counter | + +To reset everything: `docker compose down -v` + +--- + +## Manual installation + +### Prerequisites +You need a working Python installation to run the script. + +### Installation 1. Clone the repo ``` git clone https://github.com/rankka74/Missing_squadrats.git ``` -2. Install necessary python libraries eiter system wise or as a virtual environment +2. Install necessary python libraries either system wide or as a virtual environment ``` sys os diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ddd3c13 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +services: + web: + build: . + ports: + - "8000:8000" + volumes: + # Bind-mount source files so changes are live without rebuilding + - ./web-gui:/srv/www/missing_squadrats + - ./missing_squadrats.py:/srv/src/missing_squadrats/missing_squadrats.py + - ./testMissingSquadrats.py:/srv/src/missing_squadrats/testMissingSquadrats.py + - ./mkgmap-config/config.txt:/srv/src/missing_squadrats/config.txt + # Named volumes for generated output and state (persist across restarts) + - img-files:/srv/www/missing_squadrats/img + - job-queue:/srv/jobs/missing_squadrats + - oranta-data:/home/users/oranta + +volumes: + img-files: + job-queue: + oranta-data: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..10c72f7 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e + +# Start PHP built-in server as the web frontend +exec php -S 0.0.0.0:8000 -t /srv/www/missing_squadrats \ + -d upload_max_filesize=64M \ + -d post_max_size=64M diff --git a/web-gui/index.php b/web-gui/index.php index df1b8c3..c9c2960 100644 --- a/web-gui/index.php +++ b/web-gui/index.php @@ -60,7 +60,8 @@ foreach ($imgFiles as $file) { if (is_file($file)) { if ($threshold < filemtime($file)) { - echo "
  • " . str_replace("img/","",$file) . "
    \r\n"; + $href = file_exists('/.dockerenv') ? $file : "https://oranta.kapsi.fi/missing_squadrats/" . $file; + echo "
  • " . str_replace("img/","",$file) . "
    \r\n"; } } } diff --git a/web-gui/upload.php b/web-gui/upload.php index 977302a..4b1849e 100644 --- a/web-gui/upload.php +++ b/web-gui/upload.php @@ -81,6 +81,44 @@ function clean($string) { 'squadratinhosColor' => $squadratinhosColor, ]); file_put_contents($target_dir . $fileName . '.csv', $job); + +// In Docker: spawn Python directly so cron is not needed for local development. +if (file_exists('/.dockerenv')) { + echo "Processing map, please wait...
    \r\n"; + flush(); + + set_time_limit(0); + + $args = [ + '/usr/bin/python3', + '/srv/src/missing_squadrats/missing_squadrats.py', + $fileName . '.kml', + $userName, + (string) $NWlon, + (string) $NWlat, + (string) $SElon, + (string) $SElat, + (string) $squadratinhosLineWeight, + $squadratinhosColor, + ]; + $descriptors = [ + 0 => ['pipe', 'r'], + 1 => ['file', '/home/users/oranta/missingSquadrats.log', 'a'], + 2 => ['file', '/home/users/oranta/missingSquadrats.log', 'a'], + ]; + $proc = proc_open($args, $descriptors, $pipes, '/srv/src/missing_squadrats'); + if (is_resource($proc)) { + fclose($pipes[0]); + $exitCode = proc_close($proc); + if ($exitCode === 0) { + echo "Done! Go back to download your map.
    \r\n"; + } else { + echo "Processing failed (exit code $exitCode). Check the log for details.
    \r\n"; + } + } else { + echo "Failed to start processing.
    \r\n"; + } +} ?>