So option #1 would be to using docker exec
:
$ docker exec - it $containerid py.test
Then option #2 would be to create a script or task in your setup.py
so that you can run a simpler command like:
$ python setup.py test
My current solution is to mock the function that read the OS environment. OS ENV is loaded if the app started using docker. In order to make it easy for the test, I just mock that function.
def fake_secret_key(self):
return "ffakefake11"
def test_app(self, client):
app.secret_key = self.fake_secret_key
# ^ ^ real func ^ ^ fake func
Create pytest.ini
file, then put:
[pytest] env = APP_KEY = ffakefake11
I've built the flask app that designed to anycodings_docker run inside docker container. It will accept anycodings_docker POST HTTP Methods and return appropriate anycodings_docker JSON response if the header key matched with anycodings_docker the key that I put inside docker-compose anycodings_docker environment.,Or another alternative is using anycodings_docker pytest-env as @bufh suggested in anycodings_docker comment.,Then option #2 would be to create a anycodings_docker script or task in your setup.py so that anycodings_docker you can run a simpler command like:,I find some plugins one, two, three to do anycodings_docker this. But I asked here if there is any more anycodings_docker "simple"/"common" approach. Cause I also anycodings_docker want to automate this test using CI/CD anycodings_docker tools.
I've built the flask app that designed to anycodings_docker run inside docker container. It will accept anycodings_docker POST HTTP Methods and return appropriate anycodings_docker JSON response if the header key matched with anycodings_docker the key that I put inside docker-compose anycodings_docker environment.
... environment: -SECRET_KEY = fakekey123 ...
The problem is: when it comes to testing. anycodings_docker The app or the client fixture of flask anycodings_docker (pytest) of course can't find the anycodings_docker docker-compose environment. Cause the app anycodings_docker didn't start from docker-compose but from anycodings_docker pytest.
secret_key = os.environ.get("SECRET_KEY") # ^ ^ the key loaded to OS env by docker - compose post_key = headers.get("X-Secret-Key") ... if post_key == secret_key: RETURN APPROPRIATE RESPONSE .....
So option #1 would be to using docker anycodings_docker exec:
$ docker exec - it $containerid py.test
Then option #2 would be to create a anycodings_docker script or task in your setup.py so that anycodings_docker you can run a simpler command like:
$ python setup.py test
My current solution is to mock the anycodings_docker function that read the OS environment. anycodings_docker OS ENV is loaded if the app started anycodings_docker using docker. In order to make it easy anycodings_docker for the test, I just mock that function.
def fake_secret_key(self):
return "ffakefake11"
def test_app(self, client):
app.secret_key = self.fake_secret_key
# ^ ^ real func ^ ^ fake func
Create pytest.ini file, then put:
[pytest] env = APP_KEY = ffakefake11
One is the conftest.py. This file is responsible for set up pytest to run all tests in the application. Its code is:,And we have Dockerfile, too. This file is responsible for the Docker Image creation. This Image will be used to up the container with the Flask Application. Its code is:,Now the most important test. We execute the pytest into our container to run tests against our Flask application. The test is just simple only assert if the status code returned by the Flask App is 200 Ok!,Again, the focus of this article isn’t to explain detailed of the Flask application, so if you have questions about how to test Flask apps
Even though a simple “Hello World” I worked with the best practices of architecture to it. I had the following directory structure:
.├──backend│├── app.py│├── blueprints││├── core│││├── bp.py│││├── __init__.py│││├── routes.py│││└── tests│││└── test_bp_core.py││└── __init__.py│└── __init__.py├── conftest.py├── Dockerfile├──.dockerignore├──.gitignore├── Pipfile├── Pipfile.lock├── pytest.ini└── README.md
The .
(dot) is the root of project. In the backend
I have Flask application properly. I used the factory pattern for the architecture. So, in the app.py
I have this:
from flask
import Flask
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'My_Top_Secert_Key'
# Blueprint
from backend.blueprints.core
import bp as bp_core
bp_core.config(app)
return app
This code is responsible to create my Flask app. The focus of this article isn’t to explain about Flask and so on. But, how to construct an app and run it into a Docker container. In the backend/bluprints/core I have my blueprint (see de documentation to know more about blueprints), the code is in bp.py and route.py, both configure my core blueprint. The first have this code:
from flask import Blueprint bp = Blueprint('core', __name__) def config(app): from backend.blueprints.core import routes # noqa app.register_blueprint(bp)
In the backend/blueprint/core/tests
I have my tests of this blueprint. It’s a simple test, and its code is:
import pytest
from flask
import url_for
@pytest.fixture
def resp(client):
return client.get(url_for('core.home'))
def test_bp_home_status_code_ok(resp):
assert resp.status_code == 200
One is the conftest.py
. This file is responsible for set up pytest
to run all tests in the application. Its code is:
import pytest
from backend.app
import create_app
@pytest.fixture
def app():
app = create_app()
return app
@pytest.fixture
def client(app):
with app.test_client() as c:
yield c
FROM python: 3.7 .1
LABEL Author = "Vicente Marçal"
RUN mkdir / app
WORKDIR / app
COPY Pip * /app/
December 8, 2021 6 min read 1816
Let’s proceed to create a simple Flask application that renders a message on the browser. Create a folder with the name flask_docker
to contain your application.
mkdir flask_docker
Next, cd
into the flask_docker
directory and run the below command to install Flask.
pip install Flask
After successfully installing Flask, the next step is to create a Python file that receives and responds to requests in our application. Create a view.py
file that will contain the Python code snippet below:
from flask
import Flask, render_template
import os
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
if __name__ == "__main__":
port = int(os.environ.get('PORT', 5000))
app.run(debug = True, host = '0.0.0.0', port = port)
The home()
function bound to the URL provided in the @app.route
annotation will run when you send a GET
request to this route. The function returns a call to render_template
that in turn renders the content of the index.html
file, which we will create in the next section.
port = int(os.environ.get('PORT', 5000))
app.run(debug = True, host = '0.0.0.0', port = port)
Within the root directory, create a templates
directory, then create the index.html
file. Add the below code snippet to the HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask Docker</title>
</head>
<body>
<h1>This is a Flask App containerised with Docker</h1>
</body>
</html>
Creating a Docker image to Dockerize your Flask python application,Before we dive into the nitty-gritty of “How to Dockerize Flask Python Application”, let’s see the components that we are going to deploy as Docker Containers.,Deploy your Flask python application using Docker in Production,Creating a Dockerfile to Dockerize your Python Flask Application
- Go to the home directory
$ cd /home/ubuntu/ - Create a new directory
$ mkdir clickittech - Change your current working directory and stay in it throughout the article.
$ cd clickittech/ - Create a directory to put Python Flask Application files under it
$ mkdir flask - Create a main.py under the flask directory
$ vim flask/main.py
import redisfrom flask
import Flaskapp = Flask(__name__) redis = redis.Redis(host = 'redis', port = 6379, db = 0) @app.route('/') def hello_world(): return 'This is a Python Flask Application with redis and accessed through Nginx'
@app.route('/visitor') def visitor(): redis.incr('visitor') visitor_num = redis.get('visitor').decode("utf-8") return "Visit Number = : %s" % (visitor_num) @app.route('/visitor/reset') def reset_visitor(): redis.set('visitor', 0) visitor_num = redis.get('visitor').decode("utf-8") return "Visitor Count has been reset to %s" % (visitor_num)
- Stay in the same directory(/home/ubuntu/clickittech) and create a Dockerfile in the “flask” directory for creating an image of the Python Flask Application.
$ vim flask/Dockerfile
FROM python: 3.7 - alpine
RUN mkdir / app
WORKDIR / app
ADD requirements.txt / app
ADD main.py / app
RUN pip3 install - r requirements.txt
CMD["gunicorn", "-w 4", "-b", "0.0.0.0:8000", "main:app"]
- Now create a file containing application requirements
$ vim flask/requirements.txt
Flask == 1.1 .2 redis == 3.4 .1 gunicorn >= 19, < 20 F
- Also, create a conf file that will hold the routing configuration
$ vim nginx/conf
server {
listen 80;
server_name localhost;
location / {
proxy_pass http: //app:8000;
}
location / hit {
proxy_pass http: //app:8000/visitor;
}
location / hit / reset {
proxy_pass http: //app:8000/visitor/reset;
}
}
- Stay in your “/home/ubuntu/clickittech” directory and create a docker-compose.yml in it.
$ vim docker-compose.yml
version: '3'
services: app: build: flask volumes: -app: /app ports: - "8000:8000"