You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
***`python3.6`** tag: general Flask web application, structured as a package, for bigger Flask projects, with different submodules. Use it only as an example of how to import your modules and how to structure your own project:
***`python3.6-index`** tag: `static/index.html` served directly in `/`, e.g. for Angular, React, or any other Single-Page Application that uses a static `index.html`, not modified by Python:
@@ -55,7 +59,7 @@ There are several image tags available for Python 3.6, Python 3.5 and Python 2.7
55
59
56
60
As of now, [everyone](https://www.python.org/dev/peps/pep-0373/)[should be](http://flask.pocoo.org/docs/0.12/python3/#python3-support)[using **Python 3**](https://docs.djangoproject.com/en/1.11/faq/install/#what-python-version-should-i-use-with-django).
57
61
58
-
There are two template projects that you can download (as a `.zip` file) to bootstrap your project in the section "**Examples (project templates)**" above.
62
+
There are several template projects that you can download (as a `.zip` file) to bootstrap your project in the section "**Examples (project templates)**" above.
59
63
60
64
This Docker image is based on [**tiangolo/uwsgi-nginx**](https://hub.docker.com/r/tiangolo/uwsgi-nginx/). That Docker image has uWSGI and Nginx installed in the same container and was made to be the base of this image.
**Note**: As your `index.html` file will be served from `/` and from `/static/index.html`, it would be better to have absolute paths in the links to other files in the `static` directory from your `index.html` file. As in `/static/css/styles.css` instead of relative paths as in `./css/styles.css`. But still, above you added code in your `main.py` to handle that too, just in case.
230
236
237
+
## QuickStart for bigger projects structured as a Python package
238
+
239
+
**Note**: You can download the **example-flask-package-python3.6.zip** project example and use it as an example or template for your project from the section **Examples** above.
240
+
241
+
---
242
+
243
+
You should be able to follow the same instructions as in the "**QuickStart**" section above, with some minor modifications:
244
+
245
+
* Instead of putting your code in the `app/` directory, put it in a directory `app/main/`.
246
+
* Add a file `__init__.py` inside of that `app/main/` directory.
247
+
248
+
Your file structure would look like:
249
+
250
+
```
251
+
.
252
+
├── app
253
+
│ ├── main
254
+
│ │ ├── __init__.py
255
+
│ │ ├── main.py
256
+
└── Dockerfile
257
+
```
258
+
259
+
...instead of:
260
+
261
+
```
262
+
.
263
+
├── app
264
+
│ ├── main.py
265
+
└── Dockerfile
266
+
```
267
+
268
+
* In the file `app/main/__init__.py` put:
269
+
270
+
```python
271
+
from .main import app
272
+
```
273
+
274
+
...after that, everything should work as expected. All the other instructions would apply normally.
275
+
276
+
### Working with submodules
277
+
278
+
* After adding all your modules you could end up with a file structure similar to (taken from the example project):
279
+
280
+
```
281
+
.
282
+
├── app
283
+
│ ├── main
284
+
│ │ ├── api
285
+
│ │ │ ├── api.py
286
+
│ │ │ ├── endpoints
287
+
│ │ │ │ ├── __init__.py
288
+
│ │ │ │ └── user.py
289
+
│ │ │ ├── __init__.py
290
+
│ │ │ └── utils.py
291
+
│ │ ├── core
292
+
│ │ │ ├── app_setup.py
293
+
│ │ │ ├── database.py
294
+
│ │ │ └── __init__.py
295
+
│ │ ├── __init__.py
296
+
│ │ ├── main.py
297
+
│ │ └── models
298
+
│ │ ├── __init__.py
299
+
│ │ └── user.py
300
+
└── Dockerfile
301
+
```
302
+
303
+
* Make sure you follow [the offical docs while importing your modules](https://docs.python.org/3/tutorial/modules.html#intra-package-references):
304
+
305
+
* For example, if you are in `app/main/main.py` and want to import the module in `app/main/core/app_setup.py` you would wirte it like:
306
+
307
+
```python
308
+
from .core import app_setup
309
+
```
310
+
311
+
* And if you are in `app/main/api/endpoints/user.py` and you want to import the `users` object from `app/main/core/database.py` you would write it like:
312
+
313
+
```python
314
+
from ...core.database import users
315
+
```
231
316
232
317
## Advanced instructions
233
318
@@ -416,34 +501,39 @@ If you go to your Docker container URL you should see your app, and you should b
416
501
417
502
...but, as uWSGI loads your whole Python Flask web application once it starts, you won't be able to edit your Python Flask code and see the changes reflected.
418
503
419
-
To be able to (temporarily) debug your Python Flask code live, you can run your container overriding the default command (that starts Supervisord which in turn starts uWSGI and Nginx) and run your application directly with `python`, in debug mode.
504
+
To be able to (temporarily) debug your Python Flask code live, you can run your container overriding the default command (that starts Supervisord which in turn starts uWSGI and Nginx) and run your application directly with `python`, in debug mode, using the `flask` command with its environment variables.
420
505
421
-
So, with all the modifications above and making your app run directly with `python`, the final Docker command would be:
506
+
So, with all the modifications above and making your app run directly with `flask`, the final Docker command would be:
docker run -d --name mycontainer -p 80:80 -v $(pwd)/app:/app -e FLASK_APP=main.py -e FLASK_DEBUG=1 myimage flask run --host=0.0.0.0 --port=80
510
+
```
511
+
512
+
Or in the case of a package project, you would set `FLASK_APP=main/main.py`:
513
+
514
+
```bash
515
+
docker run -d --name mycontainer -p 80:80 -v $(pwd)/app:/app -e FLASK_APP=main/main.py -e FLASK_DEBUG=1 myimage flask run --host=0.0.0.0 --port=80
425
516
```
426
517
427
518
Now you can edit your Flask code in your local machine and once you refresh your browser, you will see the changes live.
428
519
429
520
Remember that you should use this only for debugging and development, for deployment in production you shouldn't mount volumes and you should let Supervisord start and let it start uWSGI and Nginx (which is what happens by default).
430
521
431
-
For these last steps to work (live debugging and development), your Python Flask code should have that section with:
522
+
An alternative for these last steps to work when you don't have a package but just a flat structure with single files (modules), your Python Flask code could have that section with:
432
523
433
-
```python
434
-
if__name__=="__main__":
435
-
app.run(host='0.0.0.0', debug=True, port=80)
436
-
```
524
+
```python
525
+
if__name__=="__main__":
526
+
# Only for debugging while developing
527
+
app.run(host='0.0.0.0', debug=True, port=80)
528
+
```
437
529
438
-
otherwise your app will only listen to `localhost` (inside the container), in another port (5000) and not in debug mode.
530
+
...and you could run it with `python main.py`. But that will only work when you are not using a package structure and don't plan to do it later. In that specific case, if you didn't add the code block above, your app would only listen to `localhost` (inside the container), in another port (5000) and not in debug mode.
439
531
440
532
**Note**: The example project **example-flask-python3.6** includes a `docker-compose.yml` and `docker-compose.override.yml` with all these configurations, if you are using Docker Compose.
441
533
442
534
---
443
535
444
-
Also, if you want to do the same live debugging using the tags with `-index` (to serve `/app/static/index.html` directly when requested for `/`) your Nginx won't serve it directly as it won't be running (only your Python Flask app in debug mode will be running).
445
-
446
-
For that, your Python Flask code should have that section with:
536
+
Also, if you want to do the same live debugging using the environment variable `STATIC_INDEX=1` (to serve `/app/static/index.html` directly when requested for `/`) your Nginx won't serve it directly as it won't be running (only your Python Flask app in debug mode will be running).
447
537
448
538
```python
449
539
from flask import Flask, send_file
@@ -457,7 +547,25 @@ def main():
457
547
return send_file('./static/index.html')
458
548
```
459
549
460
-
That makes sure your app also serves the `/app/static/index.html` file when requested for `/`.
550
+
...that makes sure your app also serves the `/app/static/index.html` file when requested for `/`.
551
+
552
+
And if you are using a SPA framework, to allow it to handle the URLs in the browser, your Python Flask code should have the section with:
553
+
554
+
```python
555
+
# Everything not declared before (not a Flask route / API endpoint)...
556
+
@app.route('/<path:path>')
557
+
defroute_frontend(path):
558
+
# ...could be a static file needed by the front end that
559
+
# doesn't use the `static` path (like in `<script src="bundle.js">`)
560
+
file_path ='./static/'+ path
561
+
if os.path.isfile(file_path):
562
+
return send_file(file_path)
563
+
# ...or should be handled by the SPA's "router" in front end
564
+
else:
565
+
return send_file('./static/index.html')
566
+
```
567
+
568
+
...that makes Flask send all the CSS, JavaScript and image files when requested in the root (`/`) URL but also makes sure that your front end SPA handles all the other URLs that are not defined in your Flask app.
461
569
462
570
That's how it is written in the tutorial above and is included in the downloadable examples.
463
571
@@ -471,12 +579,18 @@ And since the only process running was your debugging server, that now is stoppe
471
579
472
580
Then you will have to start your container again after fixing your code and you won't see very easily what is the error that is crashing your server.
473
581
474
-
So, while developing, you could do the following (that's what I normally do):
582
+
So, while developing, you could do the following (that's what I normally do, although I do it with Docker Compose, as in the example projects):
475
583
476
584
* Make your container run and keep it alive in an infinite loop (without running any server):
477
585
478
586
```bash
479
-
docker run -d --name mycontainer -p 80:80 -v $(pwd)/app:/app myimage bash -c "while true ; do sleep 10 ; done"
* Connect to your container with a new interactive session:
@@ -490,13 +604,18 @@ You will now be inside your container in the `/app` directory.
490
604
* Now, from inside the container, run your Flask debugging server:
491
605
492
606
```bash
493
-
python main.py
607
+
flask run --host=0.0.0.0 --port=80
494
608
```
495
609
496
610
You will see your Flask debugging server start, you will see how it sends responses to every request, you will see the errors thrown when you break your code and how they stop your server and you will be able to re-start your server very fast, by just running the command above again.
497
611
498
612
## What's new
499
613
614
+
2017-09-02:
615
+
616
+
* Example project with a [Python package](https://docs.python.org/3/tutorial/modules.html#packages) structure and a section explaining how to use it and structure a Flask project like that.
617
+
* Also, the examples and documentation now use the [`flask run`](http://flask.pocoo.org/docs/0.12/quickstart/#a-minimal-application) commands, that allows running a package application while developing more easily.
618
+
500
619
2017-08-10: Many changes:
501
620
502
621
* New official image tags: `python3.6`, `python3.6-index`, `python.3.5`, `python3.5-index`, `python2.7` and `python2.7-index`. All the other images are deprecated in favor is this ones.
0 commit comments