从Node Cron 做定时任务到 Docker 部署一、简介 1.1)先看看 cron 背景: 当然 windows
一、简介
1.1)先看看 cron 背景:
cron表达式最初是由Unix操作系统中的cron守护进程所使用的一种语法规则,用于设置定时任务。
cron守护进程是Unix系统中的一个后台进程,用于周期性地执行指定的命令或脚本。
它可以根据用户的需求,按照指定的时间间隔或时间点来执行任务,通常用于定时备份、清理日志、发送邮件等操作。
当然 windows 也有定时任务,但是与 linux 和我们要讲的 cron 一些区别,windows 中叫 任务计划程序(本地)
,通过 任务计划程序(本地)
可以添加任务。接下来我们将通过 node-cron 在 node 平台上做定时任务。
1.2)定时任务目标:
使用 Node.js 创建发送每天定时发送邮件:
邮件内容是: `6 点了能下班了吗?`
二、先熟悉一下 node-cron 的规则
┌────────────── second (可选)
│ ┌──────────── 分钟 (minute,0 - 59)
│ │ ┌────────── 小时 (hour,0 - 23)
│ │ │ ┌──────── 一个月中的第几天 (day of month,1 - 31)
│ │ │ │ ┌────── 月份 (month,1 - 12)
│ │ │ │ │ ┌──── 一个星期中星期几 (day of week,0 - 6) 注意:星期天为 0
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * *
如果我们想要每天早上 7 点开始任务吗,那么我们的 cron 语句应该:
* 7 * * *
三、初始化项目并安装依赖
cd your_dir
pnpm init
pnpm add node-cron nodemailer typescript tsx
mkdir src && cd src
touch index.ts
本项目使用 typescript + esm, 因为不涉及前端内容,其实纯 Node.js 模块模式也是可以的。这里使用 esm 模块。意味着我们要使用 .js
文件结束导入 esm。 下面给出一 tsconfig 配置:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
四、安装 docker
安装 docker,推荐安装图形化软件,因为定时任务,管理使用图形化可能后期维护自己的项目,更加方便。
4.1)安装 docker 桌面端
当然喜欢 cli 的小伙伴也可以直接用,注意安装 cli 需要安装社区版本。
4.2)添加 Dockerfile 文件
FROM node:18-alpine
RUN npm install -g pnpm
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . .
RUN pnpm run build
CMD [ "pnpm", "start" ]
这里我们使用 node:18-alpine 一个较小的版本管理,然后使用 pnpm 管理项目,注意pnpm下载慢的换镜像源。然后指向构建相关的任务,最后开始运行开始名程序命令。
4.3)添加 .dockerignore 文件
node_modules
防止 docker 在 copy 文件的时候将 node_modules 也复制进去了。
五、安装依赖
pnpm add nodemailer dotenv node-cron
pnpm add @types/node @types/node-cron @types/nodemailer rimraf tsx typescript
5.1) 编写 npm script 运行脚本
"scripts": {
"dev": "tsx ./src/index.ts",
"build": "rimraf dist & tsc --outDir ./dist",
"start": "node ./dist/index.js",
"docker:build": "docker build -t node-cron .",
"docker:run": "docker run -itd node-cron"
},
六、编写代码
6.1)nodemailer 简单封装
import type SMTPConnection from "nodemailer/lib/smtp-connection";
import nodemailer from "nodemailer";
type SendMailOptions = {
host: string;
port: number;
auth: {
user: string;
pass: string;
};
to: string; // 接收者的邮箱地址
subject: string; // 邮件主题
html?: string; //也可以用html发送
};
export function sendMail(options: SendMailOptions) {
let transporter = nodemailer.createTransport({
host: options.host, // 发送者的邮箱厂商,支持列表:https://nodemailer.com/smtp/well-known/
port: options.port, // SMTP 端口
secureConnection: false, // SSL安全链接
secure: true,
requireTLS: true,
auth: {
//发送者的账户密码
user: options.auth.user, //账户
pass: options.auth.pass, //smtp授权码,到邮箱设置下获取
},
} as SMTPConnection.Options);
let mailOptions = {
from: `<${options.auth.user}>`, // 发送者昵称和地址
to: options.to, // 接收者的邮箱地址
subject: options.subject, // 邮件主题
html: options.html, //也可以用html发送
};
//发送邮件
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
reject(error);
return console.log(error);
}
resolve(info);
});
});
}
6.2)程序入口
import cron from "node-cron";
import dotenv from 'dotenv'
import { sendMail } from "./nodemail.js";
dotenv.config()
const data = {
host: "smtp.163.com",
port: 465,
user: process.env.user,
pass: process.env.pass,
to: process.env.to,
subject: "早安~",
html: "新的一天开始了,保持开心😄~",
};
cron.schedule("* 7 * * *", () => {
sendMail({
host: data.host,
port: data.port,
auth: {
user: process.env.user!,
pass: process.env.pass!,
},
to: process.env.to!, // 接收者的邮箱地址
subject: data.subject, // 邮件主题
html: data.html, //也可以用html发送
}).then((res: any) => {
console.log(res.response)
}).catch(error => {
console.log(error)
});
console.log("定时服务已启动~")
});
6.3) 配置环境变量
本文以 163 邮箱为例,设置环境变量
user = "" # 邮箱用户名
pass = "" # 邮箱授权吗
to = "" # 将要对象
当然,对于敏感信息,我们不能够
七、docker 构建与运行
7.1) 构建
因为有了 npm 脚本运行 docker 构建任务,我们使用
pnpm run docker:build
很简单使用 dockerfile 文件内容构建一个 node-cron
的镜像。有了镜像
7.2) 运行
pnpm run docker:run # 将会会在后台运行
有了 docker 部署到自己的服务器也是非常的简单容易,这里就在做过多的介绍了。
7.3)alpine 镜像 docker 时区问题
- 使用 tzdata 来处理时区问题
docker 设置时区可能会存在问题,因为使用 alpine linux
小体积 linxu 没有时区信息,使用 apk 管理包
apk add tzdata
ls /usr/share/zoneinfo # 展示 zoneinfo 数据
# 设置中国标准时间
cp /usr/share/zoneinfo/PRC /etc/localtime
echo "PRC" > /etc/timezone date
# 或者设置上海
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "PRC" > /etc/timezone date
## 移除 tzdata
apk del tzdata
## 校验
date # 校验
7.4) docker 优化
方案:一个简单的小项目其实可以不用 typescript/pnpm, 不用其他的辅助库,直接写简单的 js 代码,依赖减少,镜像体积也会减小。
八、其他适合 cron 的任务
- 定时数据库备份
- 定时充值清理数据
- 定时构建
- 定时签到等
- ...
九、小结
本文主要讲解 node-cron 相关内容,定时任务非常有用,能够帮助我们做一些重复的内容,实现一些自动化。node-cron 是 node.js 平台的 cron, 使用 node-cron + docker 部署项目能够帮助我们方便的发送定时邮件、以及其他的任务。希望能够帮助读者。
转载自:https://juejin.cn/post/7366516215378165810