generated from danielcgilibert/blog-template
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8aa34d9
commit 12f1ca5
Showing
2 changed files
with
148 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
148 changes: 148 additions & 0 deletions
148
src/content/blog/Containerise-Streamlit-application-and-publish-image-to-ghcr.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
--- | ||
heroImage: /src/assets/images/streamlitdocker.png | ||
category: Containers | ||
description: Containerise Streamlit application and publish image to ghcr | ||
pubDate: 2024-06-09T22:00:00.000Z | ||
draft: true | ||
tags: | ||
- docker | ||
- containers | ||
- streamlit | ||
title: 'Streamlit Containerization: A Complete Guide with Docker Best Practices' | ||
--- | ||
|
||
I needed to create a quick proof of concept (PoC) using Streamlit but had two constraints: | ||
|
||
- Self-host instead of using [Streamlit community cloud](https://streamlit.io/cloud) | ||
- Control access to the deployed website | ||
|
||
With this in mind, containerizing and hosting on Azure was the solution. This post starts a series with the list of parts below: | ||
|
||
- Part 1: Containerized Streamlit app with a blank app.py file (just add your code). You are here😊 | ||
- Part 2: GitHub workflow to build and publish the image to ghcr.io. | ||
- Part 3: Terraform code to manage infrastructure on Azure. | ||
- Part 4: GitHub workflow to execute Terraform apply & destroy infrastructure. | ||
|
||
# Prerequisite | ||
|
||
Prerequisite is Docker. Follow installation information | ||
|
||
# Docker best practices | ||
|
||
Here are the high-level best practices for building Docker images: | ||
|
||
	• Use multi-stage builds to reduce image size and improve efficiency. | ||
|
||
	• Choose the right base image from trusted sources and keep it small. | ||
|
||
	• Rebuild images frequently to incorporate updates and patches. | ||
|
||
	• Use .dockerignore to exclude unnecessary files. | ||
|
||
	• Create ephemeral containers for stateless applications. | ||
|
||
	• Avoid installing unnecessary packages to minimize the attack surface. | ||
|
||
	• Decouple applications into separate containers. | ||
|
||
	• Sort multi-line arguments for better readability. | ||
|
||
	• Leverage build cache for faster builds. | ||
|
||
	• Pin base image versions to ensure consistency. | ||
|
||
	• Integrate image build and tests in CI/CD pipelines. | ||
|
||
For detailed information, visit [Docker Building Best Practices](https://docs.docker.com/build/building/best-practices/). | ||
|
||
[https://docs.docker.com/build/building/best-practices/](https://docs.docker.com/build/building/best-practices/) | ||
|
||
[https://codefresh.io/blog/docker-anti-patterns/](https://codefresh.io/blog/docker-anti-patterns/) | ||
|
||
# Create a docker file | ||
|
||
This is the full file we will create | ||
|
||
```dockerfile | ||
FROM python:3.9-slim | ||
|
||
LABEL maintainer="Wayne Goosen" | ||
LABEL version="1.0.0" | ||
LABEL description="Streamlit template for Docker. Uses app.py as the main file." | ||
|
||
WORKDIR /app | ||
|
||
RUN apt-get update \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
COPY requirements.txt . | ||
|
||
RUN pip3 install -r requirements.txt | ||
|
||
COPY .streamlit/config.toml .streamlit/ | ||
COPY app.py . | ||
|
||
RUN groupadd -g 1005 appgroup && \ | ||
useradd -u 1005 -g appgroup appuser && \ | ||
chown -R appuser:appgroup /app | ||
|
||
EXPOSE 80 | ||
|
||
USER appuser | ||
|
||
ENTRYPOINT ["streamlit", "run"] | ||
CMD ["app.py"] | ||
``` | ||
|
||
# Dockerfile walkthrough | ||
|
||
- The base image is python:3.9-slim. | ||
- The Dockerfile creates a working directory at /app. | ||
- It updates the package lists for upgrades and new package installations. | ||
- It copies requirements.txt into the Docker image and installs the Python dependencies. | ||
- It copies app.py (the main application file) into the Docker image. | ||
- It creates a group appgroup and a user appuser with group ID and user ID 1005, respectively. It then changes the ownership of the /app directory to appuser\:appgroup. | ||
- It exposes port 8501 for the Streamlit application. | ||
- It sets appuser as the user to run the subsequent commands and the application. | ||
- The entrypoint is set to streamlit run, and the command is set to run app.py with server port 8501 and server address 0.0.0.0. | ||
|
||
# Build a docker image | ||
|
||
To build the Docker image, navigate to the directory containing the Dockerfile and run the following command: | ||
|
||
docker build -t my-streamlit-app . | ||
|
||
The -t flag is used to tag the image. Here, we have tagged the image streamlit. If you run: | ||
|
||
docker images | ||
|
||
You should see a streamlit image under the REPOSITORY column. For example: | ||
|
||
REPOSITORY TAG IMAGE ID CREATED SIZE | ||
streamlit latest 70b0759a094d About a minute ago 1.02GB | ||
|
||
# Run the docker container | ||
|
||
To run the Docker container, use the following command: | ||
|
||
docker run -p 8501:80 my-streamlit-app\:latest | ||
|
||
To view your app, users can browse to [http://0.0.0.0:8501 or http://localhost:8501](http://0.0.0.0:8501 or http://localhost:8501)[ | ||
](https://docs.docker.com/build/building/best-practices/) | ||
|
||
# Streamlit configuration | ||
|
||
Besides the config.toml (Describe this more detail) the configuration can be passed as a param: | ||
|
||
- "--server.port=8501" | ||
- "--server.address=127.0.0.1" | ||
- "--client.showErrorDetails=true" | ||
- "--client.toolbarMode=minimal" | ||
|
||
Find more configuration [here](https://docs.streamlit.io/develop/api-reference/configuration/config.toml) | ||
|
||
Part 2 coming soon.. | ||
|
||
# References | ||
|
||
- [Deploy streamlit using Docker](https://docs.streamlit.io/deploy/tutorials/docker) |