Container hosting: Hugging Face Spaces with Docker#
Container platforms let you deploy applications in isolated, portable environments that include all dependencies. They’re perfect for ML applications that need custom environments, specific packages, or persistent state. Here are some common real-life uses:
- A text summarization API that processes documents using custom NLP models (runs for 10-30 seconds per request)
- An image classification tool that requires specific computer vision libraries (runs for 5-15 seconds per upload)
- A chatbot with custom fine-tuned models that need GPU acceleration (runs for 2-5 seconds per message)
Unlike serverless functions, containers can maintain state, install any packages, write to the filesystem, and run background processes. They provide more control over the environment but require more configuration.
Hugging Face Spaces hosts ML apps with free CPU runtime for public repos and paid upgrades for persistent runs or stronger hardware. It plugs into the wider Hub—models, datasets, and tokens—so you can ship demos quickly.
Spaces offer four SDKs when you create a project: Gradio (default ML demos), Streamlit (dashboards), Static HTML, and Docker for any custom stack. This guide focuses on Docker Spaces, which provide full control over runtimes and dependencies.
Setting up a Docker Space#
Sign up with Hugging Face and create a new Space. Choose “Docker” as your SDK.
Your Space repository needs these essential files:
README.md - Configure your Space with YAML frontmatter:
---
title: My FastAPI App
emoji: 🚀
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
---
# My FastAPI Application
Description of your app goes here.Dockerfile - Define your container environment (see Dockerfile documentation):
FROM python:3.11-slim
# Create the same UID (1000) that Spaces uses when running your container
RUN useradd -m -u 1000 user
# Install Python dependencies before copying the entire source tree
WORKDIR /home/user/app
COPY --chown=user requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
# Copy the rest of the app and switch to the non-root user
COPY --chown=user . .
USER user
ENV HOME=/home/user PATH=/home/user/.local/bin:$PATH
EXPOSE 7860
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]Spaces execute your container as UID 1000. Creating that user in the image avoids permission problems when the platform switches users at runtime.
requirements.txt - List your Python dependencies:
fastapi
uvicorn[standard]
transformers
torchmain.py - Your FastAPI application:
from fastapi import FastAPI
from transformers import pipeline
app = FastAPI()
# Initialize your model (this happens once when container starts)
classifier = pipeline("sentiment-analysis")
@app.get("/")
def read_root():
return {"message": "Hello from Hugging Face Spaces!"}
@app.post("/analyze")
def analyze_sentiment(text: str):
result = classifier(text)
return {"sentiment": result[0]["label"], "score": result[0]["score"]}Deployment Process#
- Create Space: Visit huggingface.co/new-space and select Docker SDK.
- Clone Repository:
git clone https://huggingface.co/spaces/your-username/your-space-name - Add Files: Create the files above in your local repository.
- Deploy:
git add .
git commit -m "Initial deployment"
git pushYour Space will automatically build and deploy. Build time depends on your base image and dependency downloads—refresh the Logs tab if the build appears stuck.
Writing Files and Data Persistence#
Docker Spaces support both temporary and persistent storage. Every Space gets 50 GB of free ephemeral disk that resets whenever the Space restarts or is paused.
Temporary Files (reset on restart):
import tempfile
import os
# Write temporary files
with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
f.write("This will be lost on restart")
temp_path = f.name
# Read it back
with open(temp_path, "r") as f:
content = f.read()Persistent Files (paid upgrade):
Upgrade to a persistent storage plan from the Space Settings tab to mount /data as durable disk. Tiers start at 20 GB for $5/month and scale up to 1 TB for $100/month. The /data volume exists only at runtime (not during Docker build).
import os
# Write to persistent storage (requires upgrade)
data_dir = "/data"
if os.path.exists(data_dir):
with open(f"{data_dir}/persistent_file.txt", "w") as f:
f.write("This persists across restarts")Using Hugging Face Hub for Data Storage (Free Alternative):
As a free alternative to persistent storage, you can programmatically upload files to a Hugging Face Dataset repository using the huggingface_hub library.
from huggingface_hub import HfApi, upload_file
# Upload files to a dataset repository for persistence
api = HfApi()
upload_file(
path_or_fileobj="local_file.json",
path_in_repo="data/saved_data.json",
repo_id="your-username/your-dataset",
repo_type="dataset",
)Environment Variables and Secrets#
Adding Variables: Go to your Space settings → Variables & secrets tab. Add environment variables and secrets that will be available in your container.
Using Variables in Code:
import os
# Access environment variables
model_name = os.environ.get("MODEL_NAME", "default-model")
api_key = os.environ.get("SECRET_API_KEY") # For secretsUsing Variables in Dockerfile:
You can expose variables at build time using the ARG directive.
# Declare build-time variables
ARG MODEL_REPO_NAME
ENV MODEL_NAME=$MODEL_REPO_NAME
# Use in your application
RUN echo "Using model: $MODEL_NAME"Advanced Features#
Hardware upgrades: By default Spaces run on the free CPU basic tier (2 vCPU, 16 GB RAM, 50 GB disk). You can switch to CPU Upgrade ($0.03/hour) or attach GPUs/TPUs such as T4, A10G, L40S, H100, and TPU v5e in the Settings → Hardware panel. See the hardware spec table for prices and memory footprints.
GPU Support: When you select GPU hardware, base your image on an NVIDIA CUDA runtime and install CUDA-ready wheels. GPU devices are injected only at runtime—skip commands like nvidia-smi during the Docker build phase.
FROM nvidia/cuda:12.1.1-runtime-ubuntu22.04Multiple Ports: Spaces expose a single public port. To serve multiple internal services, run a reverse proxy (for example Nginx or Caddy) and route everything through the exposed port defined by app_port.
RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/*
COPY nginx.conf /etc/nginx/nginx.confCustom Dependencies: Install system packages before switching away from root to avoid permission issues.
RUN apt-get update && apt-get install -y \
build-essential \
curl \
software-properties-common \
&& rm -rf /var/lib/apt/lists/*Keep persistent caches (like Hugging Face model downloads) under /data/.huggingface after enabling persistent storage and setting HF_HOME=/data/.huggingface so restarts skip re-downloading assets.
