This commit is contained in:
aaron 2025-08-10 12:37:00 +08:00
parent 7a7a9759ca
commit 70371686f9
6 changed files with 338 additions and 6 deletions

12
.gitignore vendored
View File

@ -92,3 +92,15 @@ payment-config.json
# Backup files
*.bak
*.backup
# Docker
.dockerignore
docker-compose.override.yml
.docker
# SSL certificates
ssl/
*.pem
*.key
*.crt
*.csr

183
DOCKER_DEPLOYMENT.md Normal file
View File

@ -0,0 +1,183 @@
# Docker 部署指南
## 快速开始
### 1. 使用 Docker Compose推荐
```bash
# 克隆项目
git clone <repository-url>
cd myusdtshop
# 启动服务
docker-compose up -d
# 查看日志
docker-compose logs -f
# 停止服务
docker-compose down
```
服务将在 http://localhost:3000 启动
### 2. 使用单独的 Docker 容器
```bash
# 构建镜像
docker build -t usdt-shop .
# 运行容器
docker run -d \
--name usdt-shop \
-p 3000:3000 \
-v $(pwd)/database:/app/database \
-e UPAY_APP_ID=your_app_id \
-e UPAY_APP_SECRET=your_app_secret \
usdt-shop
```
## 环境变量配置
创建 `.env` 文件来配置环境变量:
```bash
# UPay 配置
UPAY_APP_ID=your_production_app_id
UPAY_APP_SECRET=your_production_app_secret
# 服务端口
PORT=3000
# 运行环境
NODE_ENV=production
```
## 使用 Nginx 反向代理
如果需要使用 Nginx 反向代理:
```bash
# 启动包含 Nginx 的完整服务
docker-compose --profile nginx up -d
```
### SSL 证书配置
1. 将 SSL 证书放在 `ssl/` 目录下:
```
ssl/
├── cert.pem
└── key.pem
```
2. 编辑 `nginx.conf` 取消 HTTPS 部分的注释
3. 重启服务:
```bash
docker-compose --profile nginx restart nginx
```
## 数据持久化
- 数据库文件:`./database/shop.db`
- 图片文件:`./public/images/`
这些目录已通过 Docker volumes 映射到宿主机,数据会持久化保存。
## 生产环境部署
1. **修改 UPay 配置**
- 将测试环境的 APP_ID 和 APP_SECRET 改为生产环境值
- 在 `server.js` 中将 API_URL 改为生产环境地址
2. **设置环境变量**
```bash
export UPAY_APP_ID=production_app_id
export UPAY_APP_SECRET=production_app_secret
```
3. **使用 HTTPS**
- 配置 SSL 证书
- 启用 Nginx HTTPS 配置
## 常用命令
```bash
# 查看运行状态
docker-compose ps
# 查看实时日志
docker-compose logs -f usdt-shop
# 重启服务
docker-compose restart usdt-shop
# 更新应用
docker-compose down
docker-compose build --no-cache
docker-compose up -d
# 备份数据库
docker-compose exec usdt-shop cp /app/database/shop.db /tmp/
docker cp $(docker-compose ps -q usdt-shop):/tmp/shop.db ./backup/
# 进入容器调试
docker-compose exec usdt-shop sh
```
## 监控和维护
### 健康检查
应用包含健康检查端点Docker 会定期检查服务状态:
```bash
# 手动检查健康状态
docker-compose exec usdt-shop wget --spider http://localhost:3000
```
### 日志管理
```bash
# 查看最近100行日志
docker-compose logs --tail=100 usdt-shop
# 按时间过滤日志
docker-compose logs --since="2024-01-01T00:00:00" usdt-shop
```
## 故障排除
1. **端口占用**
```bash
# 检查端口占用
lsof -i :3000
# 修改端口
# 编辑 docker-compose.yml 中的 ports 配置
```
2. **数据库权限问题**
```bash
# 修复数据库文件权限
sudo chown -R 1001:1001 database/
sudo chmod 666 database/shop.db
```
3. **容器无法启动**
```bash
# 查看详细错误信息
docker-compose logs usdt-shop
# 重新构建镜像
docker-compose build --no-cache usdt-shop
```
## 安全注意事项
- 确保 `.env` 文件不被提交到版本控制
- 定期更新 Docker 镜像和依赖
- 使用强密码和安全的 API 密钥
- 在生产环境中启用 HTTPS
- 定期备份数据库文件

