使用 Streamlit Docker 镜像快速上线数据 App
解读
面试官抛出这道题,核心想验证三件事:
- 你是否能在国内网络环境下(镜像源、PyPI 源、企业内网 Artifactory)把 Streamlit 应用容器化;
- 镜像体积、构建速度、运行时安全是否达到生产交付标准;
- 能否把“本地能跑”一键变成“线上可灰度、可回滚、可观测”的DevOps 闭环。
如果仅回答“FROM streamlit/streamlit 然后 docker run”,会被追问“镜像 1.3 GB 怎么优化?非 root 怎么写?Swarm 怎么滚动?Secrets 怎么注入?”因此回答必须体现国内实战细节与云原生最佳实践。
知识点
- 国内加速:/etc/docker/daemon.json 配置 registry-mirrors(阿里云、腾讯云、DaoCloud),pip 换清华源,构建机缓存挂载。
- 多阶段构建:python:3.11-slim 阶段装 gcc 编译依赖,最终阶段只保留 venv 与 app,把 1.3 GB 压到 120 MB。
- 非 root 与 UID 统一:Dockerfile 里创建 uid=1000 的 app 用户,与 K8s securityContext.runAsUser 对齐,防止卷权限 777。
- requirements 冻结:pip freeze > requirements.txt 并加 --no-cache-dir,避免“本地最新版线上没有”的国内 pip 源延迟问题。
- 健康检查:HEALTHCHECK CMD curl -f http://localhost:8501/_stcore/health 或 python -m streamlit hello 探测,Swarm/K8s 就绪探针复用。
- Secrets 管理:Swarm 用 docker secret,K8s 用 sealed-secrets,本地开发用 docker-compose --env-file .env,绝不写死 AK/SK。
- 镜像仓库:企业内网 Harbor 配项目级机器人账号,开启镜像扫描与策略 webhook,阻断 CVE≥High 的镜像上线。
- CI/CD:GitLab-CI 中 docker buildx 跨平台构建,tag 用 ${CI_COMMIT_SHORT_SHA},推送后自动更新 Swarm service 或 ArgoCD 同步。
- 资源限制:--memory=512M --cpus=0.5,结合 streamlit.server.maxUploadSize=50 避免 OOM,国内 2C4G 轻量云也能跑。
- 日志与监控:stdout 输出 JSON,Filebeat 收集到阿里云 SLS,Prometheus 通过 streamlit-prometheus 暴露指标,告警直接飞书机器人。
答案
-
项目结构
streamlit-app/
├─ app.py
├─ requirements.txt
├─ .dockerignore
└─ Dockerfile -
Dockerfile(国内优化版)
# 阶段1:依赖编译
FROM registry.cn-hangzhou.aliyuncs.com/acs/python:3.11-slim as builder
RUN sed -i 's@deb.debian.org@mirrors.aliyun.com@g' /etc/apt/sources.list && \
apt-get update && apt-get install -y --no-install-recommends \
build-essential gcc g++ && rm -rf /var/lib/apt/lists/*
COPY requirements.txt /tmp/
RUN pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple --no-cache-dir -r /tmp/requirements.txt
# 阶段2:运行镜像
FROM registry.cn-hangzhou.aliyuncs.com/acs/python:3.11-slim
RUN groupadd -r appuser && useradd -r -g appuser -u 1000 -m -d /app appuser
WORKDIR /app
COPY --from=builder /root/.local /home/appuser/.local
ENV PATH=/home/appuser/.local/bin:$PATH
COPY --chown=appuser:appuser app.py .
EXPOSE 8501
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import requests,sys; sys.exit(0 if requests.get('http://localhost:8501/_stcore/health').status_code==200 else 1)"
USER appuser
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
- 构建与推送
docker buildx build --platform linux/amd64 -t harbor.mycompany.com/dataapp/streamlit-demo:1.0.0 --push .
- Swarm 部署(单命令上线)
echo $AK | docker secret create ak -
echo $SK | docker secret create sk -
docker stack deploy -c docker-compose.yml demo
docker-compose.yml 片段:
secrets:
ak:
external: true
sk:
external: true
services:
streamlit:
image: harbor.mycompany.com/dataapp/streamlit-demo:1.0.0
ports:
- "8501:8501"
environment:
AWS_ACCESS_KEY_ID_FILE: /run/secrets/ak
secrets:
- ak
- sk
deploy:
replicas: 2
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
resources:
limits:
cpus: '0.5'
memory: 512M
healthcheck:
test: ["CMD", "python", "-c", "import requests,sys; sys.exit(0 if requests.get('http://localhost:8501/_stcore/health').status_code==200 else 1)"]
interval: 30s
timeout: 3s
retries: 3
- 灰度验证
curl -I http://demo.mycompany.com:8501/_stcore/health
返回 200 后,在 Harbor 把 1.0.0 标记为“已签名”,ArgoCD 自动同步到 K8s 集群,完成零停机上线。
拓展思考
- 国内监管:如果 App 涉及个人信息,镜像里需预装国密 SM4 加密库,并在 Dockerfile 里声明 LABEL 安全责任人,满足《个人信息保护法》审计。
- 边缘场景:在工厂内网用 Docker Swarm 部署,节点通过阿里云边缘镜像加速 ACR EE 实例拉取,断网时靠本地缓存镜像继续运行。
- 成本优化:利用 Harbor 的镜像代理缓存,把公网流量降到 0;同时用 cgroup v2 的 memory.high 做弹性限流,2C4G 机器可跑 8 个副本。
- 回滚策略:在 GitLab-CI 里把旧版本镜像 tag 加 -rollback,Swarm update --rollback 可在 30 秒内完成,比 K8s 更轻量。
- 可观测性:通过 OpenTelemetry 把 Streamlit 的 st.metric 指标直接打到阿里云链路追踪 XTrace,实现“代码无侵入,问题 1 分钟定位”。