From 152243f6538d9e5ce5a2a34516e45b7dfbac8b7a Mon Sep 17 00:00:00 2001 From: Henrik Loeser Date: Tue, 5 Jul 2022 15:29:18 +0200 Subject: [PATCH] new version for Code Engine (#5) * version for Code Engine * Db2 driver version * Db2 driver version * old CF branch --- Dockerfile | 55 ++++++++++++++++++++++++++++++++++++++++++++ Procfile | 1 - README.md | 11 +++++++-- manifest.yml | 7 ------ requirements.txt | 6 +++-- runtime.txt | 1 - templates/index.html | 2 +- worldcities.py | 21 ++++++++++------- 8 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 Dockerfile delete mode 100644 Procfile delete mode 100644 manifest.yml delete mode 100644 runtime.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..337d8ba --- /dev/null +++ b/Dockerfile @@ -0,0 +1,55 @@ +######## +# Python dependencies builder +# +# Full official Debian-based Python image +FROM python:3.8 AS builder + +# Always set a working directory +WORKDIR /app +# Sets utf-8 encoding for Python et al +ENV LANG=C.UTF-8 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + + +# Ensures that the python and pip executables used +# in the image will be those from our virtualenv. +ENV PATH="/venv/bin:$PATH" + +# Install OS package dependencies. +# Do all of this in one RUN to limit final image size. +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential && \ + rm -rf /var/lib/apt/lists/* + +# Setup the virtualenv +RUN python -m venv /venv + +# Install Python deps +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + + +# Actual container +# +# +FROM python:3.8-slim AS app + +# Extra python env +ENV PATH="/venv/bin:$PATH" + +WORKDIR /app +EXPOSE 8080 + +# copy in Python environment +COPY --from=builder /venv /venv + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libxml2 && \ + rm -rf /var/lib/apt/lists/* + +# copy in the rest of the app +COPY ./ ./ +ENTRYPOINT ["gunicorn", "--bind", "0.0.0.0:8080","worldcities:app"] \ No newline at end of file diff --git a/Procfile b/Procfile deleted file mode 100644 index b074077..0000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: python worldcities.py diff --git a/README.md b/README.md index 4e812fa..befafad 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**Note**: A former version of the tutorial deployed the app to Cloud Foundry Public on IBM Cloud. You can find the material in the [branch **cloudfoundry**](https://github.com/IBM-Cloud/cloud-sql-database/tree/cloudfoundry). + # IBM Cloud SQL Database This tutorial shows how to provision a SQL (relational) database service, create a table and load a larger data set, city information into the database. Thereafter, we deploy a web app "worldcities" to make use of that data and show how to access the cloud database. The app is written in Python using the Flask framework. @@ -5,6 +7,11 @@ This tutorial is part of [IBM Cloud tutorials](https://cloud.ibm.com/docs/tutori # Up and running in few steps To get this SQL database-backed app up and running only few steps and about 10 minutes are needed. Please follow the steps outlined in the IBM Cloud tutorial. - + +# Local testing + +- Install the requirements to run Python directly or build and run the container image. +- Set the environment variable **DASHDB_SSLDSN** to the value obtained from the Db2 Warehouse credentials for the key **ssldsn**. + # Feedback -If you have feedback on the code or the related tutorial, please either open an issue on this repository or leave documentation feedback at the above mentioned tutorial. +If you have feedback on the code or the related tutorial, please open an issue on this repository. diff --git a/manifest.yml b/manifest.yml deleted file mode 100644 index f0de4f4..0000000 --- a/manifest.yml +++ /dev/null @@ -1,7 +0,0 @@ -applications: -- name: worldcities - memory: 256M - command: python worldcities.py - random-route: true - services: - - sqldatabase diff --git a/requirements.txt b/requirements.txt index 7716b31..55276f1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ -Flask -ibm_db +Flask==2.0.3 +gunicorn +ibm_db == 3.1.2 +python-dotenv==0.15.0 \ No newline at end of file diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index 5a26ef3..0000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.7.x diff --git a/templates/index.html b/templates/index.html index ae8d279..1757a33 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,7 +3,7 @@ {% block title %}World Cities{% endblock %} {% block content %}

Hello Cities of the World!

-

This app is named "{{ app["application_name"] }}". You can search for information on cities with a population over 1000. Use the local name. +

You can search for information on cities with a population over 1000. Use the local name. As an alternative, you can directly access city information using "/city/name", e.g., /city/Friedrichshafen.


diff --git a/worldcities.py b/worldcities.py index 2ff0599..18dc853 100644 --- a/worldcities.py +++ b/worldcities.py @@ -1,4 +1,4 @@ -# (C) 2017 IBM +# (C) 2017-2022 IBM # Author: Henrik Loeser # # Very short sample app used with Db2 Warehouse on Cloud to demonstrate @@ -12,22 +12,27 @@ import json import ibm_db +# for loading .env +from dotenv import load_dotenv + +# load environment +load_dotenv() + app = Flask(__name__) # get service information if on IBM Cloud Platform -if 'VCAP_SERVICES' in os.environ: - db2info = json.loads(os.environ['VCAP_SERVICES'])['dashDB'][0] - db2cred = db2info["credentials"] - appenv = json.loads(os.environ['VCAP_APPLICATION']) +if 'DASHDB_SSLDSN' in os.environ: + db2cred = os.getenv('DASHDB_SSLDSN') else: - raise ValueError('Expected cloud environment') + # log error, but continue - it might be before service binding + app.logger.error('No Db2 credentials configured.') # handle database request and query city information def city(name=None): # connect to DB2 rows=[] try: - db2conn = ibm_db.connect(db2cred['ssldsn'], "","") + db2conn = ibm_db.connect(db2cred, "","") if db2conn: # we have a Db2 connection, query the database sql="select * from cities where name=? order by population desc" @@ -55,7 +60,7 @@ def city(name=None): # main page to dump some environment information @app.route('/') def index(): - return render_template('index.html', app=appenv) + return render_template('index.html') # for testing purposes - use name in URI @app.route('/hello/')