I’m trying to get a small webapp running in a Docker container with very little experience in Docker. The webapp uses input from a form, renders a template and returns it as a text file to the user.
If I run the app locally everything works as expected.
If I run the app in a Docker container, I can access every static site. When pressing “submit” in the form, I get a “connection refused” error.
In the Flask debugger I don’t see anything happening which leads me to believe that either the form data never makes it to Flask or Flask for whatever reason (missing module?) fails to send me the file in Docker.
From researching I figure that I don’t need to add any local firewall rules. I realize that the Docker container is a bit large and I could use alpine and gunicorn instead of centos but at this point I’m not looking for efficiency.
The Docker host is running CentOS 7.
Requirements.txt:
Flask==1.1.2
Docker file:
FROM centos:centos7
COPY ./requirements.txt /app/requirements.txt
RUN yum install -y python3 python3-pip python3-devel
WORKDIR /app
RUN pip3 install --no-cache-dir -r requirements.txt
COPY . /app
ENTRYPOINT ["python3"]
CMD ["flaskapp.py" ]
Docker start command
docker run -d -p 5000:5000 flaskapp
Output when running python3 flaskapp.py locally and submitting the form
PS c:user> python3.exe .flaskapp.py
* Serving Flask app "flaskapp" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 205-510-917
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [17/Jun/2020 15:31:28] "[37mGET /generator HTTP/1.1[0m" 200 -
127.0.0.1 - - [17/Jun/2020 15:32:00] "[37mPOST /result HTTP/1.1[0m" 200 -
Same actions in Docker container
]# docker run -p 5000:5000 flaskapp
* Serving Flask app "flaskapp" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 161-592-324
10.10.10.10 - - [17/Jun/2020 13:30:10] "GET /generator HTTP/1.1" 200 -
Form action in html
<form action = "http://localhost:5000/result" method = "POST">
<p><input type = "submit" value = "submit" /></p>
Flaskapp.py shortened to just contain my send_file usages
from flask import Flask, render_template, request, send_file
import ipaddress
import zipfile
from pathlib import Path
app = Flask(__name__)
[...]
# generate configuration when data is received from generator form
@app.route('/result', methods=['POST', 'GET'])
def result():
[...] some code, input checks, text manipulation
# check folder content for .cfg files and add them to a zip archive
with zipfile.ZipFile(temp_zipfile, mode='w') as z:
for file in base_path.iterdir():
if file.suffix == ".cfg":
try:
z.write(file, file, zipfile.ZIP_DEFLATED)
except:
continue
# send the zip file to the user
return send_file(temp_zipfile, as_attachment=True, mimetype='application/zip',attachment_filename="configurations.zip")
# if HA is not used, send a cfg file directly
elif result["cluster"] == "no":
configfile = config_filepath + result["HOSTNAME"] + ".cfg"
with open(configfile, "w+") as cfg:
cfg.write(content)
return send_file(configfile, as_attachment=True,attachment_filename='configurations.cfg')
Am I missing a step in the Docker setup or is there additional debugging I could do?
2
Answers
Kendas' comment pointed to the obvious, the form action was pointing to localhost which could not work. Changed the form action to the servers' IP address, now everything's working.
It looks like a problem with Docker configuration. I’m assuming that you are using Docker for Windows or alternative and not Docker Toolbox.
Run
docker ps
and take a look at the PORTS section. There should be a binding between localhost of your docker host machine and the exposed port of the docker container. The section should read0.0.0.0:5000->5000/tcp
.You are not saying how you are running your container. To achieve the port binding you should add the
-p
parameter. An example would bedocker run -p 5000:5000 image_name
I recommend going through the basic Docker documentation. It is not too long and should give you more clarity about how it works.