跳转到主要内容
PocketBase.cn
部署运维 精选

Docker 部署 PocketBase 完整指南

详细介绍如何使用 Docker 容器化部署 PocketBase,包括单机部署、数据持久化、反向代理配置、以及生产环境最佳实践。

PocketBase.cn
·

目录

  1. 为什么使用 Docker
  2. 基础部署
  3. 数据持久化
  4. 反向代理配置
  5. 生产环境配置
  6. 高级配置
  7. 监控与日志
  8. 故障排查

为什么使用 Docker

Docker 部署优势

传统部署 Docker 部署
┌─────────────────┐ ┌─────────────────┐
│ 环境依赖复杂 │ │ 环境隔离 │
│ 版本冲突 │ VS │ 一致的运行环境 │
│ 迁移困难 │ │ 快速部署 │
│ 扩展不便 │ │ 容易扩展 │
│ 回滚麻烦 │ │ 快速回滚 │
└─────────────────┘ └─────────────────┘
优势说明
环境一致性开发、测试、生产环境完全一致
快速部署几秒钟启动新实例
易于扩展支持水平扩展和负载均衡
资源隔离CPU、内存、网络隔离
版本管理镜像版本化管理,支持快速回滚
安全性最小化容器,减少攻击面

基础部署

1. 快速开始

使用官方镜像

Terminal window
# 拉取最新镜像
docker pull ghcr.io/muchdogesec/pocketbase:latest
# 运行容器
docker run -d \
--name pocketbase \
-p 8090:8090 \
ghcr.io/muchdogesec/pocketbase:latest

使用国内镜像

Terminal window
# 使用阿里云镜像加速
docker pull registry.cn-hangzhou.aliyuncs.com/pocketbase/pocketbase:latest
docker run -d \
--name pocketbase \
-p 8090:8090 \
registry.cn-hangzhou.aliyuncs.com/pocketbase/pocketbase:latest

2. Docker Compose 部署

创建 docker-compose.yml

version: "3.8"
services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
container_name: pocketbase
ports:
- "8090:8090"
volumes:
- ./pb_data:/pb_data
- ./pb_public:/pb_public
restart: unless-stopped
healthcheck:
test:
["CMD", "wget", "-q", "--spider", "http://localhost:8090/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
environment:
- TZ=Asia/Shanghai

启动服务:

Terminal window
# 启动
docker-compose up -d
# 查看日志
docker-compose logs -f
# 停止
docker-compose down

3. 自定义 Dockerfile

如果需要自定义配置,创建 Dockerfile

# 使用官方镜像作为基础
FROM ghcr.io/muchdogesec/pocketbase:latest
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 创建必要的目录
RUN mkdir -p /pb_data /pb_public /pb_hooks
# 复制自定义 Hooks
COPY ./pb_hooks /pb_hooks
# 设置权限
RUN chown -R pocketbase:pocketbase /pb_data /pb_public /pb_hooks
# 切换用户
USER pocketbase
# 暴露端口
EXPOSE 8090
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD wget -q --spider http://localhost:8090/api/health || exit 1
# 启动命令
CMD ["/pocketbase", "serve", "--http=0.0.0.0:8090"]

构建和运行:

Terminal window
# 构建镜像
docker build -t my-pocketbase:latest .
# 运行容器
docker run -d \
--name pocketbase \
-p 8090:8090 \
-v $(pwd)/pb_data:/pb_data \
-v $(pwd)/pb_public:/pb_public \
my-pocketbase:latest

数据持久化

1. 理解 PocketBase 数据目录

PocketBase 容器
├── /pb_data/ # 数据库和核心数据(必须持久化)
│ ├── data.db # SQLite 数据库文件
│ └── ...
├── /pb_public/ # 公共静态文件(建议持久化)
│ └── uploads/ # 用户上传的文件
├── /pb_hooks/ # 自定义 Hooks(可选持久化)
└── /pb_migrations/ # 数据库迁移文件(可选持久化)

2. Volume 配置方式

命名 Volume(推荐用于生产)

version: "3.8"
services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
volumes:
- pb_data:/pb_data
- pb_public:/pb_public
ports:
- "8090:8090"
restart: unless-stopped
volumes:
pb_data:
driver: local
pb_public:
driver: local

绑定挂载(适合开发)

version: "3.8"
services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
volumes:
- ./data:/pb_data
- ./public:/pb_public
ports:
- "8090:8090"

3. 数据备份策略

自动备份脚本

backup.sh
#!/bin/bash
BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)
CONTAINER_NAME="pocketbase"
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 备份数据库
docker exec $CONTAINER_NAME \
wget -qO- "http://localhost:8090/api/export-database" \
> "$BACKUP_DIR/data_$DATE.db"
# 压缩备份
tar -czf "$BACKUP_DIR/backup_$DATE.tar.gz" \
-C ./data . \
-C ./public .
# 删除 7 天前的备份
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete
echo "Backup completed: backup_$DATE.tar.gz"

