Deploy Chainlit applications using Docker.
Note: Chainlit does not provide an official Docker image. You can create a custom Dockerfile for your application.
FROM python:3.11-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements
COPY requirements.txt .
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY . .
# Create public directory for static assets
RUN mkdir -p public
# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV CHAINLIT_HOST=0.0.0.0
ENV CHAINLIT_PORT=8000
# Expose port
EXPOSE 8000
# Default command
CMD ["chainlit", "run", "app.py", "--host", "0.0.0.0", "--port", "8000"]
chainlit==2.10.0
python-dotenv>=1.0.0
langchain>=0.3.0
langchain-openai>=0.3.0
docker build -t chainlit-app .
docker run -d \
--name chainlit \
-e OPENAI_API_KEY="sk-your-key" \
-e CHAINLIT_AUTH_SECRET="your-secret" \
-p 8000:8000 \
-v $(pwd)/public:/app/public \
chainlit-app
version: "3.9"
services:
chainlit:
build: .
ports:
- "8000:8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- CHAINLIT_AUTH_SECRET=${CHAINLIT_AUTH_SECRET}
volumes:
- ./public:/app/public
- ./data:/app/data
restart: unless-stopped
# Create .env file
cat > .env << EOF
OPENAI_API_KEY=sk-your-key
CHAINLIT_AUTH_SECRET=your-secret-key
EOF
# Start container
docker compose up -d
# View logs
docker compose logs -f
# Stop
docker compose down
# Build stage
FROM python:3.11-slim as builder
WORKDIR /app
RUN apt-get update && apt-get install -y \
git \
build-essential \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.11-slim
WORKDIR /app
# Create non-root user
RUN useradd -m -u 1000 chainlit
# Copy from builder
COPY --from=builder /root/.local /home/chainlit/.local
COPY --chown=chainlit:chainlit . .
# Create directories
RUN mkdir -p /app/public /app/data && chown chainlit:chainlit /app/public /app/data
# Set environment
ENV PATH=/home/chainlit/.local/bin:$PATH
ENV PYTHONUNBUFFERED=1
ENV CHAINLIT_HOST=0.0.0.0
ENV CHAINLIT_PORT=8000
USER chainlit
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
EXPOSE 8000
CMD ["chainlit", "run", "app.py", "--host", "0.0.0.0", "--port", "8000"]
version: "3.9"
services:
chainlit:
build: .
ports:
- "8000:8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- CHAINLIT_AUTH_SECRET=${CHAINLIT_AUTH_SECRET}
- DATABASE_URL=postgresql://chainlit:password@postgres:5432/chainlit
depends_on:
- postgres
volumes:
- ./public:/app/public
restart: unless-stopped
postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: chainlit
POSTGRES_PASSWORD: password
POSTGRES_DB: chainlit
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
volumes:
postgres-data:
chainlit==2.10.0
python-dotenv>=1.0.0
langchain-openai>=0.3.0
psycopg2-binary>=2.9.0
version: "3.9"
services:
chainlit:
build: .
expose:
- "8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- CHAINLIT_AUTH_SECRET=${CHAINLIT_AUTH_SECRET}
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- chainlit
restart: unless-stopped
events {
worker_connections 1024;
}
http {
upstream chainlit {
server chainlit:8000;
}
server {
listen 80;
server_name _;
location / {
proxy_pass http://chainlit;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
version: "3.9"
services:
chainlit:
build: .
expose:
- "8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- CHAINLIT_AUTH_SECRET=${CHAINLIT_AUTH_SECRET}
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certbot/www:/var/www/certbot:ro
- ./certbot/conf:/etc/nginx/ssl:ro
depends_on:
- chainlit
restart: unless-stopped
certbot:
image: certbot/certbot
volumes:
- ./certbot/www:/var/www/certbot:ro
- ./certbot/conf:/etc/letsencrypt
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
apiVersion: apps/v1
kind: Deployment
metadata:
name: chainlit-deployment
spec:
replicas: 2
selector:
matchLabels:
app: chainlit
template:
metadata:
labels:
app: chainlit
spec:
containers:
- name: chainlit
image: your-registry/chainlit-app:latest
ports:
- containerPort: 8000
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: chainlit-secrets
key: openai-api-key
- name: CHAINLIT_AUTH_SECRET
valueFrom:
secretKeyRef:
name: chainlit-secrets
key: auth-secret
volumeMounts:
- name: public-volume
mountPath: /app/public
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 5
volumes:
- name: public-volume
emptyDir: {}
apiVersion: v1
kind: Service
metadata:
name: chainlit-service
spec:
selector:
app: chainlit
ports:
- protocol: TCP
port: 80
targetPort: 8000
type: LoadBalancer
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
# Check logs
docker logs chainlit
# Run interactively for debugging
docker run -it --rm chainlit-app /bin/bash
# Verify nginx configuration for WebSocket
docker exec chainlit-nginx cat /etc/nginx/nginx.conf
# Check WebSocket upgrade headers
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://localhost:8000
# Verify environment variable is set
docker exec chainlit env | grep OPENAI