Deploy Streamlit With Nginx Reverse Proxy Using Docker Compose
Deploying Streamlit applications in a production environment often involves using a reverse proxy like Nginx to handle incoming traffic, manage SSL certificates, and improve security. Docker Compose simplifies the process of setting up multi-container applications, making it an ideal tool for deploying Streamlit with Nginx. This article guides you through creating a production-ready docker-compose.yml file for your Streamlit application, complete with Nginx as a reverse proxy.
Understanding the Basics: Docker, Docker Compose, Streamlit, and Nginx
Before diving into the specifics, let's clarify the core technologies involved.
- Docker: Docker is a platform for developing, shipping, and running applications inside containers. Containers allow you to package an application with all of its dependencies, ensuring it runs consistently across different environments.
- Docker Compose: Docker Compose is a tool for defining and managing multi-container Docker applications. It uses a YAML file (
docker-compose.yml) to configure the application's services, networks, and volumes. - Streamlit: Streamlit is an open-source Python library that makes it easy to create and share custom web apps for machine learning and data science. It simplifies the process of turning data scripts into shareable web applications.
- Nginx: Nginx is a high-performance web server and reverse proxy server. In this context, Nginx acts as an intermediary between the outside world and your Streamlit application, handling incoming HTTP requests and forwarding them to the Streamlit container. This setup allows you to manage SSL/TLS certificates, load balance traffic, and add other security features.
Why Use Nginx as a Reverse Proxy with Streamlit?
Using Nginx as a reverse proxy with Streamlit offers several significant advantages for production deployments. First and foremost, Nginx can handle SSL/TLS encryption, ensuring secure communication between clients and your application. This is crucial for protecting sensitive data transmitted over the internet. Secondly, Nginx can act as a load balancer, distributing traffic across multiple Streamlit instances if needed, which improves the application's availability and responsiveness under heavy load. Additionally, Nginx provides enhanced security features, such as protection against DDoS attacks and other web vulnerabilities. It also simplifies the management of static assets, allowing you to serve static files directly from Nginx without involving the Streamlit application server. By centralizing these functions in Nginx, you can optimize the performance and security of your Streamlit deployment, making it robust and scalable for production use.
Prerequisites
Before you start, make sure you have the following installed:
- Docker: You can download and install Docker from the official Docker website.
- Docker Compose: Docker Compose typically comes bundled with Docker Desktop. If you're using Docker Engine, you may need to install Docker Compose separately. Instructions can be found on the Docker documentation.
- A Streamlit application: You should have a Streamlit application ready to deploy. If you don't have one, you can create a simple example for testing purposes.
Step-by-Step Guide: Creating the docker-compose.yml File
1. Project Structure
Start by creating a project directory for your Streamlit application and Docker Compose files. A typical project structure might look like this:
my-streamlit-app/
├── streamlit_app.py # Your Streamlit application
├── requirements.txt # Python dependencies
├── docker-compose.yml # Docker Compose configuration
└── nginx/ # Nginx configuration files
└── nginx.conf # Nginx configuration
2. Streamlit Application (streamlit_app.py)
If you don't already have a Streamlit application, create a simple one for testing:
# streamlit_app.py
import streamlit as st
st.title('Hello, Streamlit!')
st.write('This is a simple Streamlit application.')
3. Python Dependencies (requirements.txt)
List your Streamlit application's dependencies in a requirements.txt file:
streamlit
4. Nginx Configuration (nginx/nginx.conf)
Create an Nginx configuration file that acts as a reverse proxy for your Streamlit application:
# nginx/nginx.conf
upstream streamlit {
server streamlit:8501; # Streamlit service name and port
}
server {
listen 80;
server_name yourdomain.com; # Replace with your domain
location / {
proxy_pass http://streamlit; # Proxy to Streamlit upstream
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
# Add SSL configuration if needed
# listen 443 ssl;
# ssl_certificate /etc/nginx/ssl/yourdomain.crt;
# ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
}
The Nginx configuration file is crucial for setting up the reverse proxy. The upstream streamlit block defines the Streamlit service, which Nginx will forward requests to. The server block configures the Nginx server, listening on port 80 for HTTP traffic. The location / block specifies how Nginx should handle incoming requests. The proxy_pass directive tells Nginx to forward requests to the Streamlit upstream, while the proxy_set_header directives preserve the original client's IP address and host information. If you want to enable HTTPS, you would uncomment the SSL configuration lines and provide the paths to your SSL certificate and key files. Remember to replace yourdomain.com with your actual domain name and configure DNS settings accordingly.
5. Docker Compose Configuration (docker-compose.yml)
Now, create the docker-compose.yml file to define your application's services:
# docker-compose.yml
version: "3.8"
services:
streamlit:
build:
context: .
dockerfile: Dockerfile
ports:
- "8501:8501" # Streamlit port
volumes:
- .:/app
environment:
- STREAMLIT_SERVER_PORT=8501
- STREAMLIT_SERVER_ADDRESS=0.0.0.0
networks:
- app-network
nginx:
image: nginx:latest
ports:
- "80:80" # HTTP port
- "443:443" # HTTPS port (if SSL configured)
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
# - ./nginx/ssl:/etc/nginx/ssl # Uncomment if using SSL
depends_on:
- streamlit
networks:
- app-network
networks:
app-network:
driver: bridge
6. Dockerfile
Create a Dockerfile in the root of your project to define how the Streamlit application container should be built:
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8501
CMD streamlit run streamlit_app.py
7. Building and Running the Application
Open a terminal in your project directory and run the following command to build and start the application:
docker-compose up --build
This command builds the Docker images and starts the containers defined in your docker-compose.yml file. The --build flag ensures that the images are rebuilt if there are any changes to the Dockerfile or other build context files.
Once the containers are running, you can access your Streamlit application through your browser by navigating to http://yourdomain.com (or http://localhost if you're testing locally). Nginx will forward the requests to the Streamlit container.
Key Components of the docker-compose.yml File
Let's break down the key components of the docker-compose.yml file:
- Version: Specifies the version of the Docker Compose file format.
- Services: Defines the different services that make up your application.
- streamlit: This service defines the Streamlit application container.
build: Specifies the build context andDockerfileto use for building the image.ports: Maps the container port 8501 to the host port 8501, allowing external access to the Streamlit application.volumes: Mounts the current directory (.) into the container's/appdirectory, enabling code changes to be reflected in the container without rebuilding the image.environment: Sets environment variables for the Streamlit application, such as the server port and address.networks: Attaches the container to theapp-networknetwork.
- nginx: This service defines the Nginx reverse proxy container.
image: Specifies the Nginx image to use from Docker Hub.ports: Maps the host ports 80 and 443 to the container ports 80 and 443, allowing HTTP and HTTPS traffic to be routed through Nginx.volumes: Mounts the Nginx configuration file (nginx.conf) into the container and optionally mounts SSL certificate files if using HTTPS.depends_on: Specifies that the Nginx service depends on the Streamlit service, ensuring that the Streamlit container is started before Nginx.networks: Attaches the container to theapp-networknetwork.
- streamlit: This service defines the Streamlit application container.
- Networks: Defines the networks that the services will use to communicate with each other.
- app-network: A bridge network that allows the Streamlit and Nginx containers to communicate.
The Role of the Dockerfile
The Dockerfile is essential for building the Streamlit application container. It starts with a base Python image, sets the working directory inside the container, copies the requirements.txt file, and installs the Python dependencies. Then, it copies the Streamlit application code into the container, exposes port 8501, and specifies the command to run the Streamlit application. This ensures that the Streamlit application runs in a consistent and isolated environment.
Configuring SSL/TLS
To enable HTTPS, you need to configure SSL/TLS for Nginx. You can obtain SSL certificates from a Certificate Authority (CA) like Let's Encrypt. Here's how to configure SSL in your nginx.conf file:
-
Obtain SSL Certificates:
- Use Let's Encrypt or another CA to obtain SSL certificates for your domain.
-
Update
nginx.conf:- Uncomment the SSL configuration lines in your
nginx.conffile. - Specify the paths to your SSL certificate and key files.
# nginx/nginx.conf upstream streamlit { server streamlit:8501; # Streamlit service name and port } server { listen 80; server_name yourdomain.com; # Replace with your domain return 301 https://$host$request_uri; # Redirect HTTP to HTTPS } server { listen 443 ssl; server_name yourdomain.com; # Replace with your domain ssl_certificate /etc/nginx/ssl/yourdomain.crt; # Path to your SSL certificate ssl_certificate_key /etc/nginx/ssl/yourdomain.key; # Path to your SSL key location / { proxy_pass http://streamlit; # Proxy to Streamlit upstream proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; } } - Uncomment the SSL configuration lines in your
-
Mount SSL Certificates:
- Create an
nginx/ssldirectory in your project. - Place your SSL certificate and key files in this directory.
- Uncomment the SSL volume mount in your
docker-compose.ymlfile.
# docker-compose.yml version: "3.8" services: streamlit: # ... (Streamlit service configuration) nginx: # ... (Nginx service configuration) volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf - ./nginx/ssl:/etc/nginx/ssl # Uncomment if using SSL # ... - Create an
Additional Considerations for Production
1. Domain and DNS Configuration
Configuring your domain and DNS is a critical step in making your application accessible to users. You need to set up a domain name and configure DNS records to point to the IP address of your server. This involves purchasing a domain from a domain registrar and updating the DNS settings with your hosting provider. Specifically, you'll need to create an A record that maps your domain to the server's IP address. Additionally, you may want to set up a CNAME record for the www subdomain to point to your main domain. These configurations ensure that users can access your application by typing your domain name into their web browser, making it a user-friendly and professional experience.
2. Logging and Monitoring
Implement logging and monitoring to track your application's performance and identify potential issues. You can use tools like Prometheus and Grafana to monitor your application's metrics.
3. Security Best Practices
Follow security best practices to protect your application from vulnerabilities. This includes keeping your software up to date, using strong passwords, and implementing security policies.
4. Persistent Storage
If your application requires persistent storage, consider using Docker volumes or external storage solutions to store data outside of the container.
5. CI/CD Pipeline
Set up a CI/CD pipeline to automate the deployment process. This allows you to easily deploy updates to your application without manual intervention.
6. Load Balancing and Scalability
If your application experiences high traffic, consider implementing load balancing and scaling strategies to distribute traffic across multiple instances of your application.
Conclusion
Deploying Streamlit applications with Nginx as a reverse proxy using Docker Compose is an efficient and scalable way to create production-ready environments. By following this guide, you can set up a robust infrastructure that handles traffic, manages SSL certificates, and ensures the security of your Streamlit application. Remember to consider additional production considerations such as logging, monitoring, and security best practices to ensure the long-term stability and performance of your deployment.
For further information on Docker Compose and Nginx, you can refer to the official documentation: Docker Compose Documentation and Nginx Documentation.