ใน ep ก่อน เราได้สมัคร Account ของ Heroku เรียบร้อยแล้ว ดังนั้นใน ep นี้เราจะมาสร้าง App ง่าย ๆ ด้วยภาษา Python และ Flask Framework แล้ว Deploy ขึ้นไปยัง Heroku ให้ User สามารถเข้ามาใช้ได้ผ่านทาง Internet
Flask คืออะไร
Flask คือ Framework ที่ใช้ในการสร้าง Web Application ที่รองรับ Web Server Gateway Interface (WSGI) Flask เป็น Framework ที่ออกแบบให้ Lightweight มีขนาดเล็ก ไม่ซับซ้อน มีฟังก์ชันเท่าที่จำเป็นเท่านั้น ถึงขนาดไม่มีฟังก์ชันติดต่อ Database และ Form Validation ที่ Web Application ส่วนใหญ่ต้องใช้ ติดตั้งง่าย Required Library อื่นน้อยมาก
เพื่อให้สามารถเริ่มต้นพัฒนาโปรแกรมได้อย่างรวดเร็ว เริ่มตั้งแต่โค้ดไม่กี่บรรทัดในไฟล์เดียว แต่มีความยืนหยุ่นที่จะ Scale ให้รองรับงานที่ซับซ้อน และผู้ใช้จำนวนมากได้ โดย Flask รองรับการเพิ่มความสามารถอื่น ๆ ผ่านทาง Extension ที่มีให้เลือกจำนวนมากมาย พัฒนาโดยชุมชนขนาดใหญ่ที่มีความ Active
Flask เริ่มต้นจากโปรแกรม Wrapper ง่าย ๆ ที่ห่อ Library 2 ตัว คือ Werkzeug Web Application Library และ Jinja Template Engine และได้พัฒนาต่อมาเรื่อย ๆ จนเป็นหนึ่งใน Web Application Framwork ที่ได้รับความนิยมที่สุดตัวหนึ่ง ของภาษา Python
0. Install Git และ Heroku cli
Install Git ตามลิงค์ด้านล่าง
https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
Install Heroku CLI (Command Line Interface) ตามลิงค์ด้านล่าง
https://devcenter.heroku.com/articles/heroku-cli
1. เตรียม Folder
เราจะสร้าง Folder hello-flask1
เอาไว้ใส่ Source Code ทั้งหมดที่เกี่ยวข้อง ตั้งชื่อว่า hello-flask1 เสร็จแล้ว สั่ง git init เพื่อ Initialize Git ให้ Folder นี้
mkdir hello-flask1
cd hello-flask1/
git init
Output
Initialized empty Git repository in /home/bualabs/projects/hello-flask1/.git/
2. สร้าง App บน Heroku
ก่อนที่จะส่งคำสั่งไปยัง Heroku เราต้อง Login ด้วย Account ที่สมัครไว้ใน ep ก่อน ด้วยคำสั่งด้านล่าง จะเปิดหน้าเว็บให้เรา Login
heroku login
เราสามารถสร้าง App บน Heroku ผ่านทางหน้าเว็บ และ ทาง Command Line
ในเคสนี้ เราจะสร้างทาง Command Line ด้วยคำสั่งด้านล่าง
heroku apps:create hello-flask1
Output
จะเห็นว่ามีการผูก URL และ Git remote ให้โดยอัตโนมัติ
Creating ⬢ hello-flask1… done
https://hello-flask1.herokuapp.com/ | https://git.heroku.com/hello-flask1.git
ดูบนหน้าเว็บ Heroku Dashboard จะพบว่ามี App ชื่อ hello-flask1 ขึ้นมาใหม่
ดู Git Remote จะเห็นว่า Git Remote ถูกผูกกับ Repository บน Heroku โดยอัตโนมัติ
git remote -v
Output
heroku https://git.heroku.com/hello-flask1.git (fetch)
heroku https://git.heroku.com/hello-flask1.git (push)
เช็ค Git Status จะเห็นว่ายังไม่มีการเปลี่ยนแปลงอะไร เพราะเรายังไม่ได้เริ่มต้นเขียนโปรแกรม
git status
Output
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
3. Install Library บนเครื่อง Local
เราจะใช้ venv ช่วยในการจัดการ Environment แล้วจึง Install Library ที่จำเป็น ในเคสนี้คือ flask
เรื่อง venv หรือ Virtual Environment จะอธิบายต่อไป
python3 -m venv venv
. venv/bin/activate
pip install flask
Output
Collecting flask
Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
100% |████████████████████████████████| 102kB 347kB/s
Collecting click>=5.1 (from flask)
.
.
.
Installing collected packages: click, itsdangerous, Werkzeug, MarkupSafe, Jinja2, flask
Successfully installed Jinja2-2.11.1 MarkupSafe-1.1.1 Werkzeug-1.0.0 click-7.0 flask-1.1.1 itsdangerous-1.1.0
4. เขียนโปรแกรม
ในเคสนี้ เราจะเขียนโปรแกรมง่าย ๆ คือ จะแสดงหน้าเว็บ Hello, world! เมื่อเปิดหน้า Homepage
app.py
รายละเอียด Source Code ของ Flask แต่ละบรรทัด จะอธิบายต่อไป
5. รันโปรแกรมในเครื่อง Local ด้วย Flask
เมื่อเขียนโปรแกรมเสร็จแล้ว ให้เซฟในชื่อไฟล์ app.py แล้วไปที่ shell พิมพ์คำสั่งดังนี้ เพื่อสั่ง flask ให้รันโปรแกรมขึ้นมา
export FLASK_APP=app.py
flask run
Output
* Serving Flask app "app.py"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
เปิด Web Browser ไปที่ http://127.0.0.1:5000/ จะเห็นหน้าเว็บดังรูป
เมื่อเปิดหน้าเว็บ หน้าจอ Shell จะมี Access Log แสดงขึ้นมา
Output
127.0.0.1 - - [13/Feb/2020 19:41:12] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [13/Feb/2020 19:41:12] "GET /favicon.ico HTTP/1.1" 404 -
6. เตรียม Deployment Script
การ Deploy บน Heroku จำเป็นต้องมีการกำหนด Library ที่ใช้งานคล้าย ๆ กับ venv เพื่อสร้าง Container เราจึงต้องเตรียมไฟล์สำหรับ Deploy บน Heroku ดังนี้
requirements.txt
กำหนด Library ที่จำเป็น
Procfile
กำหนดจุดเริ่มต้นของ app
.gitignore
กำหนดไฟล์ที่จะไม่นำเข้าสู่ git repository
7. Deploy บน Heroku Local
เราจะ Deploy บน Heroku Local ก่อน เพื่อเทส ก่อนที่จะ Deploy อัพขึ้น Server ของ Heroku บน Remote
heroku local
Output
8:12:14 PM web.1 | [2020-02-13 20:12:14 +0700] [30992] [INFO] Starting gunicorn 20.0.4
8:12:14 PM web.1 | [2020-02-13 20:12:14 +0700] [30992] [INFO] Listening at: http://0.0.0.0:5000 (30992)
8:12:14 PM web.1 | [2020-02-13 20:12:14 +0700] [30992] [INFO] Using worker: sync
8:12:14 PM web.1 | [2020-02-13 20:12:14 +0700] [30996] [INFO] Booting worker with pid: 30996
8:13:11 PM web.1 | [2020-02-13 20:13:11 +0700] [30992] [CRITICAL] WORKER TIMEOUT (pid:30996)
8:13:11 PM web.1 | [2020-02-13 20:13:11 +0700] [30996] [INFO] Worker exiting (pid: 30996)
8:13:11 PM web.1 | [2020-02-13 20:13:11 +0700] [31078] [INFO] Booting worker with pid: 31078
เปิด Web Browser ไปที่ http://127.0.0.1:5000/ จะเห็นหน้าเว็บดังรูป แต่คราวนี้มาจาก Heroku Local ไม่ใช่ Flask
8. Deploy บน Heroku Remote
สุดท้าย Deploy บน Heroku Remote ให้ user เข้ามาใช้งานได้ ด้วยการ add/commit/push เข้าไปที่ Git Remote ที่อยู่บน Heroku ที่ผูกไว้ก่อนหน้านี้
git add app.py requirements.txt Procfile .gitignore
git commit -m "Initital import to heroku"
Output
[master (root-commit) 148698d] Initital import to heroku
4 files changed, 18 insertions(+)
create mode 100644 .gitignore
create mode 100644 Procfile
create mode 100644 app.py
create mode 100644 requirements.txt
Push ไปยัง heroku ใน master branch
git push heroku master
Output
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 596 bytes | 596.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing python-3.6.10
remote: -----> Installing pip
remote: -----> Installing SQLite3
remote: Sqlite3 successfully installed.
remote: -----> Installing requirements with pip
remote: Collecting Flask==1.1.1 (from -r /tmp/build_58d6e6dae722e0ac1ef5f7f9701e5e7d/requirements.txt (line 1))
.
.
.
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 45M
remote: -----> Launching...
remote: Released v3
remote: https://hello-flask1.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/hello-flask1.git
* [new branch] master -> master
เปิด Web Browser ไปที่ https://hello-flask1.herokuapp.com/
Credit
- https://www.palletsprojects.com/p/flask/
- https://www.palletsprojects.com/p/jinja/
- https://www.palletsprojects.com/p/werkzeug/
- https://flask.palletsprojects.com/en/1.1.x/quickstart/
- https://devcenter.heroku.com/articles/getting-started-with-python