diff --git a/Dockerfile b/Dockerfile index 32a4867..595297a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,4 +57,16 @@ EXPOSE 5000 # Wait for the database, run migrations, then serve. The DB wait keeps a briefly # slow/unready database from crash-looping the container. Family convention # (rule 82): schema is built by real migrations, never metadata.create_all. -CMD ["sh", "-c", "python -m inkwell.dbwait && alembic upgrade head && hypercorn 'inkwell.app:create_app()' --bind 0.0.0.0:5000 --keep-alive 600"] +# +# Timeouts (family idea #5105, practice 9; read from hypercorn 0.18's source): +# - `--keep-alive 120` is the idle timeout. It is also the header timeout: +# hypercorn marks a connection busy only once a whole request has arrived, so a +# client dribbling headers is still "idle" and is cut off at this. It was 600, +# ten minutes per held connection. 120 stays above Traefik's 90s idle timeout +# for backend connections, so the proxy never reuses one this server has just +# closed (a 502). +# - No `--read-timeout`, on purpose. It bounds every socket read, including the +# whole time a download is streaming and the client sends nothing, so it would +# cut off an APK fetched slowly over mobile data. Bodies are capped instead +# (MAX_CONTENT_LENGTH in app.py). +CMD ["sh", "-c", "python -m inkwell.dbwait && alembic upgrade head && hypercorn 'inkwell.app:create_app()' --bind 0.0.0.0:5000 --keep-alive 120"]