定时备份(Cron)

Terminal window
# 编辑 crontab
crontab -e
# 每天凌晨 2 点备份
0 2 * * * /path/to/backup.sh >> /var/log/pocketbase-backup.log 2>&1

反向代理配置

1. Nginx 配置

基础配置

upstream pocketbase {
server 127.0.0.1:8090;
keepalive 32;
}
server {
listen 80;
server_name api.yourdomain.com;
# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
# SSL 证书配置
ssl_certificate /etc/ssl/certs/yourdomain.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# 日志
access_log /var/log/nginx/pocketbase-access.log;
error_log /var/log/nginx/pocketbase-error.log;
# 上传文件大小限制
client_max_body_size 100M;
# 代理设置
location / {
proxy_pass http://pocketbase;
proxy_http_version 1.1;
# WebSocket 支持
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;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://pocketbase;
expires 30d;
add_header Cache-Control "public, immutable";
}
}

使用 Let’s Encrypt 自动证书

Terminal window
# 安装 certbot
apt install certbot python3-certbot-nginx
# 获取证书
certbot --nginx -d api.yourdomain.com
# 自动续期
certbot renew --dry-run

2. Traefik 集成

version: "3.8"
services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
volumes:
- pb_data:/pb_data
- pb_public:/pb_public
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.pocketbase.rule=Host(`api.yourdomain.com`)"
- "traefik.http.routers.pocketbase.entrypoints=websecure"
- "traefik.http.routers.pocketbase.tls.certresolver=letsencrypt"
- "traefik.http.services.pocketbase.loadbalancer.server.port=8090"
restart: unless-stopped
traefik:
image: traefik:v2.10
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=your@email.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- web
networks:
web:
external: true
volumes:
pb_data:
pb_public:

3. Caddy 配置

# Caddyfile
api.yourdomain.com {
reverse_proxy localhost:8090
# WebSocket 支持
header_up Upgrade {>Connection}
header_up Connection websocket
# 日志
log {
output file /var/log/caddy/pocketbase-access.log
}
}

生产环境配置

1. 完整生产配置

