Stay organized with collections Save and categorize content based on your preferences.

Build and create a Node.js job in Cloud Run

Learn how to create a simple Cloud Run job, package it into a container image, upload the container image to Container Registry, and then deploy to Cloud Run. You can use other languages in addition to the ones shown.

Before you begin

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Cloud project. Learn how to check if billing is enabled on a project.

  4. Install and initialize the Google Cloud CLI.
  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Cloud project. Learn how to check if billing is enabled on a project.

  7. Install and initialize the Google Cloud CLI.

Writing the sample job

To write a job in Node.js:

  1. Create a new directory named jobs and change directory into it:

    mkdir jobs
    cd jobs
    
  2. Create a package.json file with the following contents:

    {
        "name": "jobs",
        "version": "1.0.0",
        "description": "Node.js sample for Cloud Run jobs",
        "main": "index.js",
        "scripts": {
          "start": "node index.js"
        },
        "author": "Google LLC",
        "license": "Apache-2.0"
      }
    
  3. In the same directory, create a index.js file for the actual job code. Copy the following sample lines into it:

    // Retrieve Job-defined env vars
    const {CLOUD_RUN_TASK_INDEX = 0, CLOUD_RUN_TASK_ATTEMPT = 0} = process.env;
    // Retrieve User-defined env vars
    const {SLEEP_MS, FAIL_RATE} = process.env;
    
    // Define main script
    const main = async () => {
      console.log(
        `Starting Task #${CLOUD_RUN_TASK_INDEX}, Attempt #${CLOUD_RUN_TASK_ATTEMPT}...`
      );
      // Simulate work
      if (SLEEP_MS) {
        await sleep(SLEEP_MS);
      }
      // Simulate errors
      if (FAIL_RATE) {
        try {
          randomFailure(FAIL_RATE);
        } catch (err) {
          err.message = `Task #${CLOUD_RUN_TASK_INDEX}, Attempt #${CLOUD_RUN_TASK_ATTEMPT} failed.\n\n${err.message}`;
          throw err;
        }
      }
      console.log(`Completed Task #${CLOUD_RUN_TASK_INDEX}.`);
    };
    
    // Wait for a specific amount of time
    const sleep = ms => {
      return new Promise(resolve => setTimeout(resolve, ms));
    };
    
    // Throw an error based on fail rate
    const randomFailure = rate => {
      rate = parseFloat(rate);
      if (!rate || rate < 0 || rate > 1) {
        console.warn(
          `Invalid FAIL_RATE env var value: ${rate}. Must be a float between 0 and 1 inclusive.`
        );
        return;
      }
    
      const randomFailure = Math.random();
      if (randomFailure < rate) {
        throw new Error('Task failed.');
      }
    };
    
    // Start script
    main().catch(err => {
      console.error(err);
      process.exit(1); // Retry Job Task by exiting the process
    });

    Cloud Run jobs allows users to specify the number of tasks the job is to execute. This sample code shows how to use the built-in CLOUD_RUN_TASK_INDEX environment variable. Each task represents one running copy of the container. Note that tasks are usually executed in parallel. Using multiple tasks is useful if each task can independently process a subset of your data.

    Each task is aware of its index, stored in the CLOUD_RUN_TASK_INDEX environment variable. The built-in CLOUD_RUN_TASK_COUNT environment variable contains the number of tasks supplied at job execution time via the --tasks parameter.

    The code shown also shows how to retry tasks, using the built-in CLOUD_RUN_TASK_ATTEMPT environment variable, which contains the number of times this task has been retried, starting at 0 for the first attempt and incrementing by 1 for every successive retry, up to --max-retries.

    The code also lets you generate failures as a way to test retries and to generate error logs so you can see what those look like.

  4. Create a Procfile with the following contents:

    # Define the application's entrypoint to override default, `npm start`
    # https://github.com/GoogleCloudPlatform/buildpacks/issues/160
    web: node index.js
    

Your code is complete and ready to be packaged in a container.

Build the code into a container image and push it to a registry

Important: This quickstart assumes that you have owner or editor roles in the project you are using for the quickstart. Otherwise, refer to Cloud Run deployment permissions, Cloud Build permissions, and Artifact Registry permissions for the permissions required.

Use a Buildpack to build the container:

gcloud builds submit --pack image=gcr.io/PROJECT_ID/logger-job

Create a job in Cloud Run

To create a job using the container you just built:

gcloud beta run jobs create job-quickstart \
    --image gcr.io/PROJECT_ID/logger-job \
    --tasks 50 \
    --set-env-vars SLEEP_MS=10000 \
    --set-env-vars FAIL_RATE=0.5 \
    --max-retries 5 \
    --region REGION

where PROJECT_ID is your project ID and REGION is your region, for example, us-central1. Note that you can change the various parameters to whatever values you want to use for your testing purposes. SLEEP_MS simulates work and FAIL_RATE causes X% of tasks to fail so you can experiment with parallelism and retrying failing tasks.

Execute a job in Cloud Run

To execute the job you just created:

gcloud beta run jobs execute job-quickstart

When you are prompted for a region, select the region of your choice, for example us-central1.

Test locally

You can run the job locally:

docker run --rm -e FAIL_RATE=0.9 -e SLEEP_MS=1000 gcr.io/PROJECT_ID/logger-job
where PROJECT_ID is your project ID.

What's next

For more information on building a container from code source and pushing to a repository, see: