Thanks for the Python demo app! I enjoyed deploying it, and Fly.io seems like a fantastic platform.
I would love to see the Python builder support Poetry. Poetry is a tool for Python dependency management and packaging. I’ve been working with Poetry for some time now, with and without Docker, in a variety of personal and enterprise projects. It has a number of compelling benefits, including:
-
Automatic virtual environment management: Poetry automatically manages the
virtualenv
for the application.
-
Automatic dependency management: rather than having to run
pip freeze > requirements.txt
, Poetry automatically manages a configuration file called pyproject.toml, which enables SemVer-level control over dependencies and can be used by other Python tools. Poetry also manages a lockfile called poetry.lock to automatically track specific versions and hashes for every dependency.
-
Dependency resolution: Poetry will automatically resolve any dependency version conflicts.
-
Dependency separation: Poetry can maintain separate lists of dependencies for development and production in the pyproject.toml. Production installs can skip development dependencies to speed up Docker builds.
-
Builds: Poetry has features for easily building the project into a Python package.
If you’re open to supporting Poetry, I would be happy to get you a GitHub PR to update the demo app correspondingly.
To start, the directories would be restructured to support proper Python packaging, without disrupting the pre-existing commands:
~/path/to/fly-apps/python-hellofly-flask
❯ git mv hellofly.py hellofly/__init__.py
~/path/to/fly-apps/python-hellofly-flask
❯ git mv templates hellofly/templates
~/path/to/fly-apps/python-hellofly-flask
❯ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: hellofly.py -> hellofly/__init__.py
renamed: templates/hello.html -> hellofly/templates/hello.html
~/path/to/fly-apps/python-hellofly-flask
❯ git commit -m "Restructure project to support Python packaging"
The requirements.txt would be refactored into a pyproject.toml configuration file like this:
# pyproject.toml
[tool.poetry]
name = "hellofly"
version = "0.0.1"
authors = ["Fly <support@fly.io>"]
description = "Fly.io configuration within pyproject.toml."
homepage = "https://github.com/fly-apps/python-hellofly-flask"
[tool.poetry.dependencies]
python = "^3.9"
click = "^7"
flask = "^1"
gunicorn = "^20"
itsdangerous = "^1"
jinja2 = "^2"
markupsafe = "^1"
werkzeug = "^1"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
After running a poetry install
, the changes would look like this:
~/path/to/fly-apps/python-hellofly-flask
❯ git rm requirements.txt
~/path/to/fly-apps/python-hellofly-flask
❯ git add --all
~/path/to/fly-apps/python-hellofly-flask
❯ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: poetry.lock
new file: pyproject.toml
deleted: requirements.txt
The builder could check the project directory for a pyproject.toml and run Poetry if one is found. See heroku/heroku-buildpack-python#796 for some related discussion of how this might look on Heroku. Heroku hasn’t implemented Poetry support yet, as far as I know, so this could give you an edge over Heroku.
I could think of some interesting future directions for this. You’re already using TOML for configuration, so the Fly.io configuration could even be added directly to pyproject.toml (flyproject.toml?). For Python projects, this could obviate the need for both the Procfile and the fly.toml.
# pyproject.toml
[tool.fly]
app = "hellofly-python"
[tool.fly.build]
builtin = "python"
[tool.fly.run]
web = "gunicorn hellofly:app"
[tool.fly.services]
http_checks = []
internal_port = 8080
protocol = "tcp"
script_checks = []
[tool.poetry]
name = "hellofly"
version = "0.0.1"
authors = ["Fly <support@fly.io>"]
description = "Fly.io configuration within pyproject.toml."
homepage = "https://github.com/fly-apps/python-hellofly-flask"
[tool.poetry.dependencies]
python = "^3.9"
click = "^7"
flask = "^1"
gunicorn = "^20"
itsdangerous = "^1"
jinja2 = "^2"
markupsafe = "^1"
werkzeug = "^1"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
In the meantime, I can continue configuring Poetry through Docker. Thanks for your consideration, and keep up the good work.