version: "3.8"
services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
container_name: pocketbase
hostname: pocketbase
ports:
- "127.0.0.1:8090:8090"
volumes:
- pb_data:/pb_data
- pb_public:/pb_public
- ./pb_hooks:/pb_hooks:ro
environment:
- TZ=Asia/Shanghai
- POCKETBASE_ENCRYPTION_KEY=${ENCRYPTION_KEY}
env_file:
- .env
restart: unless-stopped
healthcheck:
test:
["CMD", "wget", "-q", "--spider", "http://localhost:8090/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.25"
memory: 128M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- pocketbase-net
nginx:
image: nginx:alpine
container_name: pocketbase-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./nginx/logs:/var/log/nginx
depends_on:
pocketbase:
condition: service_healthy
restart: unless-stopped
networks:
- pocketbase-net
volumes:
pb_data:
driver: local
driver_opts:
type: none
o: bind
device: /opt/pocketbase/data
pb_public:
driver: local
networks:
pocketbase-net:
driver: bridge

2. 环境变量配置

创建 .env 文件:

# 时区
TZ=Asia/Shanghai
# 数据加密密钥(生产环境必须设置)
# 使用 openssl rand -base64 32 生成
POCKETBASE_ENCRYPTION_KEY=your-32-character-encryption-key
# 日志级别
LOG_LEVEL=info
# 邮件配置(用于发送通知)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=noreply@example.com
SMTP_PASS=your-smtp-password
SMTP_FROM=PocketBase <noreply@example.com>

3. 安全加固

限制容器权限

services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
pids_limit: 100
ulimits:
nproc: 512
nofile:
soft: 1024
hard: 2048

防火墙配置

Terminal window
# UFW 配置
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 8090/tcp # 仅允许本地访问
sudo ufw enable
# iptables 配置
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 8090 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 8090 -j DROP

高级配置

1. 多实例部署(负载均衡)

version: "3.8"
services:
pocketbase-1:
image: ghcr.io/muchdogesec/pocketbase:latest
volumes:
- pb_data:/pb_data
- pb_public:/pb_public
networks:
- pocketbase-net
restart: unless-stopped
pocketbase-2:
image: ghcr.io/muchdogesec/pocketbase:latest
volumes:
- pb_data:/pb_data
- pb_public:/pb_public
networks:
- pocketbase-net
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- pocketbase-1
- pocketbase-2
networks:
- pocketbase-net
volumes:
pb_data:
pb_public:
networks:
pocketbase-net:

Nginx 负载均衡配置:

upstream pocketbase_cluster {
least_conn;
server pocketbase-1:8090 max_fails=3 fail_timeout=30s;
server pocketbase-2:8090 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name api.yourdomain.com;
location / {
proxy_pass http://pocketbase_cluster;
# ... 其他配置
}
}

2. 自动重启策略

services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
restart: always # 始终重启
# restart: unless-stopped # 除非手动停止
# restart: on-failure:5 # 失败时重启,最多5次

3. 资源限制

services:
pocketbase:
deploy:
resources:
limits:
cpus: "1.0" # 最多 1 个 CPU 核心
memory: 512M # 最多 512MB 内存
reservations:
cpus: "0.25" # 保留 0.25 个 CPU 核心
memory: 128M # 保留 128MB 内存

监控与日志

1. 日志配置

services:
pocketbase:
logging:
driver: "json-file"
options:
max-size: "10m" # 单个日志文件最大 10MB
max-file: "3" # 保留 3 个日志文件
labels: "service"

2. 监控集成

Prometheus + Grafana

version: "3.8"
services:
pocketbase:
image: ghcr.io/muchdogesec/pocketbase:latest
# ... 其他配置
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
ports:
- "3000:3000"
volumes:
prometheus-data:
grafana-data:

cAdvisor(容器监控)

version: "3.8"
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8081:8080"
restart: unless-stopped

故障排查

常见问题

1. 容器无法启动

Terminal window
# 查看日志
docker logs pocketbase
# 检查端口占用
ss -tlnp | grep 8090
# 检查文件权限
ls -la ./pb_data

2. 数据丢失

Terminal window
# 检查 volume 挂载
docker inspect pocketbase | grep -A 10 Mounts
# 恢复备份
docker exec -i pocketbase \
sh -c 'cat > /pb_data/data.db' < backup/data.db

3. 性能问题

Terminal window
# 检查资源使用
docker stats pocketbase
# 检查数据库大小
docker exec pocketbase ls -lh /pb_data/
# 数据库优化
docker exec pocketbase \
sqlite3 /pb_data/data.db "VACUUM;"

健康检查脚本

health-check.sh
#!/bin/bash
CONTAINER_NAME="pocketbase"
EXPECTED_URL="http://localhost:8090/api/health"
if docker ps | grep -q $CONTAINER_NAME; then
if curl -f -s $EXPECTED_URL > /dev/null; then
echo "OK: PocketBase is healthy"
exit 0
else
echo "ERROR: PocketBase not responding"
exit 1
fi
else
echo "ERROR: Container not running"
exit 2
fi

参考资源


相关文章