-
Notifications
You must be signed in to change notification settings - Fork 1k
/
python.html.markerb
338 lines (248 loc) · 11.9 KB
/
python.html.markerb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
---
title: "Run a Python App"
layout: language-and-framework-docs
sitemap: false
redirect_from: /docs/getting-started/python/
---
<%= partial "partials/intro", locals: { runtime: "Python" } %>
- [Run a Flask App](#run-a-flask-app)
## Initial Local Setup
Make sure that [Python](https://www.python.org/) is already installed on your computer along with a way to create virtual environments.
This allows you to run your project locally, and test that it works, before deploying it to Fly.io.
<section class="callout">
We recommend the latest [supported versions](https://devguide.python.org/versions/#supported-versions) of Python.
</section>
### Virtual Environment
For this guide, we use [venv](https://docs.python.org/3/library/venv.html#module-venv) but any of the other popular choices such as [Poetry](https://python-poetry.org/), [Pipenv](https://github.com/pypa/pipenv), or [pyenv](https://github.com/pyenv/pyenv) work too.
```shell
# Unix/macOS
$ mkdir hello-flask
$ cd hello-flask
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $
```
```shell
# Windows
> mkdir hello-flask
> cd hello-flask
> python -m venv .venv
> .venv\Scripts\activate
(.venv) $
```
<section class="callout">From this point on, the commands won't be displayed with (.venv) $ but we assume you have your Python virtual environment activated.</section>
## Run a Flask App
In this guide we recreate and deploy this [minimal Flask application](https://github.com/fly-apps/hello-flask) to demonstrate how quickly Flask apps can be deployed to Fly.io!
<section class="callout">
You can follow the guide to recreate the app or just `git clone https://github.com/fly-apps/hello-flask` to get a local copy.
</section>
We assume you already have [Python installed](#initial-local-setup) and your [virtual environment is activated](#virtual-environment).
### Install Flask
With your virtual environment **activated**, install the [latest](https://flask.palletsprojects.com/en/latest/) version of Flask using [pip](https://pip.pypa.io/en/stable/):
```cmd
python -m pip install Flask
```
This will load Flask and all its dependency packages. You can check all of the packages with `pip freeze` command:
```cmd
pip freeze
```
```output
blinker==1.6.2
click==8.1.3
Flask==2.3.2
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
Werkzeug==2.3.3
```
<section class="callout">
If you have a local copy of `hello-flask`, you can install all the dependencies using `python -m pip install -r requirements.txt`
</section>
### Create the Flask App
The [`hello-flask`](https://github.com/fly-apps/hello-flask) application is, as you'd expect for an example, very minimal.
Inside the `hello-flask` folder, create an `app.py` file and add the code:
```python
# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
@app.route('/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
```
### Create the Template
Flask is set up to route request to a `hello` function which in turn passes a `name` variable (taken from the requests path) to a function to render the `hello.html` template. Create a directory named `templates/` and inside, create the `hello.html`:
```html
<!-- templates/hello.html -->
<!DOCTYPE html>
<html>
<title>Hello from Fly.io</title>
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}">
<body>
{% if name %}
<h1>Hello, {{ name | capitalize }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}
</body>
</html>
```
We're using a template as it makes it easier to show what you should do with assets that aren't the actual application.
### Start the Development Server
Flask apps are run with the `flask run` command:
```cmd
flask run
```
```out
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
```
or
```cmd
flask --app app run
```
```out
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
```
Note that `flask run` command works since our file is named `app.py`. It also works if your file is named `wsgi.py`, so you don't have to use [`--app`](https://flask.palletsprojects.com/en/latest/cli/) to tell Flask where your app is. More details [here](https://flask.palletsprojects.com/en/latest/quickstart/#a-minimal-application).
If your file is saved as `hello.py` instead of `app.py`, you would need to use the `--app` option to point to Flask where your app is:
```cmd
flask --app hello run
```
```out
* Serving Flask app 'hello'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
```
If you open http://127.0.0.1:5000/ in your web browser and it displays `Hello, World!`.
If you open, for example, http://127.0.0.1:5000/fly , it displays `Hello, Fly!`.
### Before Deployment
A few more steps are necessary before deploying the app.
For production, the web application will be served by [`gunicorn`](https://gunicorn.org/). To install it, run:
```cmd
python -m pip install gunicorn
```
And now, save all the dependencies to a `requirements.txt` file using:
```cmd
pip freeze > requirements.txt
```
Now, let's move on to deploying this app to Fly.io.
### Launch your Fly App
Fly.io has its own command-line utility for managing apps, [flyctl](/docs/hands-on/install-flyctl/).
If not already installed, follow the instructions on the [installation guide](/docs/hands-on/install-flyctl/) and [log in to Fly.io](/docs/getting-started/log-in-to-fly/).
<section class="callout">
Both `flyctl` and `fly` commands will work the same way.
</section>
To configure and launch the app, run `fly launch` and follow the wizard as follow:
```cmd
fly launch
```
```output
Creating app in ../flyio/hello-flask
Scanning source code
Detected a Python app
Using the following build configuration:
Builder: paketobuildpacks/builder:base
? Choose an app name (leave blank to generate one): hello-fly-flask
? Select Organization: Fly.io (fly-io)
Some regions require a paid plan (bom, fra, maa).
See https://fly.io/plans to set up a plan.
? Choose a region for deployment: Amsterdam, Netherlands (ams)
App will use 'ams' region as primary
Created app 'hello-fly-flask' in organization 'fly-io'
Admin URL: https://fly.io/apps/hello-fly-flask
Hostname: hello-fly-flask.fly.dev
? Would you like to set up a Postgresql database now? No
? Would you like to set up an Upstash Redis database now? No
Wrote config file fly.toml
Validating ../flyio/hello-flask/fly.toml
Platform: machines
✓ Configuration is valid
We have generated a simple Procfile for you. Modify it to fit your needs and run "fly deploy" to deploy your application.
```
You can set a unique name for the app and choose your primary region. You can also choose to launch and attach a [PostgreSQL database](/docs/postgres/) and/or an [Upstash Redis database](/docs/reference/redis/) though we are not using either in this example.
Organizations are a way of sharing applications between Fly users. When you are asked to select an organization, there should be one with your account name, this is your personal organization. Select that.
One thing to know about the built-in Python builder (`paketobuildpacks/builder:base`) is that it will automatically copy over the contents of the directory to the deployable image. This is how you can move static assets such as templates and other files to your application.
The other thing to know is that it uses a `Procfile` to run the application. `Procfile`s are used on other platforms to deploy Python applications so we keep it simple. The Procfile contains instructions for starting the application. The minimal generated `Procfile` starts the Gunicorn server with our WSGI application:
```Procfile
# Modify this Procfile to fit your needs
web: gunicorn app:app
```
`gunicorn` says that the web component of the application is served by `gunicorn`.
`{module_import}:{app_variable}` as in `app:app` is equivalent to 'from app import app':
- first `app` is the Python module (our `app.py` file)
- second `app` is the Flask object created inside of `app.py` (our `app = Flask(__name__)`)
**Important**: If your Flask object is created, for example, in `hello.py` instead of `app.py`, you should update your `Procfile` like this:
```Procfile
web: gunicorn hello:app
```
### Inside `fly.toml`
The `fly.toml` file now contains a default configuration for deploying your app. In the process of creating that file, `flyctl` has also created a Fly-side application slot by the name, `hello-fly-flask`. If we check the `fly.toml` file we can verify the name in there:
```toml
# fly.toml app configuration file generated for hello-fly-flask on 2023-06-12T17:22:20+02:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "hello-fly-flask"
primary_region = "ams"
[build]
builder = "paketobuildpacks/builder:base"
[env]
PORT = "8080"
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
```
The `fly` command will always refer to this file in the current directory if it exists, specifically for the `app` name/value at the start. That name will be used to identify the application to the Fly service. The rest of the file contains settings to be applied to the application when it deploys:
- `primary_region`: it configures where the primary region is, used to create new Machines;
- `internal_port`: it configures which port the application will use to communicate with clients;
- `force_https = true`: it enforces HTTP to HTTPS redirects;
- `auto_start_machines = true`: it enables starting Machines automatically based on requests and capacity;
- `auto_stop_machines = true`: it enables stopping Machines automatically when the app is idle for several minutes;
- `min_machines_running = 0`: it sets the number of Machines to keep running, in the primary region only, when `auto_stop_machines = true`.
### Deploy to Fly.io
We are now ready to deploy our app to Fly.io. At the command line, run:
```cmd
fly deploy
```
This will lookup our `fly.toml` file, and get the app name `hello-fly-flask` from there. Then `flyctl` will start the process of deploying our application to Fly.io. `flyctl` will return you to the command line when it's done.
Once complete, visit your app with the following command:
```cmd
fly apps open
```
### View the Deployed App
Now the application has been deployed, let's find out more about its deployment. The command `fly status` will give you all the essential details.
```cmd
fly status
```
```output
App
Name = hello-fly-flask
Owner = fly-io
Hostname = hello-fly-flask.fly.dev
Image = hello-fly-flask:deployment-01H2R4E4ABT72E5FVVMP0C0588
Platform = machines
Machines
PROCESS ID VERSION REGION STATE CHECKS LAST UPDATED
app 1781903a919e98 1 ams started 2023-08-31T03:50:27Z
app e28673dfd42186 1 ams started 2023-08-29T14:14:34Z
```
The application has been assigned with a DNS hostname of `hello-fly-flask.fly.dev`, and two instances are running in Amsterdam. Your deployment's name will, of course, be different.
### Connecting to the App
The quickest way to connect to your deployed app is with the `fly apps open` command. This will open a browser on the HTTP version of the site. That will automatically be upgraded to an HTTPS secured connection (for the fly.dev domain).
To specify a path, add `/name` to `fly apps open` and it'll be appended to the URL as the path and you'll get an extra greeting from the `hello-fly-flask` app:
```cmd
fly apps open /fly
```
Congrats! You have successfully built, deployed, and connected to your first Flask application on Fly.io.