feat(docker): 安装 tzdata 并设置 TZ=Asia/Shanghai 以让 Node.js 使用上海时区
This commit is contained in:
parent
a96aa6e073
commit
e936fbc140
|
|
@ -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 . .
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 (?, ?, ?, ?, ?)',
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue