首页/新闻资讯/正文详情

使用 Docker 与 Docker Compose 容器化部署 PostGraphile 与 PostgreSQL 实战指南

发布时间:2026/9/23 20:37:48 来源:云帆数科 栏目:资讯中心
使用 Docker 与 Docker Compose 容器化部署 PostGraphile 与 PostgreSQL 实战指南
使用 Docker 与 Docker Compose 容器化部署 PostGraphile 与 PostgreSQL 实战指南【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址: https://gitcode.com/gh_mirrors/cry/crystal本文是一份面向 V5 版本的完整 Docker 部署教程讲解如何在本机用 Docker Compose 编排一个 PostgreSQL 数据库容器和一个 PostGraphile GraphQL API 容器从环境准备、SQL 初始化脚本、Dockerfile 与graphile.config.ts配置到镜像构建、容器启动、数据库重建以及自定义wrapPlans插件的完整流程。读完本文你将能够在本机一键拉起一套论坛示例GraphQL API并理解 PostGraphile 容器化部署中连接串、端口、数据卷与插件加载的底层原理。重要提示来自官方文档本指南已针对 PostGraphile V5 更新但尚未经过完整测试。请谨慎操作并在遇到问题时反馈 issues。文中方案已在 Linux、Windows Pro、Windows Home 三种系统上开发和测试。前置要求与 Docker 安装需要准备什么本教程要求在本地工作站安装Docker与Docker Compose。Docker Compose 的价值在于它能通过配置文件一次性编排一组容器网络而不是在命令行里堆砌大量参数——当容器参数很多时命令行会变得冗长且难以阅读这正是 Compose 存在的意义。如果你已经安装 Docker Desktop for Windows它自动附带 Docker Compose无需单独安装。Linux安装 Docker 与 Docker Compose先添加 Docker 官方仓库以 Ubuntu 系为例sudo apt-get update sudo apt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository deb [archamd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable安装 Docker 社区版sudo apt-get update sudo apt-get install docker-ce将当前用户加入docker组以获取权限执行后务必重启机器sudo usermod -a -G docker username验证安装。下面的命令会自动下载hello-world镜像如果本地不存在并运行docker run hello-world验证完毕后清理该镜像docker image ls docker rmi -f hello-world接着安装 Docker Composesudo apt install docker-composeWindows Pro安装 Docker Desktop for Windows从官方渠道下载 Docker Desktop for WindowsDocker 社区版 Windows 版本按默认设置安装即可。它自带 Docker Compose。Windows Home安装 Docker Toolbox for WindowsWindows Home 无法运行 Docker Desktop 的 Hyper-V 方案可改用 Docker Toolbox for Windows同样按默认设置安装也会自动附带 Docker Compose。注意在 Windows Home 的 Docker Toolbox 环境下容器地址不再是localhost而是 Docker Machine 的 IP。可用docker-machine ip default命令获取该 IP见下文运行容器章节的地址对照表。创建 PostgreSQL 数据库容器编写.env环境变量文件在仓库根目录新建.env文件Docker 会把它作为环境变量注入容器。本教程中数据库容器用到了三个关键变量POSTGRES_DBPostgreSQL 容器启动时要创建的数据库名POSTGRES_USER数据库初始化时创建的默认管理员用户POSTGRES_PASSWORD默认管理员用户的密码。# DB # Parameters used by db container POSTGRES_DBforum_example POSTGRES_USERpostgres POSTGRES_PASSWORDchange_me建议更安全的管理方式是用 Docker Secrets 管理数据库密码避免明文写入配置文件。编写数据库初始化 SQL新建db目录存放数据库容器所需文件再在其中新建db/init子目录存放 SQL 初始化脚本。PostgreSQL 在首次初始化数据库时会按文件名的顺序依次执行init目录下的所有内容——这是官方postgres镜像的docker-entrypoint-initdb.d约定。本教程以一个简单论坛为例数据库包含user与post两张表二者是一对多关系一个用户可有多篇帖子post.author_id作为外键引用user.id。创建db/init/00-database.sql定义表结构\connect forum_example; /*Create user table in public schema*/ CREATE TABLE public.user ( id SERIAL PRIMARY KEY, username TEXT, created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE public.user IS Forum users.; /*Create post table in public schema*/ CREATE TABLE public.post ( id SERIAL PRIMARY KEY, title TEXT, body TEXT, created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, author_id INTEGER NOT NULL REFERENCES public.user(id) ); COMMENT ON TABLE public.post IS Forum posts written by a user.;再创建db/init/01-data.sql填充示例数据\connect forum_example; /*Create some dummy users*/ insert into public.user (username) values (Benjie), (Singingwolfboy), (Lexius); /*Create some dummy posts*/ insert into public.post (title, body, author_id) values (First post example, Lorem ipsum dolor sit amet, 1), (Second post example, Consectetur adipiscing elit, 2), (Third post example, Aenean blandit felis sodales, 3);编写 PostgreSQL DockerfileDockerfile 是构建 Docker 镜像的蓝图容器则由镜像创建而来。官方 PostgreSQL 镜像的 Dockerfile 极其简单。在db目录注意不是db/init下新建DockerfileFROM postgres:14-alpine COPY ./init/ /docker-entrypoint-initdb.d/第一行FROM postgres:14-alpine基于运行在 Alpine Linux 上的官方 PostgreSQL 镜像构建第二行COPY ./init/ /docker-entrypoint-initdb.d/把初始化 SQL 复制进容器内的docker-entrypoint-initdb.d目录。PostgreSQL 初始化数据库时会读取该目录并执行其中的全部内容按文件名排序。编写 Docker Compose 编排文件在仓库根目录新建docker-compose.ymlversion: 3.3 services: db: container_name: forum-example-db restart: always image: forum-example-db build: context: ./db volumes: - db:/var/lib/postgresql/data env_file: - ./.env networks: - network ports: - 5432:5432 networks: network: volumes: db:参数说明参数说明dbDocker Compose 中服务的名称。container_name容器名称。image用于运行容器的镜像名称。build提供 build context 时Docker Compose 会用 context 目录中的 Dockerfile 构建自定义镜像。context指定查找 Dockerfile 以构建镜像的目录。volumesDocker 卷与容器内 PostgreSQL 数据目录的映射格式为docker_volume:container_folder。container_folder中生成的所有文件都会写入docker_volume从而在容器停止/重启后保留数据。首次运行 db 容器时 Docker 会自动创建该卷。env_file容器环境变量配置文件的路径即上文 .env 文件。networks网络用于把一组容器归入同一网络并相互连接。ports宿主机端口与容器端口的映射格式为host_port:container_port。command容器启动后要执行的命令每个参数需单独占一个列表项。此时仓库结构应为/ ├─ db/ │ ├─ init/ │ │ ├─ 00-database.sql │ │ └─ 01-data.sql │ └─ Dockerfile ├─ .env └─ docker-compose.yml创建 PostGraphile 容器扩展环境变量添加 DATABASE_URL更新.env追加DATABASE_URLPostGraphile 将用它连接 PostgreSQL 数据库[...] # GRAPHQL # Parameters used by graphql container DATABASE_URLpostgres://postgres:change_medb:5432/forum_example注意DATABASE_URL的语法为postgres://user:passworddb:5432/db_name。其中主机名写的是db——这正是 docker-compose 中数据库服务的名称。在 Compose 创建的自定义网络network内服务名db会作为容器间可解析的 DNS 主机名因此 PostGraphile 容器无需知道数据库容器的 IP 就能连接它。创建 graphql 目录与 npm 配置新建graphql目录存放 PostGraphile 容器所需的文件。先创建package.json与其锁文件如package-lock.json安装 PostGraphile{ name: postgraphile-docker, private: true, type: module, dependencies: { postgraphile: ^5.0.0 } }注意type: module与 V5 的 ESM 生态保持一致private: true表明该包不用于发布。创建 graphile.config.ts 配置文件PostGraphile V5 采用基于 preset预设的配置体系。创建graphql/graphile.config.tsimport { PostGraphileAmberPreset } from postgraphile/presets/amber; import { makePgService } from postgraphile/adaptors/pg; export default { extends: [PostGraphileAmberPreset], pgServices: [makePgService({ connectionString: process.env.DATABASE_URL })], grafserv: { host: 0.0.0.0, port: 5678, }, };配置拆解PostGraphileAmberPresetPostGraphile V5 的官方推荐预设extends继承它即可获得全套默认行为。从源码可见它聚合了QueryQueryPlugin、PgBasicsPlugin、PgIntrospectionPlugin、PgTablesPlugin、PgAllRowsPlugin、PgRelationsPlugin、PgMutationCreatePlugin、PgMutationUpdateDeletePlugin、NodePlugin等一系列插件的顺序编排见 amber.ts并挂载SwallowErrorsPlugin统一吞并记录但不抛出操作执行中的错误makePgService来自postgraphile/adaptors/pg导出路径映射到dataplan/pg的 pg 适配器负责根据连接串创建 PostgreSQL 服务配置。其接口定义于 pgServices.tsPgAdaptor.makePgService接收connectionString等选项并返回PgServiceConfiguration。这里直接读取容器环境变量process.env.DATABASE_URL而该变量由 compose 的env_file注入grafserv.host/grafserv.portHTTP 服务监听地址与端口。0.0.0.0表示监听容器内所有网卡这样宿主机才能通过端口映射访问到容器里的服务。端口5678与后面 Dockerfile 的EXPOSE 5678以及 compose 的5678:5678相互对应。创建 PostGraphile Dockerfile在graphql目录新建DockerfileFROM node:24-alpine LABEL descriptionInstant high-performance GraphQL API for your PostgreSQL database https://github.com/graphile/postgraphile # Set app folder WORKDIR /app # Install dependencies COPY package.json package-lock.json ./ RUN npm install # Copy config and plugins COPY graphile.config.ts ./ COPY plugins ./plugins EXPOSE 5678 ENTRYPOINT [npx, --no-install, postgraphile]要点基于node:24-alpine运行 PostGraphile。仓库中 PostGraphile 的 package.json 声明engines: { node: 22 }见 package.jsonNode 24 完全满足要求先复制package.json与锁文件并npm install利用镜像分层缓存加速后续构建COPY plugins ./plugins为可选的插件目录预留挂载点插件内容见下文添加自定义插件一节EXPOSE 5678声明容器对外端口ENTRYPOINT [npx, --no-install, postgraphile]容器启动后执行 PostGraphile CLI。--no-install强制 npx 只使用本地已安装的postgraphile避免它去网络下载这正是前面必须生成package-lock.json的原因——没有锁文件时npm install可能生成不一致的依赖树也可能导致 npx 行为不可预期。从 CLI 源码cli.ts可以看到postgraphile命令会加载graphile.config.ts中的 presetloadConfig解析pgServices后通过 grafserv 创建 HTTP 服务器若未配置任何 presetCLI 会提示使用--preset postgraphile/presets/amber并退出。更新 docker-compose.yml 加入 GraphQL 服务在docker-compose.yml的services段追加graphql服务version: 3.3 services: db: [...] graphql: container_name: forum-example-graphql restart: always image: forum-example-graphql build: context: ./graphql env_file: - ./.env depends_on: - db networks: - network ports: - 5678:5678 [...]新增配置解读depends_on: - db声明 graphql 服务依赖 db 服务Compose 会先启动数据库容器再启动 GraphQL 容器两个容器共享network网络graphql 容器通过服务名db访问 PostgreSQL对应DATABASE_URL中的主机名5678:5678把容器内 5678 端口映射到宿主机 5678 端口与graphile.config.ts中的grafserv.port及 Dockerfile 的EXPOSE保持一致。此时完整仓库结构为/ ├─ db/ │ ├─ init/ │ │ ├─ 00-database.sql │ │ └─ 01-data.sql │ └─ Dockerfile ├─ graphql/ │ ├─ graphile.config.ts │ ├─ package.json │ ├─ package-lock.json │ ├─ plugins/ │ └─ Dockerfile ├─ .env └─ docker-compose.yml构建镜像并运行容器构建镜像在仓库根目录执行# Build images for all services in docker-compose.yml docker-compose build # You can also build images one by one # For instance you can build the database image like this docker-compose build db # And build the graphql image like this docker-compose build graphql运行容器# Run containers for all services in docker-compose.yml docker-compose up # Run containers as daemon (in background) docker-compose up -d # Run only the database container as daemon docker-compose up -d db # Run only the GraphQL container as daemon docker-compose up -d graphql首次运行数据库容器时Docker 会自动创建一个数据卷用于持久化数据库数据卷名自动命名为your_repository_name_db。各容器访问地址如下容器Docker on Linux / Windows ProDocker on Windows HomeGraphQL API 文档http://localhost:5678/graphiqlhttp://your_docker_machine_ip:5678/graphiqlGraphQL APIhttp://localhost:5678/graphqlhttp://your_docker_machine_ip:5678/graphqlPostgreSQL 数据库host:localhost, port:5432host:your_docker_machine_ip, port:5432若在 Windows Home 上运行 Docker Toolbox可用docker-machine ip default获取 Docker Machine 的 IP 地址。数据库重建重新初始化初始化 SQL 只在数据库卷为空时执行一次。如果你修改了db/init下的文件需要删除数据卷与数据库镜像并重建改动才会生效# Stop running containers docker-compose down # List Docker volumes docker volume ls # Delete volume docker volume rm your_repository_name_db # Delete database image to force rebuild docker rmi db # Run containers (will automatically rebuild the image) docker-compose updocker-compose up会检测到 db 镜像已不存在而自动重建数据卷删除后PostgreSQL 初始化脚本会在新卷上重新执行从而应用你修改过的 schema 与数据。添加自定义插件wrapPlans本节为可选内容演示如何包装 PostGraphile 生成的 plan 以定制行为——这正是 V5 中替代 V4 wrap resolver 的官方推荐方式对应旧版makeWrapResolversPlugin见仓库 wrap-plans.md 与 customization-overview.md。新建graphql/plugins目录并添加wrap-plans.tsimport { sideEffect } from postgraphile/grafast; import { wrapPlans } from postgraphile/utils; export default wrapPlans({ Mutation: { createUser(plan) { const $result plan(); const $user $result.get(user); sideEffect($user, (user) { console.info(Created user:, user?.username); }); return $result; }, }, });代码解析wrapPlans来自postgraphile/utils其导出路径映射到graphile-utils。它接收一个按类型名 - 字段名分组的规则对象为匹配的字段包装 plan resolver从实现上看makeWrapPlansPlugin.ts每个包装函数接收plan原始 plan resolver、$source、fieldArgs、info等参数返回替换后的 plan。wrapPlans()调用后会生成一个 PostGraphile 插件对象Mutation.createUser包装 PostGraphile 为createUser变更自动生成的 plan。先调用原始plan()拿到结果 step$result再通过$result.get(user)取出其中的user字段 step$usersideEffect来自postgraphile/grafast导出Grafast 步骤库。从源码sideEffect.ts可见它创建一个SideEffectStep该 step 将上游值逐个喂给回调函数并在构造时设置this.hasSideEffects true确保其副作用不会被 Grafast 计划优化器随意剪裁或合并allowMultipleOptimizations false。这里的回调在创建用户后把用户名打印到日志最后返回$result保持变更原有的返回结构不变只是顺带加了日志副作用。随后更新graphile.config.ts导入并注册该插件import { PostGraphileAmberPreset } from postgraphile/presets/amber; import { makePgService } from postgraphile/adaptors/pg; import WrapPlansPlugin from ./plugins/wrap-plans.ts; export default { extends: [PostGraphileAmberPreset], pgServices: [makePgService({ connectionString: process.env.DATABASE_URL })], plugins: [WrapPlansPlugin], };最后重建并重启 GraphQL 容器# Shut down containers docker-compose down # Rebuild the GraphQL container docker-compose build graphql # Rerun containers docker-compose up由于graphql/Dockerfile中有COPY plugins ./plugins插件目录会被打进镜像重建后执行createUser变更时容器终端即可看到插件打印的日志。查询与变更示例查询获取全部帖子及其作者query { allPosts { nodes { id title body userByAuthorId { username } } } }allPosts来自 Amber 预设中的PgAllRowsPluginuserByAuthorId则是PgRelationsPlugin依据post.author_id外键自动生成的关联字段——PostGraphile 会为外键关系自动生成通过作者查用户的嵌套查询入口无需手写任何 resolver。变更创建新用户mutation { createUser(input: { user: { username: Bob } }) { user { id username createdDate } } }createUser由PgMutationCreatePlugin依据user表自动生成createdDate对应created_date列V5 默认采用 camelCase 命名。执行此变更时如果已按上文加载了wrap-plans.ts插件容器日志中会打印Created user: Bob。排查与提示首次启动顺序depends_on只保证容器启动顺序PostGraphile 连接数据库通常在 db 初始化完成后才能成功若 GraphQL 容器先于数据库初始化完成就绪restart: always会让它持续重试。端口冲突宿主机 5432PostgreSQL或 5678GraphQL已被占用时可修改 compose 左侧的host_port例如5679:5678后重新docker-compose up。数据持久化与重建数据库数据存放在命名卷your_repository_name_db中需要清库重来时按上文数据库重建章节操作即可删除镜像与卷不会影响宿主机其他目录。配置文件与 CLI 的关系容器内通过npx --no-install postgraphile启动 CLICLI 会加载graphile.config.ts中的 preset你也可以直接用--preset postgraphile/presets/amber --connection 连接串 --port 5678等参数运行CLI 支持的完整选项见 cli.ts包括--connection/-c、--schema/-s、--watch/-w、--subscriptions、--allow-explain/-e等两者可以互相替代或叠加。【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址: https://gitcode.com/gh_mirrors/cry/crystal创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

