In this article, I'll share my experience building a paginated transaction API that synchronizes blockchain events to a PostgreSQL database using Next.js and Prisma. Here's what we'll cover:
Architecture Overview
Client <-> API Routes <-> TransactionService (将数据存储到db)<-> Blockchain
The system follows a clean architecture pattern:
- Client Layer: Frontend interface that displays transaction data
- API Routes: Next.js API endpoints handling HTTP requests
- Service Layer: TransactionService managing business logic and blockchain interactions
- Data Layer: PostgreSQL database with Prisma ORM
Key Components
1. Database Schema
We use Prisma to define our data models:
- Transaction: Stores transaction details including status and signatures
- Signature: Records signature information for each transaction
- SyncStatus: Tracks blockchain synchronization progress,会通过第三方库node-cron设置定时任务
2. Blockchain Event Synchronization
The system maintains synchronization with the blockchain through:
- Incremental syncing from the last processed block
- Event filtering and processing
- Automatic status updates based on signature collection
3. API Implementation
The API supports flexible querying with:
- Pagination parameters (page, pageSize)
- Status filtering (CREATED, SIGNED, ACTIVATED)
Deployment
The application is containerized using Docker Compose, which manages:
- Application container with Next.js
- PostgreSQL database container
- Volume persistence for data storage使用volume amount
遇到的bug
数据从区块链上同步之后没有存储到db
从链上同步到数据库是在 TransactionService 的 syncEvents 方法中完成的
每次调用API如果上次已经从区块链拿到 有缓存 所以这次拿不到events
因为 syncEvents 方法会从上次同步的区块高度开始同步:
// 1. 获取上次同步的区块高度
const lastSync = await prisma.syncStatus.findFirst({
orderBy: { id: 'desc' },
});
const fromBlock = lastSync ? lastSync.blockNumber + 1n : 0n;
// 2. 获取当前区块高度
const currentBlock = await this.provider.getBlockNumber();
解决方法:不用事务,直接存储从合约来的events(work around),同时清除Sync表重新同步
更改schema后的数据同步
# 生成 Prisma 客户端
pnpm prisma generate --schema src/db/schema.prisma
# 运行数据库迁移
pnpm prisma migrate deploy --schema src/db/schema.prisma
# 启动开发服务器
pnpm run dev
需要在 Transaction 模型中添加 blockNumber 字段
首先更新 Prisma schema
然后在 TransactionService 中记录区块高度:
// 处理创建事件
for (const event of createdEvents) {
const decodedLog = this.contract.interface.parseLog(event);
const msgHash = this.calculateMsgHash(decodedLog);
const block = await event.getBlock();
await prisma.transaction.upsert({
where: { msgHash },
create: {
msgHash,
amount: ethers.formatUnits(decodedLog.args[2], 8),
creator: 'xxx',
target: decodedLog.args[1].toLowerCase(),
createdAt: new Date(Number(block.timestamp) * 1000),
status: TxStatus.CREATED,
nonce: decodedLog.args[3],
blockNumber: BigInt(block.number) // 存储区块高度
},
update: {}
});
}
最后更新 TypeScript 接口
并运行数据库迁移:
npx prisma migrate dev --name add_block_number
没有过滤到actived事件
需要在api/route.ts:
从 URL 参数中获取 status
- 从 URL 参数中获取 status
- 根据是否有 status 参数构建不同的查询条件
- 在 prisma 查询中使用这个条件
Awesome🌸
在更新数据库的时候,Invalid prisma.signature.upsert() invocation:,
Unknown argument msgHash. Available options are marked with ?.:
before
create: {
role,
msgHash, // 这里直接设置了 msgHash//去掉这一行即可
transaction: {
connect: { msgHash } // 同时又在这里通过关系设置了 msgHash
}
Error processing signature event: PrismaClientValidationError:
Invalid `prisma.signature.upsert()` invocation:
{
where: {
msgHash_role: {
msgHash: "0x01efc3d02651ab89e47f4aa3029c4e4201dde1abc4c78a4f215f286222f3e1a2",
role: "xxx"
}
},
create: {
role: "xxx",
msgHash: "0x01efc3d02651ab89e47f4aa3029c4e4201dde1abc4c78a4f215f286222f3e1a2",
~~~~~~~
transaction: {
connect: {
msgHash: "0x01efc3d02651ab89e47f4aa3029c4e4201dde1abc4c78a4f215f286222f3e1a2"
}
},
? id?: String,
? signedAt?: DateTime
},
update: {}
}
这导致了 Prisma 的验证错误,因为 msgHash 是一个关系字段,不应该直接设置。我们之前的修改移除了直接设置的 msgHash,只保留了通过关系设置的方式,这样就解决了这个问题。
docker-compose.yaml和dockerfile的区别?
Dockerfile
单个容器的构建说明
用于构建单个容器的镜像
- 定义如何构建应用程序
- 包含应用程序的环境、依赖和启动命令
docker-compose.yaml
多个容器的配置和关系
- 配置容器之间的关系
- 管理网络、卷、环境变量等
- 简化部署过程
主要区别
-
范围
- Dockerfile: 单个容器
- docker-compose: 多个容器的整体应用
-
用途
- Dockerfile: 构建镜像
- docker-compose: 编排容器
-
Error response from daemon: pull access denied
koki@kokideMacBook-Air learn_project % docker pull registry.cn-hangzhou.aliyuncs.com/library/postgres:alpine What's next: View a summary of image vulnerabilities and recommendations → docker scout quickview registr View a summary of image vulnerabilities and recommendations → docker scout quickview registry.cn-hangzhou.aliyuncs.com/library/postgres:alpine Error response from daemon: pull access denied for registry.cn-hangzhou.aliyuncs.com/library/pos Error response from daemon: pull access denied for registry.cn-hangzhou.aliyuncs.com/library/postgres, repository does not exist or may require 'docker login': denied: requested access to the Error response from daemon: pull access denied for registry.cn-hangzhou.aliyuncs.com/library/postgres, repository does not exist or may require 'docker login': denied: requested access to the resource is denied解决方法:手动拉取官方镜像postgres:14-alpine
-
单位问题导致的函数调用问题
单位的问题:一开始使用了ethers.parseEther
ethers.parseEther 和 ethers.parseUnits 的主要区别在于:
// parseEther 固定使用 18 位精度(以太坊主币的精度) ethers.parseEther("1.0") // 1000000000000000000n (18位小数) ethers.parseEther("2.5") // 2500000000000000000n// parseUnits 可以指定任意精度 ethers.parseUnits("1.0", 8) // 100000000n (8位小数) ethers.parseUnits("1.0", 6) // 1000000n (6位小数) -
前端的时间显示
Postgres不能存储locale时间类型,只能是unix类型,所以需要在前端修改时间的格式
const formatLocalTime = (utcTime: string) => { const date = new Date(utcTime); return date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); }; export default formatLocalTime;
部署
-
接口请求经过了7890端口
koki@debian:~/learn_project$ docker logs -f learn_project npm error code ECONNREFUSED npm error syscall connect npm error errno ECONNREFUSED npm error FetchError: request to <https://registry.npmmirror.com/pnpm> failed, reason: connect ECONNREFUSED 127.0.0.1:7890 npm error at ClientRequest.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/minipass-fetch/lib/index.js:130:14) npm error at ClientRequest.emit (node:events:518:28) npm error at emitErrorEvent (node:_http_client:101:11) npm error at _destroy (node:_http_client:884:9) npm error at onSocketNT (node:_http_client:904:5) npm error at process.processTicksAndRejections (node:internal/process/task_queues:83:21) { npm error code: 'ECONNREFUSED', npm error errno: 'ECONNREFUSED', npm error syscall: 'connect', npm error address: '127.0.0.1', npm error port: 7890, npm error type: 'system', npm error requiredBy: '.' npm error } npm error npm error If you are behind a proxy, please make sure that the npm error 'proxy' config is set properly. See: 'npm help config' npm error A complete log of this run can be found in: /root/.npm/_logs/2024-12-10T08_44_56_797Z-debug-0.log尝试在docker-compose.yml里面
version: "3.8" services: app: build: context: . dockerfile: Dockerfile image: learn_project:latest container_name: learn_project ports: - "18887:3000" environment://新增环境变量 - DATABASE_URL=postgresql://gdst:gdst@db:5432/gdst_db - HTTP_PROXY="" - HTTPS_PROXY="" - NO_PROXY="*"仍然
尝试直接在命令行 不是在容器内
unset http_proxy unset https_proxy unset HTTP_PROXY unset HTTPS_PROXY仍然
使用命令:来临时去掉代理
env -u http_proxy -u https_proxy docker-compose upRecreating gdst_db ... done Recreating learn_project ... done Attaching to gdst_db, learn_project gdst_db | gdst_db | PostgreSQL Database directory appears to contain a database; Skipping initialization gdst_db | gdst_db | 2024-12-10 09:15:10.486 UTC [1] LOG: starting PostgreSQL 14.15 on x86_64-pc-linux-musl, compiled by gcc (Alpine 14.2.0) 14.2.0, 64-bit gdst_db | 2024-12-10 09:15:10.486 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 gdst_db | 2024-12-10 09:15:10.486 UTC [1] LOG: listening on IPv6 address "::", port 5432 gdst_db | 2024-12-10 09:15:10.497 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" gdst_db | 2024-12-10 09:15:10.503 UTC [27] LOG: database system was shut down at 2024-12-10 09:15:09 UTC gdst_db | 2024-12-10 09:15:10.508 UTC [1] LOG: database system is ready to accept connections learn_project | npm error code ECONNREFUSED learn_project | npm error syscall connect learn_project | npm error errno ECONNREFUSED learn_project | npm error FetchError: request to <https://registry.npmmirror.com/pnpm> failed, reason: connect ECONNREFUSED 127.0.0.1:7890 learn_project | npm error at ClientRequest.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/minipass-fetch/lib/index.js:130:14) learn_project | npm error at ClientRequest.emit (node:events:518:28) learn_project | npm error at emitErrorEvent (node:_http_client:101:11) learn_project | npm error at _destroy (node:_http_client:884:9) learn_project | npm error at onSocketNT (node:_http_client:904:5) learn_project | npm error at process.processTicksAndRejections (node:internal/process/task_queues:83:21) { learn_project | npm error code: 'ECONNREFUSED', learn_project | npm error errno: 'ECONNREFUSED', learn_project | npm error syscall: 'connect', learn_project | npm error address: '127.0.0.1', learn_project | npm error port: 7890, learn_project | npm error type: 'system', learn_project | npm error requiredBy: '.' learn_project | npm error } learn_project | npm error learn_project | npm error If you are behind a proxy, please make sure that the learn_project | npm error 'proxy' config is set properly. See: 'npm help config' learn_project | npm error A complete log of this run can be found in: /root/.npm/_logs/2024-12-10T09_15_11_227Z-debug-0.log learn_project exited with code 1错误发生在这里
command: sh -c "cd /app && npm config delete proxy && # 这些命令正常执行 npm config delete https-proxy && # 这些命令正常执行 npm config set registry <https://registry.npmmirror.com/> && # 这些命令正常执行 npm install -g pnpm && # <-- 错误发生在这里 pnpm install &&尝试修改run命令,确保在容器内npm也不使用代理
//docker-compose.yml volumes: # todo modify in server - /home/koki/learn_project:/app # - /Users/koki/projects/learn_project:/app depends_on: - db command: sh -c "cd /app && npm config delete proxy &&//add npm config delete https-proxy &&//add仍然
尝试在docker image阶段就确保容器内的npm不使用代理
//Dockerfile FROM docker.m.daocloud.io/node:alpine # 预先配置 npm,删除代理设置 RUN npm config delete proxy \ && npm config delete https-proxy \ && npm config set registry <https://registry.npmmirror.com/> \ && npm config set strict-ssl false WORKDIR /app EXPOSE 3000尝试关闭系统级别的clash代理
koki@debian:~/learn_project$ ps aux | grep clash//查看clash在哪个进程 root 381557 0.0 0.0 725116 6496 ? Sl Nov29 1:52 /home/peter/clash/bin/clash-linux-amd64 -d /home/peter/clash/conf koki 583275 0.0 0.0 6332 2096 pts/4 S+ 04:31 0:00 grep clash koki@debian:~/learn_project$ sudo kill 381557//杀掉这个进程仍然
尝试在docker image阶段就npm install -g pnpm,再修改yml文件:
//.. //去掉这里的npm install -g pnpm command: sh -c "cd /app && pnpm install && pnpm config set fetch-timeout 300000 && pnpm prisma generate --schema src/db/schema.prisma && pnpm prisma migrate deploy --schema src/db/schema.prisma && pnpm run build && pnpm run start" db: image: docker.m.daocloud.io/postgres:14-alpine container_name: gdst_db environment: - POSTGRES_USER=gdst - POSTGRES_PASSWORD=gdst - POSTGRES_DB=gdst_db ports: - "5433:5432" volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data:koki@debian:~/learn_project$ env -u http_proxy -u https_proxy docker-compose up --build Creating network "learn_project_default" with the default driver Building app Sending build context to Docker daemon 1.575GB Step 1/5 : FROM docker.m.daocloud.io/node:alpine ---> b68700c9f27a Step 2/5 : RUN npm config delete proxy && npm config delete https-proxy && npm config delete http-proxy && npm config delete all-proxy && npm config set registry <https://registry.npmmirror.com/> && npm install -g pnpm ---> Running in 8ade6fb86642 (node:7) ExperimentalWarning: CommonJS module /usr/local/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /usr/local/lib/node_modules/npm/node_modules/supports-color/index.js using require(). Support for loading ES Module in require() is an experimental feature and might change at any time (Use `node --trace-warnings ...` to show where the warning was created) (node:1) ExperimentalWarning: CommonJS module /usr/local/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /usr/local/lib/node_modules/npm/node_modules/supports-color/index.js using require(). Support for loading ES Module in require() is an experimental feature and might change at any time (Use `node --trace-warnings ...` to show where the warning was created) npm error code ECONNREFUSED npm error syscall connect npm error errno ECONNREFUSED npm error FetchError: request to <https://registry.npmmirror.com/pnpm> failed, reason: connect ECONNREFUSED 127.0.0.1:7890 npm error at ClientRequest.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/minipass-fetch/lib/index.js:130:14) npm error at ClientRequest.emit (node:events:513:28) npm error at emitErrorEvent (node:_http_client:104:11) npm error at _destroy (node:_http_client:892:9) npm error at onSocketNT (node:_http_client:912:5) npm error at process.processTicksAndRejections (node:internal/process/task_queues:91:21) { npm error code: 'ECONNREFUSED', npm error errno: 'ECONNREFUSED', npm error syscall: 'connect', npm error address: '127.0.0.1', npm error port: 7890, npm error type: 'system', npm error requiredBy: '.' npm error } npm error npm error If you are behind a proxy, please make sure that the npm error 'proxy' config is set properly. See: 'npm help config' npm error A complete log of this run can be found in: /root/.npm/_logs/2024-12-11T01_30_54_535Z-debug-0.log The command '/bin/sh -c npm config delete proxy && npm config delete https-proxy && npm config delete http-proxy && npm config delete all-proxy && npm config set registry <https://registry.npmmirror.com/> && npm install -g pnpm' returned a non-zero code: 1最终解决方法
FROM docker.m.daocloud.io/node:alpine # 清理所有可能的代理设置 RUN set -x \ && npm config ls -l | grep proxy \ && npm config rm proxy \ && npm config rm https-proxy \ && npm config rm http-proxy \ && npm config rm all-proxy \ && unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy \ && echo "registry=https://registry.npmmirror.com/" > /root/.npmrc \ && cat /root/.npmrc \ && npm install -g pnpm WORKDIR /app EXPOSE 3000version: "3.8" services: app: build: context: . dockerfile: Dockerfile image: learn_project:latest container_name: learn_project ports: - "18887:3000" environment: - DATABASE_URL=postgresql://gdst:gdst@db:5432/gdst_db - HTTP_PROXY="" - HTTPS_PROXY="" - NO_PROXY="*" volumes: # todo modify in server - /home/koki/learn_project:/app # - /Users/koki/projects/learn_project:/app depends_on: - db command: sh -c "cd /app && pnpm install && pnpm config set fetch-timeout 300000 && pnpm prisma generate --schema src/db/schema.prisma && pnpm prisma migrate deploy --schema src/db/schema.prisma && pnpm run build && pnpm run start" db: image: docker.m.daocloud.io/postgres:14-alpine container_name: gdst_db environment: - POSTGRES_USER=gdst - POSTGRES_PASSWORD=gdst - POSTGRES_DB=gdst_db ports: - "5433:5432" volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data:在docker compose up的时候:
learn_project | Error: request to <https://binaries.prisma.sh/all_commits/5dbef10bdbfb579e07d35cc85fb1518d357cb99e/linux-musl/libquery_engine.so.node.gz.sha256> failed, reason: connect ECONNREFUSED 127.0.0.1:7890以及
learn_project | An error occurred in getProxyAgent(), no proxy agent will be used. Error: Error while instantiating HttpsProxyAgent with URL: """" learn_project | TypeError: Invalid URL learn_project | Check the following env vars "https_proxy" or "HTTPS_PROXY". The value should be a valid URL starting with "https://"解决方法
//。。 //增加这些配置 - http_proxy= - https_proxy= - HTTP_PROXY= - HTTPS_PROXY= - PRISMA_CLI_PROXY= - PRISMA_ENGINES_MIRROR= volumes: # todo modify in server - /home/koki/learn_project:/app # - /Users/koki/projects/learn_project:/app depends_on: - db command: > sh -c "cd /app && env | grep -i proxy > /tmp/env_check.log &&//增加打印日志 npm config list > /tmp/npm_config.log && pnpm install && pnpm config set fetch-timeout 300000 && pnpm prisma generate --schema src/db/schema.prisma && pnpm prisma migrate deploy --schema src/db/schema.prisma && pnpm run build && pnpm run start" db: image: docker.m.daocloud.io/postgres:14-alpine container_name: gdst_db environment: - POSTGRES_USER=gdst - POSTGRES_PASSWORD=gdst - POSTGRES_DB=gdst_db ports: - "5433:5432" volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data: -
查看容器日志的时候
✔ Generated Prisma Client (v6.0.1) to ./node_modules/.pnpm/@prisma+client@6.0.1_prisma@6.0.1/node_modules/@prisma/client in 93ms Start by importing your Prisma Client (See: <https://pris.ly/d/importing-client>) Tip: Interested in query caching in just a few lines of code? Try Accelerate today! <https://pris.ly/tip-3-accelerate> prisma:warn Prisma failed to detect the libssl/openssl version to use, and may not work as expected. Defaulting to "openssl-1.1.x". Please manually install OpenSSL and try installing Prisma again. prisma:warn Prisma failed to detect the libssl/openssl version to use, and may not work as expected. Defaulting to "openssl-1.1.x". Please manually install OpenSSL and try installing Prisma again. Prisma schema loaded from src/db/schema.prisma Datasource "db": PostgreSQL database "gdst_db", schema "public" at "db:5432" Error: Could not parse schema engine response: SyntaxError: Unexpected token 'E', "Error load"... is not valid JSONprisma需要openssl
for docker.m.daocloud.io/node:alpine 0.0s => CACHED [app 1/4] FROM docker.m.daocloud.io/node:alpine 0.0s => [app 2/4] RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories 0.4s => ERROR [app 3/4] RUN apk add --no-cache git openssl openssl-dev postgresql-client 0.4s ------ > [app 3/4] RUN apk add --no-cache git openssl openssl-dev postgresql-client: 0.309 fetch <https://mirrors.aliyun.com/alpine/v3.21/main/x86_64/APKINDEX.tar.gz> 0.310 WARNING: fetching <https://mirrors.aliyun.com/alpine/v3.21/main:> could not connect to server (check repositories file) 0.310 fetch <https://mirrors.aliyun.com/alpine/v3.21/community/x86_64/APKINDEX.tar.gz> 0.310 WARNING: fetching <https://mirrors.aliyun.com/alpine/v3.21/community:> could not connect to server (check repositories file) 0.311 ERROR: unable to select packages: 0.311 git (no such package): 0.311 required by: world[git] 0.311 openssl (no such package): 0.311 required by: world[openssl] 0.311 openssl-dev (no such package): 0.311 required by: world[openssl-dev] 0.311 postgresql-client (no such package): 0.311 required by: world[postgresql-client] ------ failed to solve: executor failed running [/bin/sh -c apk add --no-cache git openssl openssl-dev postgresql-client]: exit code: 4尝试1: 使用Alpine 和 apk add
尝试在dockerfile中
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories # 安装所需的依赖 RUN apk add --no-cache \ openssl \ openssl-dev \ libc6-compat \ git \ postgresql-client报错
koki@debian:~/learn_project$ env -u http_proxy -u https_proxy docker-compose up --build Building app Sending build context to Docker daemon 1.575GB Step 1/6 : FROM docker.m.daocloud.io/node:alpine ---> b68700c9f27a Step 2/6 : RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories ---> Using cache ---> 408859334c4a Step 3/6 : RUN apk add --no-cache openssl openssl-dev libc6-compat git postgresql-client ---> Running in 9f0ef1d47eee fetch <https://mirrors.aliyun.com/alpine/v3.21/main/x86_64/APKINDEX.tar.gz> WARNING: fetching <https://mirrors.aliyun.com/alpine/v3.21/main:> could not connect to server (check repositories file) fetch <https://mirrors.aliyun.com/alpine/v3.21/community/x86_64/APKINDEX.tar.gz> WARNING: fetching <https://mirrors.aliyun.com/alpine/v3.21/community:> could not connect to server (check repositories file) ERROR: unable to select packages: git (no such package): required by: world[git] libc6-compat (no such package): required by: world[libc6-compat] openssl (no such package): required by: world[openssl] openssl-dev (no such package): required by: world[openssl-dev] postgresql-client (no such package): required by: world[postgresql-client] The command '/bin/sh -c apk add --no-cache openssl openssl-dev libc6-compat git postgresql-client' returned a non-zero code: 5 ERROR: Service 'app' failed to build : Build failed尝试检查Alpine 版本,并下载指定版本
koki@debian:~/learn_project$ env -u http_proxy -u https_proxy docker-compose up --build Building app Sending build context to Docker daemon 1.575GB Step 1/7 : FROM docker.m.daocloud.io/node:alpine ---> b68700c9f27a Step 2/7 : RUN cat /etc/os-release ---> Using cache ---> ebb99cabf400 Step 3/7 : RUN echo "<https://mirrors.aliyun.com/alpine/v3.21/main/>" > /etc/apk/repositories && echo "<https://mirrors.aliyun.com/alpine/v3.21/community/>" >> /etc/apk/repositories ---> Running in 3f09f4777da4 Removing intermediate container 3f09f4777da4 ---> dd1686d4bb54 Step 4/7 : RUN apk add --no-cache openssl openssl-dev libc6-compat git postgresql-client ---> Running in 52f73d456853 fetch <https://mirrors.aliyun.com/alpine/v3.21/main/x86_64/APKINDEX.tar.gz> WARNING: fetching <https://mirrors.aliyun.com/alpine/v3.21/main/:> could not connect to server (check repositories file) fetch <https://mirrors.aliyun.com/alpine/v3.21/community/x86_64/APKINDEX.tar.gz> WARNING: fetching <https://mirrors.aliyun.com/alpine/v3.21/community/:> could not connect to server (check repositories file) ERROR: unable to select packages: git (no such package): required by: world[git] libc6-compat (no such package): required by: world[libc6-compat] openssl (no such package): required by: world[openssl] openssl-dev (no such package): required by: world[openssl-dev] postgresql-client (no such package): required by: world[postgresql-client] The command '/bin/sh -c apk add --no-cache openssl openssl-dev libc6-compat git postgresql-client' returned a non-zero code: 5 ERROR: Service 'app' failed to build : Build failed更换镜像
FROM docker.m.daocloud.io/node:alpine # 检查 Alpine 版本 RUN cat /etc/os-release # 使用 USTC 的 Alpine 3.21 镜像源 RUN echo "<https://mirrors.ustc.edu.cn/alpine/v3.21/main/>" > /etc/apk/repositories \ && echo "<https://mirrors.ustc.edu.cn/alpine/v3.21/community/>" >> /etc/apk/repositories # 安装所需的依赖 RUN apk add --no-cache \ openssl \ openssl-dev \ libc6-compat \ git \ postgresql-client # 清理所有可能的代理设置 RUN set -x \ && npm config ls -l | grep proxy \ && npm config rm proxy \ && npm config rm https-proxy \ && npm config rm http-proxy \ && npm config rm all-proxy \ && unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy \ && echo "registry=https://registry.npmmirror.com/" > /root/.npmrc \ && cat /root/.npmrc \ && npm install -g pnpm WORKDIR /app EXPOSE 3000尝试2:使用Debian 基础镜像和apt
FROM docker.m.daocloud.io/node:20-slim # 使用清华大学的 Debian 镜像源 RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list \ && sed -i 's/security.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list # 安装依赖 RUN apt-get update \ && apt-get install -y \ openssl \ libssl-dev \ git \ postgresql-client \ && rm -rf /var/lib/apt/lists/* # 清理所有可能的代理设置 RUN set -x \ && npm config ls -l | grep proxy \ && npm config rm proxy \ && npm config rm https-proxy \ && npm config rm http-proxy \ && npm config rm all-proxy \ && unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy \ && echo "registry=https://registry.npmmirror.com/" > /root/.npmrc \ && cat /root/.npmrc \ && npm install -g pnpm WORKDIR /app EXPOSE 3000Works!
怎么区分要用apt add 还是apk get
这取决于你使用的基础镜像(base image)的操作系统:
-
检查基础镜像:
FROM docker.m.daocloud.io/node:20-sli… # 这是基于 Debian 的镜像,使用 apt-get
常见的基础镜像对应的包管理器:
-
apt-get:
- Debian
- Ubuntu
- 示例镜像:node:20-slim, ubuntu:20.04
-
apk:
- Alpine Linux
- 示例镜像:node:20-alpine, alpine:3.18
-
检查代理配置是从哪里来的
koki@debian:~/learn_project$ sudo nano /etc/environment//空文件
koki@debian:~/learn_project$ nano ~/.bashrc//空文件
koki@debian:~/learn_project$ sudo nano /etc/apt/apt.conf.d/proxy.conf
koki@debian:~/learn_project$ env | grep -i proxy
koki@debian:~/learn_project$ ls /etc/apt/apt.conf.d/
00CDMountPoint 00trustcdrom 01autoremove 02autoremove-postgresql 20listchanges 70debconf 99needrestart
koki@debian:~/learn_project$ apt-config dump | grep -i proxy
koki@debian:~/learn_project$ sudo systemctl show --property=Environment docker
Environment=
koki@debian:~/learn_project$ cat ~/.docker/config.json
{
"proxies": {
"default": {
"httpProxy": "<http://127.0.0.1:7890>",
"httpsProxy": "<http://127.0.0.1:7890>",
"noProxy": "127.0.0.1"
}
}
}
清除代理即可: echo '{}' > ~/.docker/config.json