34
Dockerfile Normal file
View File

@ -0,0 +1,34 @@
# 使用官方Node.js运行时作为基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制package文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用源代码
COPY . .
# 创建数据库目录
RUN mkdir -p database
# 设置数据库文件权限
RUN touch database/shop.db && chmod 666 database/shop.db
# 暴露端口
EXPOSE 3000
# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
# 更改目录所有权
RUN chown -R nodejs:nodejs /app
USER nodejs
# 启动应用
CMD ["npm", "start"]

48
docker-compose.yml Normal file
View File

@ -0,0 +1,48 @@
version: '3.8'
services:
usdt-shop:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
# UPay配置 - 生产环境时需要修改这些值
- UPAY_APP_ID=${UPAY_APP_ID:-M1C40DvS}
- UPAY_APP_SECRET=${UPAY_APP_SECRET:-a2nqkkqRb09LIe87}
volumes:
# 持久化数据库文件
- ./database:/app/database
# 持久化上传的图片(如果有)
- ./public/images:/app/public/images
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
timeout: 5s
interval: 30s
retries: 3
start_period: 40s
# Nginx反向代理可选
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- usdt-shop
restart: unless-stopped
profiles:
- nginx
networks:
default:
driver: bridge
volumes:
database:
driver: local

50
nginx.conf Normal file
View File

@ -0,0 +1,50 @@
events {
worker_connections 1024;
}
http {
upstream app {
server usdt-shop:3000;
}
server {
listen 80;
server_name _;
# 重定向HTTP到HTTPS可选
# return 301 https://$server_name$request_uri;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
# HTTPS配置需要SSL证书
# server {
# listen 443 ssl;
# server_name your-domain.com;
#
# ssl_certificate /etc/nginx/ssl/cert.pem;
# ssl_certificate_key /etc/nginx/ssl/key.pem;
#
# location / {
# proxy_pass http://app;
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection 'upgrade';
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_cache_bypass $http_upgrade;
# }
# }
}

View File

@ -42,10 +42,14 @@ db.serialize(() => {
});
// UPay 配置
const UPAY_APP_ID = process.env.UPAY_APP_ID || 'E7c4dss9';
const UPAY_APP_SECRET = process.env.UPAY_APP_SECRET || 'Hwc56INsabRau2yn';
const UPAY_API_URL = 'https://api.upay.ink/v1/api/open';
// const UPAY_API_URL = 'https://api-test.upay.ink/v1/api/open';
// const UPAY_APP_ID = process.env.UPAY_APP_ID || 'E7c4dss9';
// const UPAY_APP_SECRET = process.env.UPAY_APP_SECRET || 'Hwc56INsabRau2yn';
// const UPAY_API_URL = 'https://api.upay.ink/v1/api/open';
const UPAY_APP_ID = process.env.UPAY_APP_ID || 'M1C40DvS';
const UPAY_APP_SECRET = process.env.UPAY_APP_SECRET || 'a2nqkkqRb09LIe87';
const UPAY_API_URL = 'https://api-test.upay.ink/v1/api/open';
// 产品配置
const PRODUCTS = {
@ -167,7 +171,8 @@ app.post('/api/payment/create', async (req, res) => {
chainType: '1', // USDT TRC20
fiatAmount: order.total_amount.toFixed(2),
fiatCurrency: 'USD',
notifyUrl: `${req.protocol}://${req.get('host')}/api/payment/callback`
notifyUrl: `${req.protocol}://${req.get('host')}/api/payment/callback`,
redirectUrl: `${req.protocol}://${req.get('host')}/success.html?order_id=${order_id}`
};
// 生成签名