diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a9f05c6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +.dockerignore +.gitignore +.env +docker-compose.yml +Dockerfile +env/ +venv/ + +cache/ +/web/static/ +/web/media/ +*credentials* + +.idea/ +*.iml + +__pycache__/ +*.pyc + +data/ \ No newline at end of file diff --git a/.github/workflows/build-and-publish.yaml b/.github/workflows/build-and-publish.yaml new file mode 100644 index 0000000..ec5cdac --- /dev/null +++ b/.github/workflows/build-and-publish.yaml @@ -0,0 +1,52 @@ +name: build & publish Docker image + +on: + push: + branches: + # TODO: rename master to main + - master + # TODO: remove before merge + - docker + +jobs: + build-publish: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: set up Docker buildx + uses: docker/setup-buildx-action@v2 + + - name: log into the GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: lowercase repo name + id: lower-repo + uses: ASzc/change-string-case-action@v6 + with: + string: ${{ github.repository }} + + - name: set current date as env variable + id: version + run: | + echo "builddate=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + + - name: build and push Docker image + uses: docker/build-push-action@v4 + with: + file: Dockerfile + push: true + tags: | + ghcr.io/${{ steps.lower-repo.outputs.lowercase }}:latest,ghcr.io/${{ steps.lower-repo.outputs.lowercase }}:${{ steps.version.outputs.builddate }} + platforms: linux/amd64,linux/arm64 + # https://docs.docker.com/build/ci/github-actions/cache/#cache-backend-api + cache-from: type=gha + cache-to: type=gha,mode=max + diff --git a/.gitignore b/.gitignore index 66c044f..45e9a25 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ cache/ __pycache__/ *.pyc + +data/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c33dcc1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +FROM ghcr.io/osgeo/gdal:alpine-small-3.9.2 AS builder +LABEL maintainer="Holger Bruch " + +RUN apk add --no-cache build-base python3-dev py3-pip postgresql-client libpq-dev geos-dev + + +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +WORKDIR /app +COPY requirements.txt . +COPY web/scrapers/ParkAPI2_sources/requirements.txt ./ParkAPI2_sources_requirements.txt + +RUN pip install -r requirements.txt -r ParkAPI2_sources_requirements.txt + +# Operational stage +FROM ghcr.io/osgeo/gdal:alpine-small-3.9.2 +LABEL maintainer="Holger Bruch " + +RUN apk add --no-cache bash git python3 py3-pip postgresql-client geos + +COPY --from=builder /opt/venv /opt/venv +ENV RUN_MIGRATION=0 \ + CREATE_SUPERUSER=0 \ + ASSIGN_LOCATIONS=0 \ + PYTHONBUFFERED=1 \ + PATH="/opt/venv/bin:$PATH" + +WORKDIR /app +COPY . /app/ + +EXPOSE 8000 +ENTRYPOINT ["/bin/bash", "/app/entrypoint.sh"] +CMD runserver 0.0.0.0:8000 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..504b80c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,45 @@ +version: '3' +services: + db: + image: postgis/postgis:16-3.4 + volumes: + - ./data:/var/lib/postgresql/data + env_file: .env + ports: + - 5432:5432 + healthcheck: + test: ["CMD-SHELL", "pg_isready -U parkapi2"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + api: + build: + context: . + dockerfile: ./Dockerfile + command: ["runserver", "0.0.0.0:8000"] + depends_on: + db: + condition: service_healthy + expose: + - 8000 + ports: + - 8000:8000 + env_file: .env + environment: + - RUN_MIGRATION=1 + - ASSIGN_LOCATIONS=1 + + scraper: + build: + context: . + dockerfile: ./Dockerfile + command: + - pa_scrape + - scrape + - -j + - "100" + depends_on: + db: + condition: service_healthy + env_file: .env diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..b44794f --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -euo pipefail + +cd web +if [ "$RUN_MIGRATION" -eq "1" ]; then + echo "RUN MIGRATION is TRUE" +fi + +# Run migration only if explicitly set via ENV +if [ "$RUN_MIGRATION" -eq "1" ]; then + ./manage.py migrate +fi + +if [ "$ASSIGN_LOCATIONS" -eq "1" ]; then + ./manage.py pa_find_locations +fi + +# don't create an admin interface per default +if [ "$CREATE_SUPERUSER" -eq "1" ]; then + ./manage.py createsuperuser +fi + +# start the server +./manage.py $@ diff --git a/web/scrapers/ParkAPI2_sources b/web/scrapers/ParkAPI2_sources index 119f7a1..0dd2e2c 160000 --- a/web/scrapers/ParkAPI2_sources +++ b/web/scrapers/ParkAPI2_sources @@ -1 +1 @@ -Subproject commit 119f7a11d75ddce0ff6621b6b28a07964666ddfe +Subproject commit 0dd2e2c84f80b1268a846037543d3d2965efc09d