├── .gitignore ├── Dockerfile ├── Pipfile ├── Pipfile.lock ├── README.md ├── app.py ├── app.yaml ├── config.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6-jessie 2 | 3 | RUN apt update 4 | 5 | WORKDIR /app 6 | ADD requirements.txt /app/requirements.txt 7 | RUN pip install -r /app/requirements.txt 8 | 9 | ADD . /app 10 | 11 | ENV PORT 8080 12 | CMD ["gunicorn", "app:app", "--config=config.py"] 13 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | click = "==7.0" 8 | flask = "==1.0.2" 9 | itsdangerous = "==1.1.0" 10 | "jinja2" = "==2.10" 11 | markupsafe = "==1.1.0" 12 | werkzeug = "==0.14.1" 13 | gunicorn = "==19.9.0" 14 | 15 | [dev-packages] 16 | 17 | [requires] 18 | python_version = "3.6" 19 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "085e7f1cf3e43384878f361061b669dab685751883c0c65302381770fac45114" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.6" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "click": { 20 | "hashes": [ 21 | "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", 22 | "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" 23 | ], 24 | "index": "pypi", 25 | "version": "==7.0" 26 | }, 27 | "flask": { 28 | "hashes": [ 29 | "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", 30 | "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" 31 | ], 32 | "index": "pypi", 33 | "version": "==1.0.2" 34 | }, 35 | "gunicorn": { 36 | "hashes": [ 37 | "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471", 38 | "sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3" 39 | ], 40 | "index": "pypi", 41 | "version": "==19.9.0" 42 | }, 43 | "itsdangerous": { 44 | "hashes": [ 45 | "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", 46 | "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" 47 | ], 48 | "index": "pypi", 49 | "version": "==1.1.0" 50 | }, 51 | "jinja2": { 52 | "hashes": [ 53 | "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", 54 | "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" 55 | ], 56 | "index": "pypi", 57 | "version": "==2.10" 58 | }, 59 | "markupsafe": { 60 | "hashes": [ 61 | "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", 62 | "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", 63 | "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", 64 | "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", 65 | "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", 66 | "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", 67 | "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", 68 | "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", 69 | "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", 70 | "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", 71 | "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", 72 | "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", 73 | "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", 74 | "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", 75 | "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", 76 | "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", 77 | "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", 78 | "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", 79 | "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", 80 | "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", 81 | "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", 82 | "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", 83 | "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", 84 | "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", 85 | "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", 86 | "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", 87 | "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", 88 | "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" 89 | ], 90 | "index": "pypi", 91 | "version": "==1.1.0" 92 | }, 93 | "werkzeug": { 94 | "hashes": [ 95 | "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", 96 | "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" 97 | ], 98 | "index": "pypi", 99 | "version": "==0.14.1" 100 | } 101 | }, 102 | "develop": {} 103 | } 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flask on Kubernetes 2 | 3 | Read the deployment guide: [A Guide to Deploy Flask App on Google Kubernetes Engine](https://medium.com/@pyk/a-guide-to-deploy-flask-app-on-google-kubernetes-engine-bfbbee5c6fb) 4 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | import config 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route("/") 8 | def hello(): 9 | return "Hello World!" 10 | 11 | if __name__ == "__main__": 12 | app.run(host="0.0.0.0", port=config.PORT, debug=config.DEBUG_MODE) 13 | -------------------------------------------------------------------------------- /app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta2 2 | kind: Deployment 3 | metadata: 4 | name: flask-app-tutorial 5 | labels: 6 | name: flask-app-tutorial 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | name: flask-app-tutorial 12 | template: 13 | metadata: 14 | name: flask-app-tutorial 15 | labels: 16 | name: flask-app-tutorial 17 | spec: 18 | containers: 19 | - name: flask-app-tutorial 20 | image: gcr.io/YOUR_GCP_PROJECT_NAME/flask-app:v2 21 | ports: 22 | - containerPort: 8080 23 | resources: 24 | requests: 25 | memory: 256Mi 26 | limits: 27 | memory: 512Mi 28 | env: 29 | - name: PORT 30 | value: "8080" 31 | - name: DEBUG_MODE 32 | value: "1" 33 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | from os import environ as env 2 | import multiprocessing 3 | 4 | PORT = int(env.get("PORT", 8080)) 5 | DEBUG_MODE = int(env.get("DEBUG_MODE", 1)) 6 | 7 | # Gunicorn config 8 | bind = ":" + str(PORT) 9 | workers = multiprocessing.cpu_count() * 2 + 1 10 | threads = 2 * multiprocessing.cpu_count() 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | Flask==1.0.2 3 | gunicorn==19.9.0 4 | itsdangerous==1.1.0 5 | Jinja2==2.10 6 | MarkupSafe==1.1.0 7 | Werkzeug==0.14.1 8 | --------------------------------------------------------------------------------