Deploy Flask to Amazon Elastic Beanstalk
Tags: aws, python, programming, tutorial
Published: 2023-03-27 10:17:01

As web developers, we are familiar with the JavaScript ecosystem web tools like React, Remix, Next, Nuxt, and so on. But with Python, we can build fully fledged web applications similar to using the frontend frameworks mentioned earlier. It would have the same functionality, allowing users to interact with the websites. 

The learning curve to using Flask is suitable for developers who want to try out a Python framework. Its minimalistic features let users integrate plugins and libraries during development with [pip](https://pypi.org/), just like [npm](https://www.npmjs.com/).

Flask uses the [Jinja template engine](https://jinja.palletsprojects.com/en/3.1.x/) to dynamically render HTML pages using placeholders by substituting them with Python syntax like variables, lists, and so on. 

This tutorial uses the Python mini-web framework, allowing developers to build scalable web applications faster.


## GitHub and Demo

The complete source code for this project is in [this repo](https://github.com/Terieyenike/flask-web-devt). Also, check out the final project [here](http://flaskwebapp-env.eba-tyv8nniy.us-east-1.elasticbeanstalk.com/).


## Prerequisites

To follow through this guide, you need to have the following:

- [Python 3](https://www.python.org/downloads/) installed on your local machine
- Understanding of basic Python 3
- [Sign up](https://portal.aws.amazon.com/billing/signup?nc2=h_ct&src=header_signup&redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation#/start/email) for a free AWS tier account


## Activating a virtual environment

The installation of Flask for this project will start with using the virtual environment **venv** to manage the dependencies both in development and production. 

Run the following command to create the virtual environment:


    python3 -m venv <name-of-project>
    
    // for example
    python3 -m venv flask-web-devt

This command creates a new folder named `flask-web-devt`. The folder structure should look something like this:


    .
    └── flask-web-devt
        ├── bin
        ├── include
        └── pyvenv.cfg

The next step is to navigate into the directory and activate the Python environment with the command based on your shell:


    source ./bin/activate

Check out the [commands to activate a virtual environment](https://docs.python.org/3/library/venv.html#how-venvs-work) like the platform and shell.

Activating the environment will prefix `flask-web-devt` in your prompt, which may look as follows:


    (flask-web-devt) (base)  ✝  ~/Desktop/flask-web-devt  

This prefix `(flask-web-devt)` indicates that the environment is currently active.


## Installing Flask

Before installing Flask, confirm if you have the `pip`, which is the required package installer for Python. Run this command:


    pip --version


    output
    pip 23.0.1 

To install Flask, run this command:


    pip install flask

Let’s confirm the installation of the Flask package:


    pip show flask


![show flask details](https://paper-attachments.dropboxusercontent.com/s_33EB96640D389C6C2617B007994D398197DF4F76CB7E98F68C480E9690CF8925_1679856095294_Screenshot+2023-03-26+at+19.41.04.jpg)



## Creating a Flask application

With the environment setup and installation complete, open the project editor in your text editor.

After that, create a new file within the root project folder `flask-web-devt`, which serves as the entry point for the application named `app.py`. 

Copy-paste this code:

```python
    from flask import Flask
    import datetime
    
    app = Flask(__name__)
    
    @app.route("/")
    def hello_world():
        current_year = datetime.datetime.now().year
        return f"The year is {current_year}"
```

In the preceding code block:

- Import the Flask class from the flask package
- Import the `datetime` module for manipulating dates and times, as this in-built when installing Python
- The instance `__name__` with the variable name app is the name of the current Python module
- Use `route()` decorator to tell Flask to trigger the HTTP response at the `hello_world()` function at the home route, /
- The function returns the message “The year is 2023” in the browser

To run the web application, type this command using the debug mode:


    flask --app app run --debug

`app`: used here is the name of the base application, `app.py`

The web application will start running on port `http://127.0.0.1:5000/`. Open and view the web page.

```bash
    * Serving Flask app 'app'
     * Debug mode: on
    WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
     * Running on http://127.0.0.1:5000
    Press CTRL+C to quit
     * Restarting with stat
     * Debugger is active!
     * Debugger PIN: 102-580-521
    127.0.0.1 - - [26/Mar/2023 19:54:38] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [26/Mar/2023 19:54:39] "GET /favicon.ico HTTP/1.1" 404 -
```


## Building the user interface

It is advisable to create your web page from scratch and make it custom, but for this project, we will use an already pre-existing template from the website, [HTML5 UP](https://html5up.net). Choose a free template and download it.

In the root project directory, create two additional folders called templates and static.

The primary use of the templates folder is to generate HTML pages, which will contain the files like `index.html` and any other page with the extension **.html** for the website. The other project folder, static, is meant to hold necessary files like the CSS for styling and JavaScript for the website's interactivity.

Copy and paste the folders, **assets** and **images** to the static folder and index.html file to the **templates** folder.

The folder structure of the **static** and **templates** folders will look something like this:


    .
    ├── static
    │   ├── assets
    │   │   ├── css
    │   │   │   ├── fontawesome-all.min.css
    │   │   │   └── main.css
    │   │   └── js
    │   │       └── main.js
    │   └── images
    │       └── pic01.jpg
    └── templates
        └── index.html

Let’s update the `app.py` file with the following:

```python
    //  app.py
    
    from flask import Flask, render_template
    import datetime
    app = Flask(__name__)
    @app.route("/")
    def hello_world():
        current_year = datetime.datetime.now().year
        return render_template("index.html", year=current_year)
```

The code snippets have some minor changes:

- `render_template`: this method is responsible for rendering the template to the browser. The first argument passed as a variable is the name of the file in the **templates** folder, and the other argument displays the current year to the template engine

That’s all to the app.py. 

**Formatting the page**
The page will only have the correct formatting once it contains the right path to the files in the index.html file.

Update the `<head>` and before the closing <body> element with this: 

```html
    // templates/index.html
    
    <!DOCTYPE html>
      ...
      <head>
        ...
        <title>Paradigm Shift by HTML5 UP</title>
        <link rel="stylesheet" href="../static/assets/css/main.css" />
        <link
          rel="shortcut icon"
          href="{{ url_for('static', filename='../static/images/rubik_cube.ico') }}" />
      </head>
      <body>
        ...
        <div class="copyright">
            {{year}} &copy; Teri. All rights reserved. Design:
            <a href="https://html5up.net">HTML5 UP</a>.
        </div>
        ...
        <script src="../static/assets/js/jquery.min.js"></script>
        <script src="../static/assets/js/jquery.scrolly.min.js"></script>
        <script src="../static/assets/js/browser.min.js"></script>
        <script src="../static/assets/js/breakpoints.min.js"></script>
        <script src="../static/assets/js/util.js"></script>
        <script src="../static/assets/js/main.js"></script>
      </body>
    </html>
```

**Note**: Include the relative path for the `<img>` element with the content in the **assets** folder to something like this for all the images, `<img src="../static/images/pic01.jpg" alt=""/>`. 

Make sure to update the images to the right one after the `/images/*.jpg`.

In the code above, another way to generate static files to the file location is to use `url_for``**(**``'static'``**,**` `filename='style.css'``**)**`, which gives the same result as `href="../static/assets/css/main.css"`.

The web page will look like this:


![paradigm shift web page](https://paper-attachments.dropboxusercontent.com/s_33EB96640D389C6C2617B007994D398197DF4F76CB7E98F68C480E9690CF8925_1679865088386_Screenshot+2023-03-25+at+19.45.53.jpg)


**Create requirements**
Before pushing the code to the remote server, let’s check the packages.
That is Elastic Beanstalk; we need the requirements.txt file.

Run the command: 


    pip freeze

This command should show the list of installed packages in the project directory. 

**Note:** If you haven’t installed any package before now, just like flask, **pip**, it should be empty.

To generate a requirements file used in the remote server environment, run this command:


    pip freeze > requirements.txt

This command generates the `requirements.txt` file and saves all your python libraries with the current version.

**Compress the files**
Compress the following files and folders in a zipped file, as this is necessary to deploy the web app in Elastic Beanstalk.

- static
- templates
- app.py
- requirements.txt


## Deploying to Elastic Beanstalk

According to the [official documentation](https://aws.amazon.com/elasticbeanstalk/), Elastic Beanstalk is a service that allows users to upload and deploy web applications in a simplified way.


![Diagram showing how AWS Elastic Beanstalk lets users create environments to upload and set up applications.](https://d1.awsstatic.com/Product-Page-Diagram_AWS-Elastic-Beanstalk%402x.6027573605a77c0e53606d5264ec7d3053bf26af.png)


**Steps to follow to deploy the app**


- In your AWS console, search for Elastic Beanstalk
- Click on Create application > Create
- Click on the Create environment button


![create environment](https://paper-attachments.dropboxusercontent.com/s_33EB96640D389C6C2617B007994D398197DF4F76CB7E98F68C480E9690CF8925_1679869657054_Screenshot+2023-03-26+at+23.26.43.jpg)



- Under the Environment tier, check the Web server information
- In the Environment information section, you can change the Domain
- Select Python as the platform and leave the other defaults for the Platform branch and version
- Select the following in the Application code section as shown below. Give the Version label a unique name



![application code](https://paper-attachments.dropboxusercontent.com/s_33EB96640D389C6C2617B007994D398197DF4F76CB7E98F68C480E9690CF8925_1679876226924_image.png)



- Select the Choose file option to upload the zipped file
- For the Configuration presets, select the Single instance (free tier)
- Click Next
- In the Configure service access section, leave the defaults
- Click Next
- Check Activated in the Instance settings > Next
- You can select Next for the optional sections
- Click Submit


## Conclusion

This article taught us how to use Elastic Beanstalk to deploy static websites using Flask. 

## Further reading
- [Flask documentation](https://flask.palletsprojects.com/en/2.2.x/)
- [Learn Python](https://docs.python.org/3/)
- [Creation of virtual environments](https://docs.python.org/3/library/venv.html#module-venv)
- [Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/)