五天四夜原理详解:新手避坑指南,复制代码跑不通?看这篇就通了
五天四夜原理详解:新手避坑指南,复制代码跑不通?看这篇就通了

五天四夜原理详解:新手避坑指南,复制代码跑不通?看这篇就通了 你刚把网上那段“五天四夜”的逻辑抄进项目,回车一按,终端直接报错,或者跑出来的数据全是乱码。这时候你盯着屏幕发呆,不知道是该改配置还是查依赖。别急,这就是典型的“新手避坑”场景:… · 2026/9/23 20:37:41

GD32H759+RT-Thread+DS3231 I2C实战避坑指南
GD32H759+RT-Thread+DS3231 I2C实战避坑指南

1. 为什么GD32H759的I2C驱动在RT-Thread里总“哑火”?——从硬件握手失败说起你手头刚焊好一块GD32H759核心板,接上DS3231 RTC模块,烧录RT-Thread固件后串口打印出“i2c_bus_device_init: device init failed”,或者更隐蔽的——时… · 2026/9/23 20:37:41

使用技巧2026最新
使用技巧2026最新

3个致命坑:图解原理带你搞定项目搭建 刚学完Python语法,对着空白的IDEA发呆,是不是觉得脑子很清晰但手很笨? 很多初学者卡在“代码能跑,项目建不起来”的尴尬阶段。 别慌,这很正常,因为没人教过你如何把散落的知识点拼成完整的系统。… · 2026/9/23 20:37:40

