DEV Community

Cover image for Managing Dependencies with Poetry for a Flask App on Ubuntu 24.04
Sanskriti Harmukh for Vultr

Posted on with Aashish Chaurasiya Originally published at docs.vultr.com

Managing Dependencies with Poetry for a Flask App on Ubuntu 24.04

Poetry is an open-source tool for managing and packaging dependencies for Python projects. It maintains a clean view of your dependency tree, streamlines the installation and management of dependencies, and simplifies packaging and distribution to PyPI. This guide installs Poetry with Pipx on Ubuntu 24.04, creates a virtual environment, and runs a Flask application using Poetry and Gunicorn. By the end, you'll have a Flask app managed entirely through Poetry, tested with Pytest, and served in production mode with Gunicorn.


Prerequisites

Before you begin, you need to:

  • Have access to an Ubuntu 24.04 server.

Install Poetry with Pipx

Installing Poetry in an isolated environment prevents conflicts between Poetry's internal dependencies and system-wide dependencies.

1. Update the APT package index:

$ sudo apt update
Enter fullscreen mode Exit fullscreen mode

2. Install Pipx:

$ sudo apt install pipx -y
Enter fullscreen mode Exit fullscreen mode

3. Add the Pipx libraries to your system's PATH:

$ pipx ensurepath
Enter fullscreen mode Exit fullscreen mode

4. Enable tab completions for Pipx commands:

$ echo 'eval "$(register-python-argcomplete pipx)"' >> ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

5. Reload the .bashrc shell configuration to apply the changes in your active session:

$ source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

6. Install Poetry using Pipx:

$ pipx install poetry
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

installed package poetry 2.0.0, installed using Python 3.12.3
  These apps are now globally available
    - poetry
done! ✨ 🌟 ✨
Enter fullscreen mode Exit fullscreen mode

7. View the installed Poetry version:

$ poetry --version
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

Poetry (version 2.0.0)
Enter fullscreen mode Exit fullscreen mode

Create a Poetry Project

1. Create a new flask-app Poetry project:

$ poetry new flask-app
Enter fullscreen mode Exit fullscreen mode

This creates a flask-app directory with the following files:

  • flask_app: Contains an __init__.py file that specifies all Flask code, including modules, functions, and other related support components.
  • pyproject.toml: Includes information about the project, Poetry configuration, and installed dependencies.
  • README.md: Includes basic documentation about the project.
  • tests: Integrates and organizes the project's test cases.

Your output should be similar to the one below:

Created package flask_app in flask-app
Enter fullscreen mode Exit fullscreen mode

2. Switch to the flask-app project directory:

$ cd flask-app
Enter fullscreen mode Exit fullscreen mode

Create a Virtual Environment and Install Flask

1. Specify the Python interpreter for Poetry and create a new virtual environment:

$ poetry env use python3
Enter fullscreen mode Exit fullscreen mode

This instructs Poetry to use the default Python3 interpreter on your system. You can also target a specific version, such as poetry env use python3.11, if that version is installed.

Your output should be similar to the one below:

Creating virtualenv flask-app-vnQ3DaWl-py3.12 in /home/linuxuser/.cache/pypoetry/virtualenvs
Using virtualenv: /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12
Enter fullscreen mode Exit fullscreen mode

2. Activate the virtual environment:

$ poetry env activate
Enter fullscreen mode Exit fullscreen mode

This outputs the command to run in order to activate the virtual environment manually. Your output should be similar to the one below:

source /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12/bin/activate
Enter fullscreen mode Exit fullscreen mode

3. Activate the virtual environment using its path:

$ source /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12/bin/activate
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below when the virtual environment is activated:

(flask-app-py3.12) linuxuser@:~/flask-app$
Enter fullscreen mode Exit fullscreen mode

4. Install Flask using Poetry:

$ poetry add flask
Enter fullscreen mode Exit fullscreen mode

This installs Flask with all dependencies in the active virtual environment, adds the installed Flask version to pyproject.toml, and creates a poetry.lock file for deterministic builds.

Your output should be similar to the one below:

Using version ^3.1.0 for flask

Updating dependencies
Resolving dependencies... (0.2s)

Package operations: 7 installs, 0 updates, 0 removals

- Installing markupsafe (3.0.2)
- Installing blinker (1.9.0)
- Installing click (8.1.8)
- Installing itsdangerous (2.2.0)
- Installing jinja2 (3.1.5)
- Installing werkzeug (3.1.3)
- Installing flask (3.1.0)

Writing lock file
Enter fullscreen mode Exit fullscreen mode

5. Deactivate the virtual environment:

$ deactivate
Enter fullscreen mode Exit fullscreen mode

Set Up Firewall Rules

Uncomplicated Firewall (UFW) is active on most Ubuntu 24.04 servers by default. Configure UFW to allow connections to the Flask application port 5000.

