feat(docker): 安装 tzdata 并设置 TZ=Asia/Shanghai 以让 Node.js 使用上海时区

This commit is contained in:
shenjianZ 2025-08-02 10:42:43 +08:00
parent a96aa6e073
commit e936fbc140
8 changed files with 32 additions and 21 deletions

View File

@ -1,14 +1,13 @@
FROM node:20-alpine FROM node:20-alpine
# Set timezone to Asia/Shanghai FIRST
# This ensures that any native modules compiled during npm install are linked correctly.
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
WORKDIR /usr/src/app WORKDIR /usr/src/app
COPY package*.json ./ COPY package*.json ./
# Set timezone to Asia/Shanghai
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
ENV NODE_ENV=production
RUN npm install RUN npm install
COPY . . COPY . .

View File

@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS emails (
sender VARCHAR(255) NOT NULL, sender VARCHAR(255) NOT NULL,
subject VARCHAR(512), subject VARCHAR(512),
body TEXT, body TEXT,
received_at DATETIME DEFAULT CURRENT_TIMESTAMP, received_at DATETIME,
raw MEDIUMBLOB raw MEDIUMBLOB
); );

View File

@ -4,7 +4,8 @@ const logger = winston.createLogger({
level: 'info', level: 'info',
format: winston.format.combine( format: winston.format.combine(
winston.format.timestamp({ winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss' format: 'YYYY-MM-DD HH:mm:ss',
tz: 'Asia/Shanghai'
}), }),
winston.format.errors({ stack: true }), winston.format.errors({ stack: true }),
winston.format.splat(), winston.format.splat(),
@ -17,10 +18,16 @@ const logger = winston.createLogger({
] ]
}); });
// 在非生产环境下,添加一个带有着色的控制台输出
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({ logger.add(new winston.transports.Console({
format: winston.format.combine( format: winston.format.combine(
winston.format.colorize(), winston.format.colorize(),
// 确保控制台日志也有正确格式和时区的时间戳
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
tz: 'Asia/Shanghai'
}),
winston.format.printf(({ level, message, timestamp, stack }) => { winston.format.printf(({ level, message, timestamp, stack }) => {
if (stack) { if (stack) {
// 打印错误堆栈 // 打印错误堆栈
@ -32,14 +39,4 @@ if (process.env.NODE_ENV !== 'production') {
})); }));
} }
// 在文件日志中也使用更清晰的格式
logger.transports.forEach(t => {
if (t.name === 'file') {
t.format = winston.format.combine(
winston.format.timestamp(),
winston.format.json()
);
}
});
module.exports = logger; module.exports = logger;

View File

@ -42,9 +42,14 @@ async function saveEmail(stream) {
const subject = parsed.subject || 'No Subject'; const subject = parsed.subject || 'No Subject';
const body = parsed.text || (parsed.html || ''); const body = parsed.text || (parsed.html || '');
// Manually create a timestamp for 'Asia/Shanghai' timezone
const received_at = new Date().toLocaleString('sv-SE', {
timeZone: 'Asia/Shanghai'
});
const [result] = await db.execute( const [result] = await db.execute(
'INSERT INTO emails (recipient, sender, subject, body) VALUES (?, ?, ?, ?)', 'INSERT INTO emails (recipient, sender, subject, body, received_at) VALUES (?, ?, ?, ?, ?)',
[recipient, sender, subject, body] [recipient, sender, subject, body, received_at]
); );
// const [result] = await db.execute( // const [result] = await db.execute(
// 'INSERT INTO emails (recipient, sender, subject, body, raw) VALUES (?, ?, ?, ?, ?)', // 'INSERT INTO emails (recipient, sender, subject, body, raw) VALUES (?, ?, ?, ?, ?)',

View File

@ -17,6 +17,8 @@ services:
image: mysql:8.0 image: mysql:8.0
container_name: email-mysql container_name: email-mysql
restart: always restart: always
environment:
- TZ=Asia/Shanghai
env_file: env_file:
- compose.env - compose.env
volumes: volumes:

View File

@ -17,6 +17,8 @@ services:
image: registry.cn-hangzhou.aliyuncs.com/pull-image/mysql:8.0 image: registry.cn-hangzhou.aliyuncs.com/pull-image/mysql:8.0
container_name: email-mysql container_name: email-mysql
restart: always restart: always
environment:
- TZ=Asia/Shanghai
env_file: env_file:
- compose.full.env - compose.full.env
volumes: volumes:

View File

@ -1,6 +1,10 @@
services: services:
backend: backend:
build: ./backend build:
context: ./backend
args:
HTTP_PROXY: "http://127.0.0.1:7899"
HTTPS_PROXY: "http://127.0.0.1:7899"
container_name: email-backend container_name: email-backend
restart: always restart: always
ports: ports:

View File

@ -17,6 +17,8 @@ services:
image: registry.cn-hangzhou.aliyuncs.com/pull-image/mysql:8.0 # mysql:8.0 image: registry.cn-hangzhou.aliyuncs.com/pull-image/mysql:8.0 # mysql:8.0
container_name: email-mysql container_name: email-mysql
restart: always restart: always
environment:
- TZ=Asia/Shanghai
env_file: env_file:
- compose.env - compose.env
volumes: volumes: