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 %}
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/