1. Allow connections to the Flask application port 5000:

$ sudo ufw allow 5000/tcp
Enter fullscreen mode Exit fullscreen mode

2. Reload UFW to apply the firewall configuration changes:

$ sudo ufw reload
Enter fullscreen mode Exit fullscreen mode

3. View the UFW status and verify that the rule is active:

$ sudo ufw status
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                  
5000/tcp                   ALLOW       Anywhere                  
22/tcp (v6)                ALLOW       Anywhere (v6)             
5000/tcp (v6)              ALLOW       Anywhere (v6)             
Enter fullscreen mode Exit fullscreen mode

Run the Flask App with Poetry

1. Retrieve the command to reactivate the virtual environment:

$ poetry env activate
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

source /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12/bin/activate
Enter fullscreen mode Exit fullscreen mode

2. Activate the virtual environment:

$ source /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12/bin/activate
Enter fullscreen mode Exit fullscreen mode

3. Navigate to the flask_app directory:

$ cd flask_app
Enter fullscreen mode Exit fullscreen mode

4. Create a file app.py using nano:

$ nano app.py
Enter fullscreen mode Exit fullscreen mode

5. Add the following code:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "<h1>Hello from Flask</h1>"

if __name__ == '__main__':
   app.run(host='0.0.0.0', port='5000')
Enter fullscreen mode Exit fullscreen mode

Save the file with Ctrl+X, then Y, then Enter. This creates a webpage that returns Hello from Flask on the home route /.

6. Run the Flask application:

$ poetry run python app.py
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://<SERVER-IP>:5000
Press CTRL+C to quit
Enter fullscreen mode Exit fullscreen mode

7. Access your Flask app using the following address in a web browser. Replace <SERVER-IP> with your server's IP address:

http://<SERVER-IP>:5000
Enter fullscreen mode Exit fullscreen mode

Flask application home page

8. To stop the Flask app, press Ctrl+C in your terminal session.

Create Group Dependencies

Poetry allows you to manage dependencies using groups. Follow these steps to create a group called dev and install Pytest for testing.

1. Install Pytest in the dev dependency group:

$ poetry add pytest --group dev
Enter fullscreen mode Exit fullscreen mode

This creates a new section in pyproject.toml — [tool.poetry.group.dev.dependencies] — which includes dependencies such as pytest = "^8.3.4" under the dev group. Production dependencies should not be added to any group; they belong under the root dependencies ([tool.poetry.dependencies]) instead, so they aren't excluded during deployment or packaging.

2. Navigate to your project's tests directory:

$ cd ~/flask-app/tests
Enter fullscreen mode Exit fullscreen mode

3. Create a new directory named unit:

$ mkdir unit
Enter fullscreen mode Exit fullscreen mode

4. Navigate into the unit directory:

$ cd unit
Enter fullscreen mode Exit fullscreen mode

5. Create an __init__.py file:

$ touch __init__.py
Enter fullscreen mode Exit fullscreen mode

This marks the directory as a Python package, allowing you to import modules from it.

6. Create a test file test_app.py using nano:

$ nano test_app.py
Enter fullscreen mode Exit fullscreen mode

7. Add the following code to the file:

import pytest
from flask_app.app import app  

@pytest.fixture
def client():
    with app.test_client() as client:
        yield client

def test_the_home_route(client):
    response = client.get('/')
    assert response.status_code == 200
    assert b"<h1>Hello from Flask</h1>" in response.data
Enter fullscreen mode Exit fullscreen mode

Save the file with Ctrl+X, then Y, then Enter. This checks that the response body from app.py contains the markup <h1>Hello from Flask</h1>.

8. Run the test:

$ pytest
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

platform linux -- Python 3.12.3, pytest-8.3.4, pluggy-1.5.0
rootdir: /home/linuxuser/flask-app
configfile: pyproject.toml
collected 1 item                                                             

test_app.py .                                                          [100%]

============================= 1 passed in 0.11s ==============================
Enter fullscreen mode Exit fullscreen mode

Install Gunicorn, a WSGI HTTP Server, with Flask

A WSGI HTTP server such as Gunicorn handles client requests concurrently and efficiently, making it ideal for production-grade Flask applications.

1. Navigate to the flask_app directory:

$ cd ~/flask-app/flask_app
Enter fullscreen mode Exit fullscreen mode

2. Add Gunicorn as a root dependency:

$ poetry add gunicorn
Enter fullscreen mode Exit fullscreen mode

3. Create a wsgi.py file using nano:

$ nano wsgi.py
Enter fullscreen mode Exit fullscreen mode

4. Add the following Python code:

from app import app

if __name__ == '__main__':
   app.run()
Enter fullscreen mode Exit fullscreen mode

