Deploy streamlit app to aws with elastic beanstalk
Streamlit is a framework for creating data apps with python.
I’ve built a sandbox application for testing the amazon personalization engine. I use streamlit as a framework and python as a language.
After completing the job, I had to deploy to AWS. This is the way I followed.
My stack
Services
The first task is creating a docker image for streamlit application. This is the example;
FROM python:3.9-slim
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential \
curl \
software-properties-common \
git \
&& rm -rf /var/lib/apt/lists/*
COPY . /app
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip3 install -r requirements.txt
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG AWS_DEFAULT_REGION=us-west-2
ENV AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
ENV AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
ENV AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION
EXPOSE 8501
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
The only difference from the original streamlit docker image is AWS tokens. I used that tokens in my app, so I had to import them into the image.
Then I configured docker-compose.yaml file. I will use that file with elastic beanstalk.
version: "3.4"
services:
streamlit:
image: ACCOUNTID.dkr.ecr.REGION.amazonaws.com/IMAGENAME:TAG
ports:
- 80:8501
It will fetch the image from ECR with the image name. We will build our docker image and then push it to the ECR.
And the time is creating Makefile, which contains building the docker image, pushing to ECR, and updating docker-compose file shortcuts.
AWS_REGION ?= us-west-1 # its for pushing image to ecr
ECR_ENDPOINT ?= ""
IMAGE_NAME ?= "delirehberisandbox"
TS=$(shell date +'%Y%m%d%H%M%S')
TAG=${IMAGE_NAME}:v${TS}
deploy: ## Rebuild docker image with a new tag and push to ECR
docker build --build-arg AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} --build-arg AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} --build-arg AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} -t ${TAG} .
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_ENDPOINT}
docker tag ${TAG} ${ECR_ENDPOINT}/${TAG}
docker push ${ECR_ENDPOINT}/${TAG}
$(shell sed -i 's/\(^ *image: *\).*/\1${ECR_ENDPOINT}\/${TAG}/' docker-compose.yaml)
git add docker-compose.yaml
git commit -m "autocommit: image version updated"
eb deploy
.PHONY: rebuild
help: ## Show this help
@echo ${TAG}
@echo "\nSpecify a command. The choices are:\n"
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-12s\033[m %s\n", $$1, $$2}'
@echo ""
.PHONY: help
We can use the make deploy
command after that. But wait, we didn’t ready yet.
Let’s go to the AWS console with a web browser and follow these steps;
- Open the
Elastic Container Registry
->Repositories
->Create a new repository
page and give the name to the repository. It must be the sameIMAGE_NAME
variable inside Makefile. For me, itsdelirehberisandbox
- Open the
Elastic Beanstalk
->Environments
page and clickCreate new environment
button. SelectWeb Server Environment
and clickNext
. Give an application name, i gavedelirehberi
as application name. On the platform section, chooseManaged Platform
and chooseDocker
as the platform. Then click theCreate Environment
button. It will start to create environment with example code. - Open the
IAM
->Roles
page and giveAmazonEC2ContainerRegistryReadOnly
permission toaws-elasticbeanstalk-ec2-role
andaws-elasticbeanstalk-service-role
roles.
And we are closing the final steps. You have to configure AWS credentials in your local. I am using direnv to handle environment variables by folder. Create a .envrc
file in the project root.
dotenv .env
Then create a .env file and fill in the credentials;
AWS_ACCESS_KEY_ID=CHANGE
AWS_SECRET_ACCESS_KEY=CHANGE
AWS_REGION=us-west-2
ECR_ENDPOINT=ACCOUNTID.dkr.ecr.REGION.amazonaws.com
IMAGE_NAME=delirehberi
And allow to export with direnv allow
So, now we will init elasticbeanstalk in root directory. Just run eb init -p docker YOUR_APPLICATION_NAME
It will create a config.yaml file inside .elasticbeanstalk folder like this.
branch-defaults:
master:
environment: Delirehberisandbox-env
group_suffix: null
global:
application_name: delirehberi
branch: master
default_ec2_keyname: null
default_platform: Docker
default_region: us-east-2
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: null
repository: null
sc: git
workspace_type: Application
You can configure that file for your needs.
Finally, we can run make deploy
command. It will build an image, then push it to ecr, then update the docker-compose file, and then it will add changes to git history and will deploy to your elasticbeanstalk environment.