步骤 7: 设置数据库

这个会议留言本网站要收集关于会议的反馈。我们要把参会人员贡献的评论保存在一个持久存储中。

如下这个固定的数据结构可以很好地描述一条评论:留言者、电子邮箱、反馈的文字和一张可选的照片。这种类型的数据最适合存放在传统的关系型数据库中。

PostgreSQL 是我们选用的数据库。

把 PostgreSQL 添加到 Docker Compose

在我们的本地电脑上,我们决定用Docker来管理服务。创建一个 docker-compose.yaml 文件,加入 PostgreSQL 作为一个服务:

docker-compose.yaml

  1. version: '3'
  2. services:
  3. database:
  4. image: postgres:13-alpine
  5. environment:
  6. POSTGRES_USER: main
  7. POSTGRES_PASSWORD: main
  8. POSTGRES_DB: main
  9. ports: [5432]

这个步骤会安装一个 PostgreSQL 服务器,并配置一些环境变量来设置数据库名和账号密码。具体的值不重要。

我们把容器的 PostgreSQL 端口(5432)暴露给本地机器,这样它就可以连接到数据库了。

注解

在前面安装 PHP 的步骤里,pdo_pgsql 扩展应该已经装好了。

启动 Docker Compose

在后台运行 Docker Compose(使用 -d 选项):

  1. $ docker-compose up -d

先稍等一下,让数据库启动,然后检查是否一切正常:

  1. $ docker-compose ps
  2. Name Command State Ports
  3. ---------------------------------------------------------------------------------------
  4. guestbook_database_1 docker-entrypoint.sh postgres Up 0.0.0.0:32780->5432/tcp

如果没有容器在运行,或者 State 栏不是显示为 Up,检查一下Docker Compose 的日志:

  1. $ docker-compose logs

连入本地数据库

你时不时会用到 psql 这个命令行小工具。但是你需要记住数据库名以及账号密码。更加不太为人所熟悉的一点是,你还需要知道数据库运行时的本地端口。Docker 会选用一个随机端口,这样你就可以同时开发多个使用了 PostgreSQL 的项目(本地端口是 docker-compose ps 命令输出中的一部分)。

如果你在 symfony 命令里使用 psql,你就不必记住任何信息。

symfony 命令会自动检测到项目运行的 Docker 服务,它会把 psql 连接数据库所需的环境变量暴露出来。

多亏这些约定,使用 symfony run 来连接数据库方便多了。

  1. $ symfony run psql

注解

如果你在本机上没有 psql 这个二进制文件,你也可以通过 docker-compose 来运行它:

  1. $ docker-compose exec database psql main

导出和恢复数据库的数据

使用 pg_dump 来导出数据库的数据:

  1. $ symfony run pg_dump --data-only > dump.sql

并且恢复数据:

  1. $ symfony run psql < dump.sql

警告

如果你不想丢失数据,绝不要使用 docker-compose down。或者先备份一下。

在 SymfonyCloud 中加入 PostgreSQL

在 SymfonyCloud 的生产环境软件设施里,添加一个诸如 PostgreSQL 这样的服务,是通过修改 .symfony/services.yaml 这个文件来完成的,该文件目前还是空的:

.symfony/services.yaml

  1. db:
  2. type: postgresql:13
  3. disk: 1024
  4. size: S

这个 db 服务是一个 PostgreSQL 数据库(和 Docker 里的版本一样),我们会让它在一个 1GB 磁盘空间的小容器中运行。

我们也需要把数据库“链接”到应用的容器,这需要去编辑 .symfony.cloud.yaml 文件:

.symfony.cloud.yaml

  1. relationships:
  2. database: "db:postgresql"

在应用容器中,postgresql 类型的 db 服务被称为 database

最后一步是在 PHP 运行时中添加 pdo_pgsql 扩展。

.symfony.cloud.yaml

  1. runtime:
  2. extensions:
  3. - pdo_pgsql
  4. # other extensions here

这里是对 .symfony.cloud.yaml 文件改动的全部差别比对:

patch_file

  1. --- a/.symfony.cloud.yaml
  2. +++ b/.symfony.cloud.yaml
  3. @@ -4,6 +4,7 @@ type: php:7.4
  4. runtime:
  5. extensions:
  6. + - pdo_pgsql
  7. - apcu
  8. - mbstring
  9. - sodium
  10. @@ -21,6 +22,9 @@ build:
  11. disk: 512
  12. +relationships:
  13. + database: "db:postgresql"
  14. +
  15. web:
  16. locations:
  17. "/":

提交这些改变,然后重新部署到 SymfonyCloud:

  1. $ git add .
  2. $ git commit -m'Configuring the database'
  3. $ symfony deploy

连入 SymfonyCloud 数据库

现在 PostgreSQL 在本地借助 Docker 运行,同时也在 SymfonyCloud 的生产环境中运行。

正如我们所见,运行 symfony run psql 会自动连接到 Docker 里的数据库,这要归功于 symfony run 暴露出的环境变量。

如果你想要连接到生产环境容器中的 PostgreSQL,你需要打开一个 SSH 隧道来接通你的本地电脑和 SymfonyCloud 平台设施:

  1. $ symfony tunnel:open --expose-env-vars

默认情况下,SymfonyCloud 服务不会在你的本地电脑上以环境变量暴露出来。要想把它们暴露出来,你必须明确设置 --expose-env-vars 选项。为什么要这样呢?连接到生产数据库是一个危险的操作。你可能会破坏 真实的 数据。强制设置那个选项,是要你确认这 的确是 你想要做的操作。

现在,用 symfony run psql 连接到远程的 PostgreSQL 服务器,和以前一样:

  1. $ symfony run psql

连接完后,不要忘了关掉隧道:

  1. $ symfony tunnel:close

小技巧

如果要在生产数据库上直接运行一些 SQL 语句,而不是获得一个 shell,你可以用 symfony sql 命令。

暴露环境变量

借助于环境变量,Docker Compose 和 SymfonyCloud 可以和 Symfony 无缝对接。

执行 symfony var:export 可以查看 symfony 暴露出的所有环境变量:

  1. $ symfony var:export
  2. PGHOST=127.0.0.1
  3. PGPORT=32781
  4. PGDATABASE=main
  5. PGUSER=main
  6. PGPASSWORD=main
  7. # ...

psql 小工具会读取 PG* 形式的环境变量。那其它环境变量呢?

如果一条隧道设置了 --expose-env-vars 选项并且连接到了 SymfonyCloud,那么 var:export 命令就会返回远程的环境变量:

  1. $ symfony tunnel:open --expose-env-vars
  2. $ symfony var:export
  3. $ symfony tunnel:close

描述你的基础设施

你可能还没意识到,把基础设施信息存储在文件中,并和代码放在一起,会有很多好处。Docker 和 SymfonyCloud 用配置文件来描述项目的基础设施。当一个新功能需要一个额外服务时,代码的改动和基础设施信息的改动会来自同一个补丁。

深入学习


This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.