Server Containerization and Deployment 1

Stanley Ocran
5 min readJul 29, 2022

--

The objective of this 2 part article is a walkthrough of a project I recently took up. This project is a culmination of the various cloud and web development skills I’ve obtained. In this project I will demonstrate how to containerize a simple flask app in docker, deploy that container on EKS (Elastic Kubernetes Service) and then create a CI/CD pipeline to automate the majority of the deployment activities. Following along will enable you to associate one end of a pipeline to your GitHub repository, and connect the other end to an EKS cluster. I will do all this programmatically using code (CloudFormation template file) that I will make available.

Overview

The application code for the Flask app is hosted on GitHub. As soon as a commit happens in the GitHub repository, it will trigger the CodeBuild. This step requires connecting your GitHub account to the AWS CodeBuild service using a GitHub access token. CodeBuild will build a new image for your application, and push it to a container registry. The CodePipeline service will then automatically deploy the application image to your Kubernetes cluster. After which your Kubernetes cluster will start serving the application endpoints.

Above is an architecture diagram of the entire project flow. First, you will get familiar with the Flask app by running it locally.

Prerequisites

  • Docker Desktop — Installation instructions can be found here.
  • Git: See the download instructions here.
  • Code editor: You can download and install VS code here.
  • AWS Account
  • Python version between 3.7 and 3.9. Check your current version using:
python --version

You can download a specific release version from here.

Mac/Linux users can use the default terminal. Windows users can use either the GitBash terminal or WSL.

Command line utilities:

  • AWS CLI: Installation instructions can be found here. AWS CLI should be configured using the aws configure command. Important: Do not use the us-east-1 because the EKS cluster creation may fail in us-east-1 mostly. Change the default region to us-east-2:
aws configure set region us-east-2
  • EKSCTL: Installation instructions can be found here or here to download and install eksctl utility.
  • KUBECTL: Installation instructions can be found here.

Locally clone the GitHub repo to gain access to the files.

git clone https://github.com/stanocran/Server-Deployment-and-Containerization.git

The Flask app that will be used for this project consists of a simple API with three endpoints:

  1. GET '/': This is a simple health check, which returns the response 'Healthy'.
  2. POST '/auth': This takes an email and password as json arguments and returns a JWT based on a custom secret.
  3. GET '/contents': This requires a valid JWT (JSON Web Token), and returns the decrypted contents of that token.

The app relies on a secret set as the environment variable JWT_SECRET to produce a JWT (JSON Web Token).

Containerize the Flask App and Run Locally

The following steps describe how to complete the Dockerization part of the project. After you complete these steps, you should have the Flask application up and running in a Docker container.

Store Environment Variables
Containers cannot read the values stored in your localhost’s environment variables. Therefore, create a file named .env_file and save both JWT_SECRET and LOG_LEVEL into that .env_file. We will use this file while creating the container.

JWT_SECRET='myjwtsecret'
LOG_LEVEL=DEBUG

This .env_file is only for the purposes of testing the container locally, you do not want to push it into the Github or other public repositories. You can prevent this by adding it to your .gitignore file, which will cause git to ignore it. To safely store and use secrets in the cloud, we will use a secure solution such as AWS’s parameter store.

Start the Docker Desktop service.

Build a local Docker image, by running the commands below from the directory where the Dockerfile resides:

docker build -t myimage .

Other useful commands you can try are:

# Check the list of images
docker image ls
# Remove any image
docker image rm <image_id>

Once the image has been built we proceed to use that image to create and run a container locally (on your desktop).

docker run --name myContainer --env-file=.env_file -p 80:8080 myimage

The command above is doing a few things, it is passing the name of the env file you created using the flag --env-file=<YOUR_ENV_FILENAME>. It is also exposing the port 8080 of the container to port 80 on your host machine.

Other useful commands you can try are:

# List running containers
docker container ls
docker ps
# Stop a container
docker container stop <container_id>
# Remove a container
docker container rm <container_id>

Check the endpoints

To use the endpoints, you can use the curl commands on port 80. Open a new terminal window, and try the following command:

# Flask server running inside a container
curl --request GET 'http://localhost:80/'

or check http://localhost:80/ in the browser. You should see a “Healthy” response. This is enough to verify that everything works as intended. If you want to try the full range of endpoints try these commands:

# Calls the endpoint 'localhost:80/auth' with the email/password as the message body. export TOKEN=`curl --data '{"email":"abc@xyz.com","password":"WindowsPwd"}' --header "Content-Type: application/json" -X POST localhost:80/auth  | jq -r '.token'`# The return JWT token assigned to the environment variable 'TOKEN'
echo $TOKEN
# Decrypt the token and returns its content
curl --request GET 'http://localhost:80/contents' -H "Authorization: Bearer ${TOKEN}" | jq .

This concludes testing the app in the container locally. This brings us to the end of Part 1. Next we run the app on AWS Cloud.

You can buy me a coffee too if you find this helpful.

--

--

Stanley Ocran

junior web dev, cloud practitioner and all things between.