5. Run the Flask app with Gunicorn:

$ gunicorn --bind 0.0.0.0:5000 wsgi:app
Enter fullscreen mode Exit fullscreen mode

6. Check that your Flask app is still accessible:

http://<SERVER-IP>:5000
Enter fullscreen mode Exit fullscreen mode

Flask application home page

7. Press Ctrl+C to stop the server.

Manage the Virtual Environment

1. Exit the virtual environment:

$ deactivate
Enter fullscreen mode Exit fullscreen mode

2. List all virtual environments for your project:

$ poetry env list
Enter fullscreen mode Exit fullscreen mode

The environment labeled (Activated) is the one in use. Your output should be similar to the one below:

flask-app-vnQ3DaWl-py3.12 (Activated)
Enter fullscreen mode Exit fullscreen mode

3. Copy the environment name from the previous command's output and remove the virtual environment:

$ poetry env remove flask-app-vnQ3DaWl-py3.12
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

Deleted virtualenv: /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12
Enter fullscreen mode Exit fullscreen mode

4. Recreate the virtual environment:

$ poetry env use python3
Enter fullscreen mode Exit fullscreen mode

5. Retrieve the command to reactivate the virtual environment:

$ poetry env activate
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

source /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12/bin/activate
Enter fullscreen mode Exit fullscreen mode

6. Activate the virtual environment by copying and running the activation command from the previous step:

$ source /home/linuxuser/.cache/pypoetry/virtualenvs/flask-app-vnQ3DaWl-py3.12/bin/activate
Enter fullscreen mode Exit fullscreen mode

7. Install all the dependencies from the pyproject.toml file:

$ poetry install
Enter fullscreen mode Exit fullscreen mode

With the pyproject.toml file present, the virtual environment and dependencies can always be recreated and reinstalled.

Modify the Virtual Environment Location

By default, Poetry creates a virtual environment in /.cache/pypoetry/virtualenvs. To keep the virtual environment organized alongside your project files, you can move its location to the root of your project.

1. Exit the virtual environment:

$ deactivate
Enter fullscreen mode Exit fullscreen mode

2. List the virtual environments for your project:

$ poetry env list
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

flask-app-vnQ3DaWl-py3.12 (Activated)
Enter fullscreen mode Exit fullscreen mode

3. Remove the virtual environment:

$ poetry env remove flask-app-vnQ3DaWl-py3.12
Enter fullscreen mode Exit fullscreen mode

4. Configure Poetry to allow the virtual environment to be created at the root of your project:

$ poetry config virtualenvs.in-project true
Enter fullscreen mode Exit fullscreen mode

This overwrites the default configuration set by Poetry and allows the virtual environment to be created in the root of your project.

5. Verify that the configuration change is applied:

$ poetry config virtualenvs.in-project 
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

true
Enter fullscreen mode Exit fullscreen mode

6. Create a virtual environment to verify:

$ poetry env use python3
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

Creating virtualenv flask-app in /home/linuxuser/flask-app/.venv
Using virtualenv: /home/linuxuser/flask-app/.venv
Enter fullscreen mode Exit fullscreen mode

7. Retrieve the command to activate the virtual environment:

$ poetry env activate
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

source /home/linuxuser/flask-app/.venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

8. Activate the virtual environment:

$ source /home/linuxuser/flask-app/.venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

9. View your virtual environment information:

$ poetry env info
Enter fullscreen mode Exit fullscreen mode

Your output should be similar to the one below:

Virtualenv
Python:         3.12.3
Implementation: CPython
Path:           /home/linuxuser/flask-app/.venv
Executable:     /home/linuxuser/flask-app/.venv/bin/python
Valid:          True

Base
Platform:   linux
OS:         posix
Python:     3.12.3
Path:       /usr
Executable: /usr/bin/python3.12
Enter fullscreen mode Exit fullscreen mode

10. Install all the dependencies in this new environment:

$ poetry install
Enter fullscreen mode Exit fullscreen mode

11. Run the Flask app using Gunicorn to verify that everything is running in the new environment:

$ gunicorn --bind 0.0.0.0:5000 wsgi:app
Enter fullscreen mode Exit fullscreen mode

12. Check that your Flask app is accessible:

http://<SERVER-IP>:5000
Enter fullscreen mode Exit fullscreen mode

Flask application home page

Next Steps

  • Put Gunicorn behind a reverse proxy such as Nginx and run it as a systemd service for production deployments.
  • Add more Poetry dependency groups (for example, lint or docs) to keep tooling separate from runtime dependencies.
  • Wire the Pytest suite into a CI pipeline so tests run automatically on every push.
  • Publish the package to PyPI or a private repository once it's ready to share.

For the full guide with additional tips, visit the original article on Vultr Docs.

Top comments (0)