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).
|
||||
# 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
|
||||
COPY app ./app
|
||||
|
||||
# `docker compose run --rm test`
|
||||
# `docker compose -f docker-compose.build.yaml run --rm test`
|
||||
FROM base AS test
|
||||
COPY 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.
|
||||
|
||||
## 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
|
||||
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
|
||||
docker compose up -d --build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
docker compose logs -f # follow logs
|
||||
docker compose down # stop
|
||||
docker compose up -d --build # rebuild after pulling changes
|
||||
docker compose logs -f # follow logs
|
||||
docker compose down # stop
|
||||
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)
|
||||
```
|
||||
|
||||
### 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)
|
||||
|
||||
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
|
||||
|
||||
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`.
|
||||
2. `docker compose up -d --build`. The app listens on `127.0.0.1:${PORT}`.
|
||||
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`. The app listens on `127.0.0.1:${PORT}`.
|
||||
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/db.py SQLite schema and setup
|
||||
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
|
||||
```
|
||||
|
||||
@@ -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:
|
||||
whattodo:
|
||||
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