Run from a published image; move source build to docker-compose.build.yaml
docker-compose.yaml now pulls git.goyban.com/goyban/whattodo so it can be used without the source. publish.sh builds the committed version and pushes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,3 +18,6 @@ BIND_ADDR=127.0.0.1
|
|||||||
|
|
||||||
# Behind a reverse proxy, the IPs allowed to set X-Forwarded-For (for login rate limiting).
|
# Behind a reverse proxy, the IPs allowed to set X-Forwarded-For (for login rate limiting).
|
||||||
# FORWARDED_ALLOW_IPS=127.0.0.1
|
# FORWARDED_ALLOW_IPS=127.0.0.1
|
||||||
|
|
||||||
|
# Development only: build from source instead of pulling the published image.
|
||||||
|
# COMPOSE_FILE=docker-compose.build.yaml
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ COPY requirements.txt .
|
|||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
COPY app ./app
|
COPY app ./app
|
||||||
|
|
||||||
# `docker compose run --rm test`
|
# `docker compose -f docker-compose.build.yaml run --rm test`
|
||||||
FROM base AS test
|
FROM base AS test
|
||||||
COPY requirements-dev.txt .
|
COPY requirements-dev.txt .
|
||||||
RUN pip install -r requirements-dev.txt
|
RUN pip install -r requirements-dev.txt
|
||||||
|
|||||||
@@ -16,28 +16,50 @@ A small, self-hosted to-do app for one person. It works in a desktop browser and
|
|||||||
|
|
||||||
Stack: Python (FastAPI) + SQLite with a plain HTML/CSS/JS frontend and no build step. Everything runs in Docker.
|
Stack: Python (FastAPI) + SQLite with a plain HTML/CSS/JS frontend and no build step. Everything runs in Docker.
|
||||||
|
|
||||||
## Run locally
|
## Run
|
||||||
|
|
||||||
Requirements: Docker with the Compose plugin. Nothing else is installed on the host.
|
Requirements: Docker with the Compose plugin. You don't need the source code: only `docker-compose.yaml` and a `.env`.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
mkdir whattodo && cd whattodo
|
||||||
|
# copy docker-compose.yaml and .env.example from this repo into this folder
|
||||||
cp .env.example .env # then edit .env: set APP_PASSWORD and SECRET_KEY
|
cp .env.example .env # then edit .env: set APP_PASSWORD and SECRET_KEY
|
||||||
docker compose up -d --build
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Open <http://localhost:8080> and log in with `APP_PASSWORD`.
|
Open <http://localhost:8080> and log in with `APP_PASSWORD`.
|
||||||
|
|
||||||
The database lives in `./data/whattodo.db`, which is git-ignored.
|
The database lives in `./data/whattodo.db`.
|
||||||
|
|
||||||
Useful commands:
|
Useful commands:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker compose logs -f # follow logs
|
docker compose logs -f # follow logs
|
||||||
docker compose down # stop
|
docker compose down # stop
|
||||||
docker compose up -d --build # rebuild after pulling changes
|
docker compose pull && docker compose up -d # update to the newest published version
|
||||||
|
```
|
||||||
|
|
||||||
|
To pin a version, set `WHATTODO_TAG=<commit>` in `.env` (default: `latest`).
|
||||||
|
|
||||||
|
## Develop (build from source)
|
||||||
|
|
||||||
|
`docker-compose.build.yaml` builds the image from this checkout. Add this line to your `.env` so plain `docker compose` uses it:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
COMPOSE_FILE=docker-compose.build.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose up -d --build # build and start
|
||||||
docker compose run --rm test # run the test suite (in Docker)
|
docker compose run --rm test # run the test suite (in Docker)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Publishing the image
|
||||||
|
|
||||||
|
`./publish.sh` builds the last commit (uncommitted changes are left out) and pushes it to
|
||||||
|
`git.goyban.com/goyban/whattodo` as `:latest` and `:<commit>`. `./publish.sh <tag|branch|commit>` publishes another version.
|
||||||
|
Log in once first with `docker login git.goyban.com`, using a Gitea token with package write access as the password.
|
||||||
|
|
||||||
### Testing on your phone (same Wi-Fi)
|
### Testing on your phone (same Wi-Fi)
|
||||||
|
|
||||||
Set `BIND_ADDR=0.0.0.0` in `.env`, run `docker compose up -d`, then open `http://<this-computer's-LAN-IP>:8080` on the phone.
|
Set `BIND_ADDR=0.0.0.0` in `.env`, run `docker compose up -d`, then open `http://<this-computer's-LAN-IP>:8080` on the phone.
|
||||||
@@ -45,8 +67,8 @@ Browsers only allow "Install app" / "Add to Home Screen" with offline support ov
|
|||||||
|
|
||||||
## Deploy to production
|
## Deploy to production
|
||||||
|
|
||||||
1. On the server, clone the repo and create `.env` from `.env.example`. Use a **new strong** `APP_PASSWORD` and `SECRET_KEY`, and set `COOKIE_SECURE=true`.
|
1. On the server, put `docker-compose.yaml` in a folder and create `.env` from `.env.example`. Use a **new strong** `APP_PASSWORD` and `SECRET_KEY`, and set `COOKIE_SECURE=true`.
|
||||||
2. `docker compose up -d --build`. The app listens on `127.0.0.1:${PORT}`.
|
2. `docker compose up -d`. The app listens on `127.0.0.1:${PORT}`.
|
||||||
3. Put it behind a reverse proxy with HTTPS. For example, with Caddy:
|
3. Put it behind a reverse proxy with HTTPS. For example, with Caddy:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -83,6 +105,6 @@ Export regularly from Settings, or copy `./data/whattodo.db` while the app is st
|
|||||||
app/main.py API: auth, tasks, categories, export/import
|
app/main.py API: auth, tasks, categories, export/import
|
||||||
app/db.py SQLite schema and setup
|
app/db.py SQLite schema and setup
|
||||||
app/static/ frontend (index.html, app.js, style.css, PWA files, icons)
|
app/static/ frontend (index.html, app.js, style.css, PWA files, icons)
|
||||||
tests/ API tests (run with: docker compose run --rm test)
|
tests/ API tests (run with: docker compose -f docker-compose.build.yaml run --rm test)
|
||||||
tools/make_icons.py regenerates the PNG icons
|
tools/make_icons.py regenerates the PNG icons
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Builds the image from source (development). Used instead of docker-compose.yaml when
|
||||||
|
# COMPOSE_FILE=docker-compose.build.yaml is set in .env, or with -f docker-compose.build.yaml.
|
||||||
services:
|
services:
|
||||||
whattodo:
|
whattodo:
|
||||||
build:
|
build:
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Runs the published image; no source code needed. Put this file and a .env (from .env.example) in a folder, then:
|
||||||
|
# docker compose up -d
|
||||||
|
# Update to the newest published version:
|
||||||
|
# docker compose pull && docker compose up -d
|
||||||
|
# To build from source instead, use docker-compose.build.yaml.
|
||||||
|
services:
|
||||||
|
whattodo:
|
||||||
|
image: git.goyban.com/goyban/whattodo:${WHATTODO_TAG:-latest}
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .env
|
||||||
|
ports:
|
||||||
|
# BIND_ADDR=127.0.0.1 -> this computer only; 0.0.0.0 -> also reachable from your phone on the LAN.
|
||||||
|
- "${BIND_ADDR:-127.0.0.1}:${PORT:-8080}:8000"
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/api/health')"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
Executable
+23
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build the app image from a committed version and push it to the Gitea registry.
|
||||||
|
# Only committed files are used (via `git archive`), so uncommitted work never ends up in the image.
|
||||||
|
#
|
||||||
|
# ./publish.sh # builds HEAD
|
||||||
|
# ./publish.sh v1.2 # builds a tag/branch/commit
|
||||||
|
#
|
||||||
|
# One-time setup: docker login git.goyban.com (password = a Gitea token with package write access)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REGISTRY=git.goyban.com
|
||||||
|
IMAGE="$REGISTRY/goyban/whattodo"
|
||||||
|
REF="${1:-HEAD}"
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
SHA="$(git rev-parse --short "$REF^{commit}")"
|
||||||
|
|
||||||
|
echo "Building $IMAGE from $REF ($SHA)"
|
||||||
|
git archive --format=tar "$REF" | docker build --target runtime -t "$IMAGE:$SHA" -t "$IMAGE:latest" -
|
||||||
|
|
||||||
|
docker push "$IMAGE:$SHA"
|
||||||
|
docker push "$IMAGE:latest"
|
||||||
|
echo "Pushed $IMAGE:$SHA and $IMAGE:latest"
|
||||||
Reference in New Issue
Block a user