Docker VPS work with HTTP but not with HTTPS

I am trying to host my Flask Rest API from Docker container within a VPS (apache). Its working fine with http but not working with https.

Dockerfile

FROM python:3.11
# Virtual envs not needed inside container
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
COPY . /app
RUN python3 -m pip install -r /app/requirements.txt

EXPOSE 5000
CMD ["flask", "--app=app", "run", "--host=0.0.0.0"]

running $ docker run --rm -it -p 8080:5000 myapp:latest allow me to run http://myapphostwebsite.com:8080/user/12345 on Postman. I could then retrieve data but when using https://myapphostwebsite.com:8080/user/12345 , I got this Postman error :

Error: write EPROTO 5543930632:error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER:../../../../src/third_party/boringssl/src/ssl/tls_record.cc:242:

And the Docker Log gives this

code 400, message Bad request version ('À\x13À') \x16\x03\x01\x00ü\x01\x00\x00ø\x...

I don’t know what to do. How to access my Docker container outside with https?

PS : I used Certbot to setup SSL on my VPS

Your flask looks like it is configured to expect HTTP conection, not HTTPS. Please, share why you think it should work. How did you configured flask to expect HTTPS on the port?

Here is the main file (containing the config) of my Flask app, it’s very basic :
app.py

from flask import Flask, request, jsonify, json
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.event import listens_for
from flaskext.mysql import MySQL
from flask_cors import CORS
from dataclasses import dataclass
from sqlalchemy import text
from urllib.parse import quote

app = Flask(__name__)


db = SQLAlchemy()

mysql =MySQL()

@dataclass
class User(db.Model):

    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(46), nullable=False)#1
    lastname = db.Column(db.String(46), nullable=False)#1
    

    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname

    def as_dict(self):
        excluded_fields = ['id']
        return {field.name:getattr(self, field.name) for field in self.__table__.c if field.name not in excluded_fields}

@dataclass
class User(db.Model):

    __tablename__ = 'user'
    __table_args__ = {'extend_existing': True} 

    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(46), nullable=False)#1
    lastname = db.Column(db.String(46), nullable=False)#1

    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname

    def as_dict(self):
        excluded_fields = ['id']
        return {field.name:getattr(self, field.name) for field in self.__table__.c if field.name not in excluded_fields}



app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:pwd@127.0.0.1/test'

db.init_app(app)
with app.app_context():
    db.create_all()


@app.route('/users', methods=['GET'])
def get_user():
    users = User.query.all()
    return jsonify(users)

@app.route('/user/<firstname>', methods=['GET'])
def user_byfirstname(firstname):
    user = User.query.filter_by(firstname = firstname).first()
    return jsonify(user.as_dict())

if __name__ == '__main__':
   app.run(debug=True)

I don’t see anything SSL related in the shared code. Please, point out which line is responsible for that.

I’m also going to move the topic out of the Docker Hub category as it has nothing to do with Docker Hub.

Flask probably doesn’t know very much about TLS/SSL. You either need to buy a cert or use something like LetsEncrypt to create a free one.

Usually a reverse proxy is used in front of applications to manage and terminate TLS, check nginx-proxy and companion (link) or simple Traefik example (link).

just to point out that it is the case :slight_smile:

But it is not clear how that was configured to be used. If flask can handle it, I would use that unless I need to run other containers too. Then I would definitely use Traefik.

1 Like

setting up ssl into my Flask app solved my problem. Thx everyone