skip to Main Content

I have already created a docker-compose.yaml file, Dockerfile and entrypoint.sh file. Dockerfile was used to create a ubuntu container. Inside this ubuntu container, I install Node.js and clone my project repository, then run the project. The project can be run without any problem. But, need to execute below function written in run.js file.

const users = require("./user");
users();

the console.log() is inside the user.js file,

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

Using the entrypoint.sh, I clone the repo and install node modules. then start the project. I do not want to write another .sh for the cron job. When I write the command inside the /app/ or /app/api/ directory inside container, it runs the users() function when I execute node /app/api/run.js manually.

root@6ef26d9188:/app/api# ls
index.js  node_modules  package-lock.json  package.json  run.js  user.js
root@6ef26d9188:/app/api# pwd
/app/api
root@6ef26d9188:/app/api# node /app/api/run.js
I am the function in user.js

Inside the docker, the cron service runs .After run the container, output of crontab -l is;

root@6ef26d9188:/# crontab -l
*/1 * * * * node /app/api/run.js

output of service cron status is;

root@6ef26d918826:/# service cron status
 * cron is running

This is the log of the container:

 ✔ Container cron-api-cont  Created                                        0.1s 
Attaching to cron-api-cont
cron-api-cont  | Cloning into '/app/api'...
cron-api-cont  | Cloning completed successfully.
cron-api-cont  | List of directories inside api:
cron-api-cont  | /app/api
cron-api-cont  | 
cron-api-cont  | added 90 packages, and audited 91 packages in 3s
cron-api-cont  | 
cron-api-cont  | 11 packages are looking for funding
cron-api-cont  |   run `npm fund` for details
cron-api-cont  | 
cron-api-cont  | 3 moderate severity vulnerabilities
cron-api-cont  | 
cron-api-cont  | To address all issues (including breaking changes), run:
cron-api-cont  |   npm audit fix --force
cron-api-cont  | 
cron-api-cont  | Run `npm audit` for details.
cron-api-cont  | npm notice 
cron-api-cont  | npm notice New major version of npm available! 8.19.4 -> 9.7.2
cron-api-cont  | npm notice Changelog: <https://github.com/npm/cli/releases/tag/v9.7.2>
cron-api-cont  | npm notice Run `npm install -g [email protected]` to update!
cron-api-cont  | npm notice 
cron-api-cont  | Cron job definition created.
cron-api-cont  | Found run.js file. Content:
cron-api-cont  | const users = require("./user");
cron-api-cont  | 
cron-api-cont  | users();Cron job installed.
cron-api-cont  | Cron service started.
cron-api-cont  |  * Starting periodic command scheduler cron
cron-api-cont  |    ...done.
cron-api-cont  | 
cron-api-cont  | > [email protected] start
cron-api-cont  | > nodemon index.js
cron-api-cont  | 
cron-api-cont  | [nodemon] 2.0.22
cron-api-cont  | [nodemon] to restart at any time, enter `rs`
cron-api-cont  | [nodemon] watching path(s): *.*
cron-api-cont  | [nodemon] watching extensions: js,mjs,json
cron-api-cont  | [nodemon] starting `node index.js`
cron-api-cont  | server is running on port 3002

Can anyone tell, why it does not print the console log result on the terminal for every 1 minute?

2

Answers


  1. In your entrypoint.sh, you have this line:

    echo "*/1 * * * * node /app/api/run.js" > /tmp/cron_job.txt

    The ">" character would reroute the output of the command to the /tmp/cron_job.txt, so the output does not appear on your console. Therefore, it is also not logged to your container log. Notice how you do not use the ">" character on any other echo command, which all show up in the log as you expect.

    According to this answer, you want to use the tee command, e.g.

    echo "*/1 * * * * node /app/api/run.js" | tee /tmp/cron_job.txt

    Check whether the output is in the /tmp/cron_job.txt file and see if you can log the output of the cronjob to both the console and the file.

    Also, small nitpick: Your comment in entrypoint.sh says to run the cronjob every five minutes, when you actually configure it to run every minute.

    Login or Signup to reply.
  2. Normally a Docker container only runs a single process. If you need multiple processes, you need to run multiple containers. This applies to the cron daemon too: since it’s a separate process, it needs its own container. This should be simple to set up in the docker-compose.yml:

    version: '3.8'
    services:
      node-backend:
        build: .
        ports:
          - 3002:3002
      cron-run:
        build: .
        command: cron -n
    

    (This is the entire Compose file; you do not need image: for things you build:, and you do not normally need to set container_name:, networks:, or to manually override the entrypoint:.)

    For this to work well, I’d suggest building your application only once in the Dockerfile, rather than repeating it every single time you start the container. Most of what’s in the entrypoint script should move into the Dockerfile. Don’t run git inside Docker at all; instead, add the docker-compose.yml and Dockerfile to your application’s source repository, and have the Dockerfile build whatever’s currently checked out.

    FROM node:16-slim  # based on Debian
    
    # Get the cron daemon
    RUN apt-get update 
     && DEBIAN_FRONTEND=noninteractive 
        apt-get install --no-install-recommends --assume-yes 
          cron
    
    # Install the application (boilerplate Node app setup)
    WORKDIR /app
    COPY package.json package-lock.json ./
    RUN npm ci
    COPY ./ ./
    # RUN npm build
    
    # Set up the cron job
    RUN echo '*/1 * * * * node /app/api/run.js' | crontab
    
    # By default, run the application
    CMD npm start
    

    Note that there is only one process per container now. We never launch a background process and don’t try to "start services"; this concept doesn’t really exist in a container and the service command does not work reliably. We especially do not need to "keep the container alive". One container is the Node application and one is the cron daemon, and the two containers will stay alive on their own so long as their respective processes are running.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search