SMS中文手册实战指南:RMA2地表水模拟从网格到运行
SMS中文手册实战指南:RMA2地表水模拟从网格到运行

简介:这份《SMS中文使用手册》面向水利、水文、环境工程及地表水模拟领域的学习者与工程技术人员,用于解决SMS软件界面陌生、操作流程不熟、建模步骤难以入手等问题,适合从入门到进阶的读者系统查阅。资源为单个PDF文件,压缩包约2… · 2026/9/23 23:12:51

根号怎么打?电脑手机四种输入方法全攻略
根号怎么打?电脑手机四种输入方法全攻略

1. 为什么“打根号”看起来是个小事,却总有人卡住先说个我自己的真实经历。早几年做课件,要写一道二次根式的例题,我在键盘上找了一圈,发现符号面板里压根没有√这个键,最后只能老老实实打“根号”两个字,再… · 2026/9/23 23:12:51

区块链数据共享系统源码解析:IPFS存储+以太坊记账+ABE授权
区块链数据共享系统源码解析:IPFS存储+以太坊记账+ABE授权

简介:这套基于IPFS、Ethereum与基于属性加密(ABE)的区块链安全数据共享系统设计源码,面向区块链开发者和数据安全研究人员,适用于金融、医疗、供应链等对访问控制要求较高的场景,通过IPFS实现分布式存储&am… · 2026/9/23 23:12:32

