Docker容器中Cron任务未输出console.log的问题求助
问题
我已创建docker-compose.yaml、Dockerfile和entrypoint.sh文件,通过Dockerfile构建Ubuntu容器,在容器内安装Node.js并克隆项目仓库后,项目可正常运行。现在需要通过Cron每分钟执行run.js中的users()函数,手动执行node /app/api/run.js能正常输出I am the function in user.js,但Cron任务执行时终端看不到该输出。
核心代码
run.js:
const users = require("./user"); users();
user.js:
function users() { console.log("I am the function in user.js") } module.exports = users;
容器配置文件
docker-compose.yaml:
version: '3' services: node-backend: build: context: . dockerfile: Dockerfile image: cron-api container_name: cron-api-cont ports: - 3002:3002 entrypoint: /app/entrypoint.sh
Dockerfile:
FROM ubuntu:22.04 # Install necessary dependencies RUN apt-get update && \ apt-get install -y git curl cron # Install Node.js RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - RUN apt-get install -y nodejs # Create app working directory WORKDIR /app # Copy the entrypoint script into the container COPY entrypoint.sh /app/entrypoint.sh # Set executable permissions for the entrypoint script RUN chmod +x /app/entrypoint.sh # Expose the app port EXPOSE 3002
entrypoint.sh:
#!/bin/bash # Set GitHub credentials GIT_USERNAME="username" GIT_TOKEN="my_token_private" BRANCH="main" # Clone the repository using credentials git clone -b $BRANCH "https://${GIT_USERNAME}:${GIT_TOKEN}@github.com/username/node-for-docker-test.git" /app/api # Check if the cloning process is complete if [ -d "/app/api" ]; then echo "Cloning completed successfully." echo "List of directories inside api:" ls -d /app/api else echo "Cloning failed." fi # Go to the backend directory cd /app/api # Install node modules npm ci # Start the server npm start & # Schedule the cron job to execute the users() function every 5 minutes echo "*/1 * * * * node /app/api/run.js" > /tmp/cron_job.txt echo "Cron job definition created." # Check if the run.js file exists and print its content run_js_file="/app/api/run.js" if [ -f "$run_js_file" ]; then echo "Found run.js file. Content:" cat "$run_js_file" else echo "run.js file not found." fi # Install the cron job from the file crontab /tmp/cron_job.txt echo "Cron job installed." # Start the cron service service cron start & echo "Cron service started." # Keep the container running tail -f /dev/null
验证信息
- 手动执行命令正常输出:
root@6ef26d9188:/app/api# node /app/api/run.js I am the function in user.js
- Cron任务已配置:
root@6ef26d9188:/# crontab -l */1 * * * * node /app/api/run.js
- Cron服务正在运行:
root@6ef26d918826:/# service cron status * cron is running
- 容器初始化日志正常,但无Cron任务输出。
解决方案
Cron任务的输出不会默认出现在容器终端日志里,原因和解决办法如下:
1. Cron输出未关联容器主进程日志
Cron执行命令时,标准输出和错误输出默认不会指向容器的主日志流(即docker logs或终端显示的日志),而是会尝试通过邮件发送给执行用户,但容器未配置邮件服务,导致输出直接丢失。
解决办法:修改Cron任务,将输出重定向到容器主进程的标准输出/错误流:
*/1 * * * * node /app/api/run.js >> /proc/1/fd/1 2>> /proc/1/fd/2
/proc/1/fd/1是容器主进程的标准输出,/proc/1/fd/2是标准错误,这样Cron的输出就会出现在容器日志中。
2. Cron执行环境可能找不到Node路径
手动执行时Node可用,但Cron的执行环境变量与交互式shell不同,可能无法找到node命令的路径。
解决办法:先在容器内执行which node获取Node绝对路径(比如/usr/bin/node),然后修改Cron任务:
*/1 * * * * /usr/bin/node /app/api/run.js >> /proc/1/fd/1 2>> /proc/1/fd/2
3. 可选:输出到独立日志文件
若不想把Cron输出混入容器主日志,可指定独立日志文件:
*/1 * * * * node /app/api/run.js >> /app/api/cron.log 2>&1
之后进入容器查看/app/api/cron.log即可获取输出。
内容的提问来源于stack exchange,提问作者Ke_Sandaru

