前提条件:安装好Docker Desktop、NodeJS以及具备一定的TypeScript基础
本教程实验环境为Windows 11、NodeJS-20.15.0、Docker-27.2.0
本地部署的数据库同样可以实现,确保数据库可以成功连接即可
1. Docker部署PostgreSQL
1.1 首先创建一个空文件夹
D:\> mkdir postgresql
D:\> cd postgresql
1.2 配置Docker Compose
Docker Compose
简化了对整个应用程序堆栈的控制,使得在一个易于理解的 YAML 配置文件中轻松管理服务、网络和数据卷。 接下来我们创建配置文件来对它进行配置。
在上面创建好的空文件夹中创建配置文件docker-compose.yml
,并编辑:
services:
postgres_db: # 服务名称
image: postgres:15.7 # 指定镜像及其版本
container_name: docker_postgres # 指定容器的名称
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
POSTGRES_USER: postgres
ports: # 端口映射
- "5432:5432"
volumes: # 数据持久化的配置
- data:/var/lib/postgresql/data
- log:/var/log/postgresql
volumes: # 数据卷
data:
log:
对配置文件中属性的一些注解:
image
: 指定了要使用的 Docker 镜像及其版本。在这里,我们使用了官方的 PostgreSQL 15.7 版本镜像。为了确保系统的稳定性和兼容性,推荐使用 PostgreSQL 官方镜像的一个稳定版本而不是最新版latest
。如果没有写版本,将会默认使用最新版本latest
。
contain_name
: 容器名称。
environment
: 环境变量,可以是数据库的用户名、数据库类型和密码。
ports
: 端口。
volumes
: 数据持久化卷。这个可以保证容器被删除的情况下,数据卷中的数据不会丢失。如果不需要可以把日志数据卷去掉。很多不被使用的数据卷可能会占用很大的存储空间。
1.3 部署和验证
接下来启动Docker Compose
,它会按照配置文件来配置容器,我们已经配置了数据库镜像,所以启动后它会自动拉取Postgresql
数据库镜像并部署运行:
D:\postgresql> docker compose up -d
如果没有刚才创建的docker-compose.yml
配置文件,将会报错:
D:\postgresql> docker compose up -d
no configuration file provided: not found
部署成功显示如下:
[+] Running 1/1
[+] Running 1/2tgresql_default Created 0.1s
[+] Running 1/2tgresql_default Created 0.1s
[+] Running 1/2tgresql_default Created 0.1s
[+] Running 1/2tgresql_default Created 0.1s
[+] Running 1/2tgresql_default Created 0.1s
[+] Running 2/2tgresql_default Created 0.1s
✔ Network postgresql_default Created 0.1s
- Container docker_postgres Starting 0.6s
✔ Container docker_postgres Started 0.7s
这里我已经运行过相同指令,所以输出可能会有所不同,初次运行可能的成功结果如下:
[+] Running 15/15
✔ postgres_db Pulled 61.9s
✔ 09f376ebb190 Pull complete 8.9s
✔ 119215dfb3e3 Pull complete 2.0s
✔ 94fccb772ad3 Pull complete 10.7s
✔ 0fc3acb16548 Pull complete 8.6s
✔ d7dba7d03fe8 Pull complete 13.1s
✔ 898ae395a1ca Pull complete 12.6s
✔ 088e651df7e9 Pull complete 12.4s
✔ ed155773e5e0 Pull complete 14.2s
✔ 52df7d12fb73 Pull complete 33.4s
✔ bab1ecc22dc9 Pull complete 15.2s
✔ 1655a257a5b5 Pull complete 16.0s
✔ 978f02dfc247 Pull complete 18.0s
✔ d715d7d9aee0 Pull complete 17.8s
✔ b2e9251b2f8d Pull complete 19.8s
[+] Running 3/3
✔ Volume "postgresql_log" Created 0.0s
✔ Volume "postgresql_data" Created 0.0s
✔ Container docker_postgres Started 0.9s
接着,验证一下数据库是否在运行:
D:\postgresql>docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker_postgres postgres:15.7 "docker-entrypoint.s…" postgres_db 4 minutes ago Up 4 minutes 0.0.0.0:5432->5432/tcp
可以看到,数据库已成功部署。
2. Prisma远程操作数据库
2.1 环境配置
初始化一个 TypeScript 项目,并将 Prisma CLI 作为开发依赖项添加到其中。
D:\postgresql>npm init -y
Wrote to D:\postgresql\package.json:
{
"name": "postgresql",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}
D:\postgresql>npm install prisma typescript ts-node @types/node --save-dev
added 26 packages in 9s
这将创建一个包含 TypeScript 应用程序的初始设置的 package.json
。接着初始化TypeScirpt:
D:\postgresql> npmx tsc --init
我们可以尝试调用prisma
:
D:\postgresql> npx prisma
然后,初始化prisma
,并生成环境配置文件.env
:
D:\postgresql> npx prisma init
.env
中存放数据库的远程链接等内容。PostgreSQL的远程链接地址一般如下:
DATABASE_URL="postgresql://username:password@localhost:5432/sqlname"
记得将username
password
以及 sqlname
替换成刚才创建docker
中的配置文件中的信息docker-compose.yml
.
例如我的.env
文件内容为:(参考我的docker-compose.yml
)
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres"
2.2 创建数据库表
prisma
中数据库表用model
表示,它提供了多种属性类型等,在schema.prisma
中写入两张表,关于数据库表的属性的设计可以参考官网:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
name String
age Int
profile Profile?
}
在进行数据库映射:
D:\postgresql> npx prisma migrate dev --name init
这样操作之后,远程对数据库的更改就可以同步到我们的数据库镜像中。
2.3 增删改查 (CURD)
创建一个index.ts
文件,用来通过prisma
操作数据库:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
const user = await prisma.user.findMany();
console.log(user);
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
根据我们之前创建的两张表User
和Profile
,我们上面的操作是对User
进行了查询操作。[table].findMany()
方法是对表格的查询,请注意,根据prisma
规范,表格的名称在创建是首字母应该大写,但是对表格进行操作时,表格的名称应全部改成小写,所以在上面的代码中,prisma.user.findMany()
中的表格名称user
是小写的。
运行index.ts
文件:
D:\postgresql> npx ts-node index.ts
如果正确执行,那么会打印出一个空数组,显而易见,由于表格新创建,所以里面没有数据内容。
下面我们来写入数据库,修改index.ts
:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function addUser(){
await prisma.user.create({
data:{
name:"hi",
age: 18,
profile: {
create: {
bio: "I am a software developer"
}
}
}
})
const profile = await prisma.profile.findMany()
console.log(profile)
}
addUser()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
在上面的代码中,我们向user
写入了一个名字叫hi
、年龄为18的人,并通过绑定同时写入了profile
表格的一项bio
属性。
再次执行index.ts
,注意,我将prisma.user.findmany()
中的user
改成了profile
,所以我这次查询输出的是Profile
表格中的内容,最后的输出为:
[
{ id: 1, bio: 'I am a software developer', userId: 1 },
{ id: 2, bio: 'I am a software developer', userId: 2 },
{ id: 3, bio: 'I am a software developer', userId: 3 },
{ id: 4, bio: 'I am a software developer', userId: 4 }
]
可以看到确实向表格中插入的四条数据。
最后我们尝试来更新表格内容,更新的方法为uppublished()
,语法与上述查询和插入一样,修改main
函数:
async function main() {
const profile = await prisma.profile.uppublished({
where: { id: 1 },
data: { bio: 'I am a super satr!!!' },
})
console.log(profile)
}
我对Profile
表格使用了更新方法,在id
属性为1的位置,将bio
属性值修改成了”I am a super satr!!!”,再次运行index.ts
,最后的输出为:
[
{ id: 1, bio: 'I am a super satr!!!', userId: 1 },
{ id: 2, bio: 'I am a software developer', userId: 2 },
{ id: 3, bio: 'I am a software developer', userId: 3 },
{ id: 4, bio: 'I am a software developer', userId: 4 }
]
可以看到,数据已经成功更新到数据库中。