kornia YUV 色彩转换:docstring 示例修复、测试覆盖恢复与形状校验深度解析
kornia YUV 色彩转换:docstring 示例修复、测试覆盖恢复与形状校验深度解析

计算机视觉深度学习人工智能图像处理 【免费下载链接】kornia 🐍 空间人工智能的几何计算机视觉库 项目地址: https://gitcode.com/kornia/kornia 点击查看 免费下载 kornia 在 kornia.color 模块中提供了一套完整的 YUV 色彩空间转换 API,覆… · 2026/9/23 23:12:32

K线周期规则实战:大周期定方向,小周期找买卖点
K线周期规则实战:大周期定方向,小周期找买卖点

1. 周期规则的本质:先搞清楚K线背后的时间级别做交易时间久了你会发现一个很扎心的事实:绝大多数人亏钱,不是不懂技术指标,而是把不同级别的信号混在一起用。日线刚出现买入信号,15分钟图一跌就拿不住,反过… · 2026/9/23 23:12:26

OCR识别性能评估全指南:从指标计算到多引擎选型实操
OCR识别性能评估全指南:从指标计算到多引擎选型实操

1. OCR算法识别性能评估的核心框架与选型逻辑OCR识别性能评估这件事,表面上看就是拿几张图跑一跑,看识别结果对不对。但真正做过完整评估的人都知道,这里面的坑远比想象中多。我前后参与过三轮OCR引擎的选型评估,从早期用Tesserac… · 2026/9/23 23:12:19

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码