Deploy by framework

Python (FastAPI and Flask)

Deploy FastAPI or Flask with a managed Python container and optional CDN assets.

Nitroship detects fastapi or flask in requirements.txt, pyproject.toml, or Pipfile. FastAPI is preferred when both are declared. Django has its own managed preset.

Deploy

Install the CLI

curl -fsSL https://nitroship.co/install.sh | bash
ntro login

Already installed? Skip ahead. Full options, PATH setup, and updates: Install the CLI.

Choose the preset and a compute region in the deployment root. Regions have no default. Use flask instead of fastapi for a Flask app.

nitroship.json
{
  "build": {"framework": "fastapi"},
  "compute": {"regions": ["kr-icn"]}
}
ntro apps create my-python-app
ntro deploy . --prod

Python container presets require the hosted builder. Remove --local if you previously used it. After deploying, open an API route and, if present, a public asset at the URL printed by the CLI.

Dependencies and Python version

The build chooses dependency setup in this order:

  1. uv when uv.lock is present.
  2. Poetry when poetry.lock or [tool.poetry] is present.
  3. Pipenv when Pipfile or Pipfile.lock is present.
  4. pip with requirements.txt.
  5. pip with dependencies declared in the [project] section of pyproject.toml.

Commit the manifest and lockfile for the manager you use. Python version selection reads .python-version, then pyproject.toml's requires-python, then .tool-versions. Explicit version files map to the nearest pinned supported version. A requires-python range must admit a supported pinned interpreter; incompatible bounds fail the build plan rather than silently selecting an unsupported version. Without a declaration, the builder uses a stable default.

Entrypoint and assets

For FastAPI, the preset finds a FastAPI application assignment in main.py, app.py, or app/main.py and starts its module with Uvicorn. For Flask, it looks in main.py, app.py, and wsgi.py, then other Python modules, for a Flask instance or a create_app factory, and starts it with Gunicorn. Both servers listen on 0.0.0.0:$PORT; the default port is 3000. A different app factory, nested layout, or custom startup command needs your own Dockerfile rather than guessing an entrypoint.

When public/ exists, its public assets are staged under /nitroship/static and automatically extracted to the CDN root before the runtime starts. public/logo.svg is served at /logo.svg. Keep server source and secrets out of this folder. If there is no public/, this preset produces no static CDN files; API responses and application-served assets still go to compute. It does not automatically discover arbitrary FastAPI StaticFiles mounts or Flask's static/ URL mappings.

Environment and persistence

Set API keys, app configuration, and database connection values through Environment variables. DATABASE_URL is useful only when your application reads it. Use an external database, not a local SQLite file for durable data. For Flask, configure a production secret key if you use sessions; do not enable the development debugger in production.

Generated images use a pinned Python base and run as a non-root user. The instance filesystem is ephemeral; use /tmp for temporary writes, not durable data. Store uploads in S3 or other object storage rather than writing them into the application directory.

Nitroship does not automatically run migrations, queue workers, or schedulers. Run your project's migration command, such as alembic upgrade head or flask db upgrade, in CI or locally against the external database. Run workers separately. Use Cron jobs for scheduled HTTP work instead of an in-process scheduler.

Framework selection and Dockerfile escape hatch

build.framework: "fastapi" or "flask" selects that preset explicitly and overrides an automatically found Dockerfile. build.framework cannot coexist with build.dockerfile.

Without an explicit framework, Nitroship detects the build as described in How Nitroship chooses a build. For extra OS packages, other Python servers, or a custom module/asset layout, remove build.framework and use your own Dockerfile.

On this page