icon: LiNotebook
Title: Deploying Streamlit App as a Containerized App
Congratulations on successfully building and deploying Streamlit apps on the Streamlit Community Cloud! As you continue to develop more sophisticated applications, you might encounter challenges related to environment setup, dependency management, scalability, and reproducibility. This is where Docker comes into play. In this article, we'll delve into why Docker is a game-changer for developers, especially those working with Streamlit applications.
Before diving into Docker's benefits, it's essential to understand the pain points developers often face without it:
When developing applications, especially in teams, ensuring that every team member's development environment replicates the production environment can be challenging. Differences in operating systems, installed libraries, or versions can lead to bugs that are hard to trace.
Managing dependencies can become cumbersome. Conflicting library versions required by different projects can lead to complex and error-prone setups. Without a containerization tool, isolating these dependencies for each project is tricky.
Deploying applications across different environments (development, staging, production) often requires manual configuration, increasing the risk of human error. Ensuring consistency across these environments can be time-consuming.
As your Streamlit app grows or needs d traffic, scaling it across multiple servers or services can be daunting without a standardized deployment method.
Reproducing bugs or issues in a different environment can be difficult if the setup isn't consistent. This hampers debugging and prolongs development cycles.
✦ Now is a good time to ask, what is docker?
✦ Docker is a platform designed to make it easier to create, deploy, and run applications by using containers. Containers allow developers to package an application with all of its dependencies into a standardized unit for software development. This ensures that the application runs seamlessly in any environment, whether it's on your local machine, a colleague's laptop, or a cloud server.
At its core, Docker addresses the classic "it works on my machine" problem by providing a consistent environment across various stages of development and deployment.
✦ Docker🐳 is a container management framework, it allows you to create, share and manage images and containers.
✦ But what are containers and images in the first place and how do they allow us to solve the problem of varying development environments?
✦ You see Docker’s
logo in the image up there.
✦ It creates an isolated environment for running your application at the host machine using information (code + dependencies) from the image.
✦ With containers and images, we won’t have to worry about installing and uninstalling dependencies on a host / server, before running our application there.
Docker addresses the aforementioned challenges by providing a robust framework for containerization. Let's explore the key benefits it offers:
Using Docker, deploying a Streamlit app becomes as simple as building and running a container. Whether deploying to cloud providers like AWS, GCP, or Azure, Docker ensures that your app runs consistently across platforms.
Docker containers encapsulate an application and its environment. This means the same container can run on a developer's laptop, a testing server, or a production environment without any modifications. This uniformity eliminates discrepancies that arise from varying system configurations.
Example: Suppose you develop a Streamlit app on a Windows machine, but it needs to run on a Linux-based cloud server. Docker ensures that the app runs identically in both environments, sidestepping issues like file path differences or system-specific dependencies.
With Docker, all dependencies are defined within a Dockerfile
. This file specifies the base image, necessary libraries, environment variables, and other configurations required to run the application. The Dockerfile
ensures that anyone building the container gets the exact dependencies needed, avoiding the dreaded "dependency hell."
Docker containers are lightweight and can be easily replicated or scaled across multiple servers or services. This makes it easier to handle increased traffic or deploy microservices architectures.
Example: If your Streamlit app gains popularity and needs to handle more users, Docker allows you to spin up multiple container instances effortlessly, balancing the load with orchestration tools like Kubernetes.
Containers run in isolated environments, ensuring that applications and their dependencies do not interfere with each other. This isolation enhances security by limiting the application's access to system resources and preventing malicious code from affecting other containers or the host system.
Example: Running multiple Streamlit apps on the same server becomes safer with Docker, as each app operates within its container, reducing the risk of cross-contamination or unauthorized access.
Docker facilitates collaboration by allowing team members to share containers. This ensures that everyone works with the same environment, minimizing setup times and configuration issues.
Example: A data scientist can share a Docker image of a Streamlit app with all its dependencies, ensuring that collaborators can run and modify the app without wrestling with environment setup
To dockerize an app, you need to follow the following simple steps.
Dockerfile
(note: without any extension) at the root of our project folderDockerfile
# Use the official lightweight Python image.
# https://hub.docker.com/_/python
# This lien pecifies the base image for the Docker container
# It uses the official Python image from Docker Hub,
# specifically the version 3.12 with the "slim" variant
# which is a smaller, more lightweight version of the full Python image.
FROM python:3.12-slim
# This ensures that Python output is not buffered,
# which is useful for real-time logging and debugging.
ENV PYTHONUNBUFFERED True
# This line is needed for the app to work in CStack
RUN groupadd --gid 1001 app && useradd --uid 1001 --gid 1001 -ms /bin/bash app
# Sets the working directory for the container to `/home/app`. All subsequent commands will be run from this directory.
WORKDIR /home/app
# Copies the `requirements.txt` file from the local machine to the current working directory in the container (`/home/app`).
COPY requirements.txt ./
RUN pip install -r requirements.txt
# This line is needed for the app to work in CStack
USER 1001
# Copy local code to the container image.
# Copies all files from the local directory to the current working directory in the container (`/home/app`), and changes the ownership of the copied files
COPY --chown=app:app . ./
# (Optional) Add any additional commands here
# Run the web service on container startup.
# Informs Docker that the container will listen on port 8501 at runtime.
# This is used for documentation purposes and does not actually publish the port.
EXPOSE 8501
# Specifies the command to run when the container starts. In this case, it runs a Streamlit application using the `main.py` script.
CMD streamlit run main.py
✦ Export the versions of the installed packages from the virtual environment into a requirements.txt
pip freeze > requirements
✦ Create a .dockerignore
file at the root of our project folder
.env
filename in this file that contains our credentials like API Keysvenv
that contains all the files and Python interpreter that allow us to test the app locally..env
venv
docker build
for local development<image>
is the name of the image that we are going to builddocker build -t <image> .
✦ Run container based on build image locally
.env
file using the the pop-up dialog on Docker DesktopUpload the image to DockerHub
<username>
is your unique DockerHub username. We can find it under the pop up after you clicking on the avatar after logging in to DockerHub docker buildx build --push --platform linux/amd64 -t <username>/<image> .
--platform linux/amd64
is flag (like a parameter) to allows us to define the target platform for the Docker image. linux/amd64
specifies two things:
amd64
(x86_64) architecture. amd64
processor architecture is the most common architecture for desktop and server processors, including those from Intel and AMD.