Dockerized Flask App using JDBC Hosted by AWS Fargate can’t connect

I have a simple web app that monitors a table. It runs a query, converts to dataframe, then prints the dataframe via HTML. The old app used a ODBC connection and was hosted on EC2. I have been told by my superiors to convert it to JDBC, containerize it, and deploy to AWS Fargate.

I am using Terraform to build the infrastructure. I suspect the Terraform is fine as the app launches via load balancer. However, it does not return any data. I am not sure where I’m going wrong. I’ve exposed the JDBC port, I’ve added the .jar, I’ve tried a vanilla Python Docker image, I’ve added OpenJDK to the Docker image.

All that is returned on the web page is the form with an empty data frame. It returns an empty dataframe no matter what I put in the form. I do not receive any sort of errors.

I have confirmed that port 9999 is open to the server from the subnet the AWS Fargate task is in via telnet.

app.py:

from flask import Flask, jsonify, request, render_template, send_from_directory
import jaydebeapi
import os
import pandas as pd
from socket import gethostname

app = Flask(__name__)


def execute_denodo(env, query):
    uid = 'redacted'
    pwd = 'redacted'
    db = 'mlcontrol'
    port = '9999'
    server = envs[env]['host']
    driver = '/app/denodo-vdp-jdbcdriver.jar'

    client_hostname = gethostname()
    useragent = '{}-{}'.format(jaydebeapi.__name__, client_hostname)
    conn_uri = 'jdbc:vdb://{}:{}/{}?userAgent={}'.format(server, port, db, useragent)

    conn = jaydebeapi.connect('com.denodo.vdp.jdbc.Driver',
                              conn_uri,
                              driver_args={'user': uid,'password': pwd},
                              jars=driver)

    df = pd.read_sql(query, conn)
    conn.close()

    return df


envs = {'prd': {'host': 'redacted'},
        'stg': {'host': 'redacted'},
        'dev': {'host': 'redacted'}}


@app.route('/', methods=['GET', 'POST'])
def mlcontrol_denodo():    
    if request.method == 'GET':
        days = 0
        env = 'prd'
    if request.method == 'POST':
        days = int(request.form['days'])
        env = request.form['env']

    try:
        df = pd.DataFrame()
        query = "select loadid, formatdate('dd-MMM-yyyy',updated) as updated, datatype, status, count(*) from mlcontrol where updated >= ADDDAY(current_date, - {}) group by loadid, formatdate('dd-MMM-yyyy',updated), datatype, status order by loadid desc;".format(days)
        df = execute_denodo(env, query).astype({'count': 'int32', 'loadid': 'int32'})
        df['count'] = df.apply(lambda x: "{:,}".format(x['count']), axis=1)

    except Exception as e:
        print(e)

    return render_template('index.html',  tables=[df.to_html(classes='data')], titles=df.columns.values)

@app.route('/api/health')
def health():
    print('Processing: '' + request.url + ''', flush=True)
    return jsonify({"success": True})


@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html', title='404'), 404


@app.errorhandler(500)
def internal_service_error(error):
    return render_template('500.html', title='500'), 500


@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>MarkLogic Loading Status</title>
    <link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
</head>

<body>
    <h3>MarkLogic Loading Status:</h3>
    <form name="mlcontrol" id="mlcontrol" action="/" method="POST">
        Environment:
        <input type="radio" name="env" value="prd" required /> Prod
        <input type="radio" name="env" value="stg" required /> Stage
        <input type="radio" name="env" value="dev" required /> Dev
        <br>
        <br>
        <input type="radio" name="days" value="0" /> Today OR 
        Previous Days:
        <input type="number" min="0" name="days"/>
        <button type="submit">Submit</button>
    </form>
    <br>
    <div class=page>
        {% for table in tables %}
        {{ table|safe }}
        {% endfor %}
    </div>

</body>

</html>

Dockerfile:

FROM openjdk:8
COPY --from=python:3.8 / /
WORKDIR /app
ADD . /app
RUN export CLASSPATH=${CLASSPATH}:/app/denodo-vdp-jdbcdriver.jar
RUN pip install --upgrade pip
RUN pip install --upgrade cython
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 80 9999
ENTRYPOINT ["python", "app.py"]

Working Tree:

+---app
|   |   app.py
|   |   denodo-vdp-jdbcdriver.jar
|   |   Dockerfile
|   |   requirements.txt
|   |   
|   +---static
|   |       favicon.ico
|   |       style.css
|   |       
|   ---templates
|           404.html
|           500.html
|           index.html
|           
---terraform
    |   main.tf
    |   outputs.tf
    |   terraform.plan
    |   var.tf

Source: Docker Questions