Docker + VPS 2026 — Best Practices
2026年Docker + VPS 最佳实践
Docker Compose v2 (2026 Standard)
Docker Compose v2(2026年标准)
✅ 2026 — Docker Compose v2 (built into Docker)
✅ 2026 — Docker Compose v2(Docker内置功能)
docker compose up -d
docker compose build
docker compose logs -f service-name
docker compose up -d
docker compose build
docker compose logs -f service-name
❌ Legacy v1 (deprecated, removed in 2024)
❌ 旧版v1(已弃用,2024年已移除)
docker-compose up # hyphenated — never use
docker-compose up # 带连字符 — 切勿使用
Python Container (uv-based, 2026)
Python容器(基于uv,2026年标准)
dockerfile
FROM python:3.12-slim-bookworm
dockerfile
FROM python:3.12-slim-bookworm
Copy uv from official image — always pin the version tag
从官方镜像复制uv — 务必固定版本标签
COPY --from=ghcr.io/astral-sh/uv:0.10.7 /uv /uvx /bin/
WORKDIR /app
COPY --from=ghcr.io/astral-sh/uv:0.10.7 /uv /uvx /bin/
WORKDIR /app
Layer cache: install deps before copying app code
层缓存:复制应用代码前先安装依赖
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev
COPY . .
RUN uv sync --frozen --no-dev
ENV PATH="/app/.venv/bin:$PATH"
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev
COPY . .
RUN uv sync --frozen --no-dev
ENV PATH="/app/.venv/bin:$PATH"
Never run as root
切勿以root身份运行
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
CMD ["python", "-m", "api.main"]
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
CMD ["python", "-m", "api.main"]
Browser Automation Container (Xvfb + Camoufox)
浏览器自动化容器(Xvfb + Camoufox)
dockerfile
FROM python:3.12-slim-bookworm
COPY --from=ghcr.io/astral-sh/uv:0.10.7 /uv /uvx /bin/
dockerfile
FROM python:3.12-slim-bookworm
COPY --from=ghcr.io/astral-sh/uv:0.10.7 /uv /uvx /bin/
System deps for Firefox + virtual display
Firefox + 虚拟显示所需的系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends
xvfb x11vnc
libgtk-3-0 libdbus-glib-1-2 libxt6 libx11-xcb1
libxcomposite1 libxdamage1 libxfixes3 libxrandr2
libasound2 libpangocairo-1.0-0 libatk1.0-0
libatk-bridge2.0-0 libcups2 libdrm2 libgbm1
curl procps
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev
RUN apt-get update && apt-get install -y --no-install-recommends
xvfb x11vnc
libgtk-3-0 libdbus-glib-1-2 libxt6 libx11-xcb1
libxcomposite1 libxdamage1 libxfixes3 libxrandr2
libasound2 libpangocairo-1.0-0 libatk1.0-0
libatk-bridge2.0-0 libcups2 libdrm2 libgbm1
curl procps
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev
Download Camoufox Firefox binary
下载Camoufox Firefox二进制文件
⚠️ Verify the expected version in pyproject.toml; camoufox fetch downloads
⚠️ 请核对pyproject.toml中的预期版本;camoufox fetch会下载预编译的Firefox二进制文件
a pre-built Firefox binary — pin the camoufox package version in uv.lock
请在uv.lock中固定camoufox包的版本,尽可能校验下载哈希值。
and validate the download hash when possible.
RUN uv run python -m camoufox fetch
COPY . .
RUN uv sync --frozen --no-dev
ENV PATH="/app/.venv/bin:$PATH"
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
RUN uv run python -m camoufox fetch
COPY . .
RUN uv sync --frozen --no-dev
ENV PATH="/app/.venv/bin:$PATH"
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Docker Compose — Full Stack
Docker Compose — 全栈配置
docker-compose.yml
docker-compose.yml
services:
browser:
build:
context: ./browser
dockerfile: Dockerfile
container_name: threads-browser
restart: unless-stopped
environment:
DISPLAY: ":99"
SCREEN_RES: "1920x1080x24"
ports:
- "127.0.0.1:5900:5900" # VNC — bind to localhost only!
volumes:
- ./sessions:/sessions
- /dev/shm:/dev/shm # shared memory for Firefox
shm_size: "2gb"
api:
build:
context: ./api
container_name: threads-api
restart: unless-stopped
environment:
SESSION_DIR: /sessions
ports:
- "127.0.0.1:8000:8000" # bind to localhost only — Nginx handles external
volumes:
- ./sessions:/sessions
depends_on:
- browser
dashboard:
build:
context: ./dashboard
container_name: threads-dashboard
restart: unless-stopped
environment:
NEXT_PUBLIC_API_URL:
http://localhost:8000
ports:
- "127.0.0.1:3000:3000"
nginx:
image: nginx:1.28.2-alpine3.23 # pin stable — never use bare :alpine/:latest
container_name: threads-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/ssl:ro
services:
browser:
build:
context: ./browser
dockerfile: Dockerfile
container_name: threads-browser
restart: unless-stopped
environment:
DISPLAY: ":99"
SCREEN_RES: "1920x1080x24"
ports:
- "127.0.0.1:5900:5900" # VNC — 仅绑定到localhost!
volumes:
- ./sessions:/sessions
- /dev/shm:/dev/shm # Firefox所需的共享内存
shm_size: "2gb"
api:
build:
context: ./api
container_name: threads-api
restart: unless-stopped
environment:
SESSION_DIR: /sessions
ports:
- "127.0.0.1:8000:8000" # 仅绑定到localhost — 外部访问由Nginx转发
volumes:
- ./sessions:/sessions
depends_on:
- browser
dashboard:
build:
context: ./dashboard
container_name: threads-dashboard
restart: unless-stopped
environment:
NEXT_PUBLIC_API_URL:
http://localhost:8000
ports:
- "127.0.0.1:3000:3000"
nginx:
image: nginx:1.28.2-alpine3.23 # 固定稳定版本 — 切勿使用裸标签:alpine/:latest
container_name: threads-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/ssl:ro
Security Rules (2026)
安全规则(2026)
✅ Never expose internal services directly to internet
✅ 切勿将内部服务直接暴露到公网
ports:
- "127.0.0.1:8000:8000" # only localhost — Nginx proxies externally
ports:
- "127.0.0.1:8000:8000" # 仅本地可访问 — 由Nginx对外代理
ports:
- "8000:8000" # exposes to all interfaces
> [!CAUTION]
> The commands below **modify host-level firewall rules** and require root
> privileges. Never run them unattended in CI or automated scripts. Review
> and execute manually on the target VPS only.
```bash
ports:
> [!CAUTION]
> 以下命令**会修改主机级防火墙规则**,需要root权限。切勿在CI或自动化脚本中无人值守运行这些命令。仅在目标VPS上手动审核后执行。
```bash
UFW rules on VPS (manual — requires human review)
VPS上的UFW规则(手动执行 — 需要人工审核)
sudo ufw default deny incoming
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw deny 5900 # Block VNC from outside after first use
sudo ufw enable
sudo ufw default deny incoming
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw deny 5900 # 首次使用后禁止外部访问VNC
sudo ufw enable
yaml
volumes:
- ./sessions:/sessions # named bind mount — survives container rebuild
- /dev/shm:/dev/shm # shared memory — required for Firefox stability
yaml
volumes:
- ./sessions:/sessions # 命名绑定挂载 — 容器重建后数据仍保留
- /dev/shm:/dev/shm # 共享内存 — 保障Firefox稳定性所需
Never lose sessions: backup before any docker operations
永远不要丢失会话数据:执行任何Docker操作前先备份
tar -czf sessions-backup-$(date +%Y%m%d).tar.gz ./sessions/
tar -czf sessions-backup-$(date +%Y%m%d).tar.gz ./sessions/
Useful Commands (2026)
常用命令(2026)
Build and start all services
构建并启动所有服务
docker compose up -d --build
docker compose up -d --build
Tail logs for a specific service
查看指定服务的实时日志
docker compose logs -f browser
docker compose logs -f browser
Shell into running container
进入运行中的容器的Shell
docker exec -it threads-browser bash
docker exec -it threads-browser bash
Check resource usage
查看资源占用情况
Restart single service without rebuilding
重启单个服务无需重新构建
docker compose restart api
docker compose restart api
Full teardown (preserves volumes)
完全销毁服务(保留卷数据)
Full teardown including volumes — DANGER, deletes sessions
完全销毁服务包括卷 — 危险操作,会删除会话数据
yaml
services:
api:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
yaml
services:
api:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
.dockerignore
.dockerignore配置
.venv/
__pycache__/
*.pyc
.env
.git/
node_modules/
sessions/
*.log
.venv/
__pycache__/
*.pyc
.env
.git/
node_modules/
sessions/
*.log
❌ Never run as root in production
❌ 生产环境切勿以root身份运行
CMD ["python", "app.py"] # without USER directive — runs as root
CMD ["python", "app.py"] # 没有USER指令 — 以root身份运行
❌ Never use latest tag for base images in production
❌ 生产环境基础镜像切勿使用latest标签
❌ Never install pip packages globally in 2026 Dockerfiles
❌ 2026年的Dockerfile中切勿全局安装pip包
RUN pip install fastapi # use uv instead
RUN pip install fastapi # 请改用uv
❌ Never copy all files before installing deps (kills layer cache)
❌ 安装依赖前切勿复制所有文件(会破坏层缓存)
COPY . .
RUN uv sync # every code change invalidates dep cache
COPY . .
RUN uv sync # 每次代码变更都会使依赖缓存失效