AgensGraph 完全指南 / 第 12 章:Docker 与容器化部署
第 12 章:Docker 与容器化部署
12.1 Docker 基础回顾
12.1.1 Docker 核心概念
| 概念 | 说明 | AgensGraph 场景 |
|---|
| Image | 只读模板 | bitnine/agensgraph:v2.13 |
| Container | 运行实例 | 正在运行的 AgensGraph 实例 |
| Volume | 持久化存储 | 数据库数据文件 |
| Network | 容器网络 | 客户端连接 |
| Compose | 多容器编排 | 完整的图数据库环境 |
12.1.2 官方镜像使用
# 拉取镜像
docker pull bitnine/agensgraph:v2.13
# 查看镜像信息
docker inspect bitnine/agensgraph:v2.13
# 快速启动
docker run -d --name ag \
-p 5432:5432 \
-e AG_PASSWORD=secret123 \
bitnine/agensgraph:v2.13
# 连接测试
docker exec -it ag agens -U agens
12.2 自定义 Dockerfile
12.2.1 基础 Dockerfile
# Dockerfile - AgensGraph 自定义镜像
FROM bitnine/agensgraph:v2.13
# 维护者信息
LABEL maintainer="admin@example.com"
# 设置环境变量
ENV AG_HOME=/home/agens/AgensGraph
ENV PGDATA=${AG_HOME}/data
ENV PATH=${AG_HOME}/bin:${PATH}
# 创建自定义配置目录
RUN mkdir -p /docker-entrypoint-initdb.d && \
mkdir -p /etc/agens
# 复制自定义配置
COPY config/agens.conf /etc/agens/agens.conf
COPY config/pg_hba.conf /etc/agens/pg_hba.conf
# 复制初始化脚本
COPY init/ /docker-entrypoint-initdb.d/
# 设置脚本权限
RUN chmod +x /docker-entrypoint-initdb.d/*.sh 2>/dev/null || true
# 数据持久化目录
VOLUME ${PGDATA}
# 暴露端口
EXPOSE 5432
# 健康检查
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD pg_isready -U agens || exit 1
# 启动命令
CMD ["postgres", "-D", "/home/agens/AgensGraph/data"]
12.2.2 生产级 Dockerfile
# Dockerfile.production
FROM bitnine/agensgraph:v2.13 AS base
LABEL maintainer="admin@example.com"
LABEL version="1.0"
LABEL description="AgensGraph Production Image"
# 安装额外工具
USER root
RUN apt-get update && apt-get install -y \
curl \
wget \
jq \
&& rm -rf /var/lib/apt/lists/*
# 复制配置文件
COPY config/postgresql.conf /etc/agens/postgresql.conf
COPY config/pg_hba.conf /etc/agens/pg_hba.conf
COPY config/setup.sh /docker-entrypoint-initdb.d/01-setup.sh
# 性能优化配置
RUN echo "kernel.shmmax = 17179869184" >> /etc/sysctl.conf
USER agens
WORKDIR /home/agens
EXPOSE 5432
VOLUME ["/home/agens/AgensGraph/data", "/var/log/agens"]
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=5 \
CMD pg_isready -U agens -d agens || exit 1
CMD ["postgres", "-D", "/home/agens/AgensGraph/data", "-c", "config_file=/etc/agens/postgresql.conf"]
12.2.3 初始化脚本
#!/bin/bash
# init/setup.sh
set -e
echo "=== AgensGraph Initialization ==="
# 创建图数据库
agens -U agens <<-EOSQL
CREATE GRAPH IF NOT EXISTS mygraph;
CREATE GRAPH IF NOT EXISTS social_network;
EOSQL
# 创建用户
agens -U agens <<-EOSQL
CREATE USER app_user WITH PASSWORD 'app_pass123';
GRANT ALL PRIVILEGES ON DATABASE agens TO app_user;
EOSQL
# 设置默认图路径
agens -U agens -d agens <<-EOSQL
ALTER DATABASE agens SET graph_path = 'mygraph';
EOSQL
echo "=== Initialization Complete ==="
-- init/02-schema.sql
-- 设置图路径
SET graph_path = mygraph;
-- 创建约束
CREATE CONSTRAINT person_name_unique
ON (p:Person)
ASSERT p.name IS UNIQUE;
-- 创建索引
CREATE INDEX ON :Person(name);
CREATE INDEX ON :Person(email);
CREATE INDEX ON :KNOWS(since);
12.3 Docker Compose 编排
12.3.1 开发环境
# docker-compose.dev.yml
version: '3.8'
services:
agensgraph:
image: bitnine/agensgraph:v2.13
container_name: agensgraph-dev
ports:
- "5432:5432"
environment:
AG_PASSWORD: dev123
AG_GRAPH_PATH: mygraph
volumes:
- ag_dev_data:/home/agens/AgensGraph/data
- ./init:/docker-entrypoint-initdb.d
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U agens"]
interval: 10s
timeout: 5s
retries: 5
# 管理界面(可选)
adminer:
image: adminer:latest
ports:
- "8080:8080"
depends_on:
agensgraph:
condition: service_healthy
volumes:
ag_dev_data:
12.3.2 生产环境
# docker-compose.prod.yml
version: '3.8'
services:
agensgraph:
build:
context: .
dockerfile: Dockerfile.production
container_name: agensgraph-prod
ports:
- "5432:5432"
environment:
AG_PASSWORD_FILE: /run/secrets/ag_password
volumes:
- ag_prod_data:/home/agens/AgensGraph/data
- ag_prod_log:/var/log/agens
- ./config/postgresql.conf:/etc/agens/postgresql.conf
- ./config/pg_hba.conf:/etc/agens/pg_hba.conf
secrets:
- ag_password
deploy:
resources:
limits:
cpus: '4.0'
memory: 8G
reservations:
cpus: '2.0'
memory: 4G
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U agens"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
# 连接池
pgbouncer:
image: edoburu/pgbouncer:latest
container_name: agens-pgbouncer
ports:
- "6432:5432"
environment:
DB_HOST: agensgraph
DB_PORT: 5432
DB_USER: agens
DB_PASSWORD: ${AG_PASSWORD}
POOL_MODE: transaction
MAX_CLIENT_CONN: 1000
DEFAULT_POOL_SIZE: 50
depends_on:
agensgraph:
condition: service_healthy
restart: always
# 监控(可选)
prometheus:
image: prom/prometheus:latest
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
restart: always
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin123
volumes:
- grafana_data:/var/lib/grafana
restart: always
volumes:
ag_prod_data:
driver: local
ag_prod_log:
driver: local
grafana_data:
driver: local
secrets:
ag_password:
file: ./secrets/ag_password.txt
12.3.3 主从复制架构
# docker-compose.repl.yml
version: '3.8'
services:
agensgraph-primary:
image: bitnine/agensgraph:v2.13
container_name: ag-primary
ports:
- "5432:5432"
environment:
AG_PASSWORD: primary_pass
volumes:
- ag_primary_data:/home/agens/AgensGraph/data
- ./config/primary.conf:/home/agens/AgensGraph/data/postgresql.conf
- ./config/pg_hba_repl.conf:/home/agens/AgensGraph/data/pg_hba.conf
command: >
postgres
-D /home/agens/AgensGraph/data
-c wal_level=replica
-c max_wal_senders=3
-c hot_standby=on
healthcheck:
test: ["CMD-SHELL", "pg_isready -U agens"]
interval: 10s
timeout: 5s
retries: 5
agensgraph-replica:
image: bitnine/agensgraph:v2.13
container_name: ag-replica
ports:
- "5433:5432"
environment:
AG_PASSWORD: replica_pass
volumes:
- ag_replica_data:/home/agens/AgensGraph/data
depends_on:
agensgraph-primary:
condition: service_healthy
command: >
bash -c "
until pg_basebackup -h agensgraph-primary -U replicator -D /tmp/base -Fp -Xs -P; do
echo 'Waiting for primary...';
sleep 5;
done;
cp -r /tmp/base/* /home/agens/AgensGraph/data/;
touch /home/agens/AgensGraph/data/standby.signal;
echo 'primary_conninfo = ''host=agensgraph-primary port=5432 user=replicator password=repl_pass''' >> /home/agens/AgensGraph/data/postgresql.conf;
postgres -D /home/agens/AgensGraph/data
"
volumes:
ag_primary_data:
ag_replica_data:
12.4 环境变量与密钥管理
12.4.1 环境变量
| 变量 | 说明 | 默认值 |
|---|
AG_PASSWORD | 超级用户密码 | (必须设置) |
AG_GRAPH_PATH | 默认图路径 | (空) |
AG_EXTRA_ARGS | 额外启动参数 | (空) |
12.4.2 Docker Secrets
# 使用 Docker Swarm Secrets
version: '3.8'
services:
agensgraph:
image: bitnine/agensgraph:v2.13
secrets:
- ag_password
environment:
AG_PASSWORD_FILE: /run/secrets/ag_password
secrets:
ag_password:
external: true
12.4.3 环境变量文件
# .env
AG_PASSWORD=secure_password_here
AG_GRAPH_PATH=mygraph
POSTGRES_MAX_CONNECTIONS=200
POSTGRES_SHARED_BUFFERS=2GB
# docker-compose.yml 使用 .env
services:
agensgraph:
env_file:
- .env
12.5 数据备份与恢复
12.5.1 备份策略
#!/bin/bash
# backup.sh - 自动备份脚本
BACKUP_DIR="/backup/agensgraph"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
CONTAINER="agensgraph-prod"
BACKUP_FILE="${BACKUP_DIR}/agens_backup_${TIMESTAMP}"
mkdir -p ${BACKUP_DIR}
# 逻辑备份(pg_dump)
docker exec ${CONTAINER} pg_dump -U agens -Fc -f /tmp/backup.dump
docker cp ${CONTAINER}:/tmp/backup.dump ${BACKUP_FILE}.dump
# 图数据备份(Cypher 导出)
docker exec ${CONTAINER} agens -U agens -c "
SET graph_path = mygraph;
MATCH (n) RETURN n;
" > ${BACKUP_FILE}_graph.json
# 压缩
gzip ${BACKUP_FILE}.dump
# 清理 7 天前的备份
find ${BACKUP_DIR} -name "*.gz" -mtime +7 -delete
echo "Backup completed: ${BACKUP_FILE}.dump.gz"
12.5.2 恢复操作
# 逻辑恢复
docker exec -i ${CONTAINER} pg_restore -U agens -d agens < backup.dump
# 物理恢复(从基础备份)
docker stop ${CONTAINER}
docker run --rm \
-v ag_prod_data:/data \
-v /backup/base:/backup \
bitnine/agensgraph:v2.13 \
bash -c "rm -rf /data/* && cp -r /backup/base/* /data/"
docker start ${CONTAINER}
12.5.3 定时备份(Cron)
# docker-compose.yml 中添加备份服务
services:
backup:
image: bitnine/agensgraph:v2.13
volumes:
- ./scripts/backup.sh:/backup.sh
- /backup:/backup
environment:
AG_HOST: agensgraph
AG_PASSWORD: ${AG_PASSWORD}
entrypoint: /bin/bash
command: >
-c "
echo '0 2 * * * /backup.sh' > /etc/cron.d/backup &&
cron -f
"
depends_on:
- agensgraph
12.6 容器监控
12.6.1 Prometheus 指标采集
# monitoring/prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'pgbouncer'
static_configs:
- targets: ['pgbouncer-exporter:9127']
# docker-compose.yml 中添加监控服务
services:
postgres-exporter:
image: prometheuscommunity/postgres-exporter:latest
environment:
DATA_SOURCE_NAME: "postgresql://agens:password@agensgraph:5432/agens?sslmode=disable"
ports:
- "9187:9187"
12.6.2 关键监控指标
| 指标 | 来源 | 告警阈值 |
|---|
| 连接数 | pg_stat_activity | > max_connections × 80% |
| 缓冲区命中率 | pg_stat_database | < 99% |
| 事务等待锁 | pg_locks | > 10 |
| 复制延迟 | pg_stat_replication | > 10s |
| 死锁数 | pg_stat_database | > 0 |
| 磁盘使用率 | 系统指标 | > 85% |
12.7 Kubernetes 部署
12.7.1 基本 Deployment
# k8s/agensgraph-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: agensgraph
namespace: database
spec:
replicas: 1
selector:
matchLabels:
app: agensgraph
template:
metadata:
labels:
app: agensgraph
spec:
containers:
- name: agensgraph
image: bitnine/agensgraph:v2.13
ports:
- containerPort: 5432
env:
- name: AG_PASSWORD
valueFrom:
secretKeyRef:
name: agensgraph-secret
key: password
volumeMounts:
- name: data
mountPath: /home/agens/AgensGraph/data
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "8Gi"
cpu: "4000m"
readinessProbe:
exec:
command:
- pg_isready
- -U
- agens
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
exec:
command:
- pg_isready
- -U
- agens
initialDelaySeconds: 30
periodSeconds: 10
volumes:
- name: data
persistentVolumeClaim:
claimName: agensgraph-pvc
---
apiVersion: v1
kind: Service
metadata:
name: agensgraph
namespace: database
spec:
selector:
app: agensgraph
ports:
- port: 5432
targetPort: 5432
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: agensgraph-pvc
namespace: database
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
12.8 本章小结
| 要点 | 说明 |
|---|
| 官方镜像 | bitnine/agensgraph:v2.13 |
| 自定义镜像 | 基于官方镜像添加配置和初始化脚本 |
| Compose | 开发/生产环境一键部署 |
| 备份 | pg_dump + 定时任务 |
| 监控 | Prometheus + Grafana + postgres_exporter |
| K8s | StatefulSet 更适合有状态服务 |
12.9 练习
- 编写一个包含 AgensGraph + PgBouncer + 监控的 Docker Compose 文件。
- 编写自动备份脚本并配置定时任务。
- 使用 Docker 构建一个包含测试数据的 AgensGraph 镜像。
- 编写 Kubernetes 的 StatefulSet 部署文件。
12.10 扩展阅读