Skip to main content
In this guide, you will learn how to create a custom Node.js buildpack using the Pack CLI. We’ll generate the starter boilerplate, update the detection logic to target Node.js projects, and enhance the build process to install Node.js and application dependencies. This article covers each step in detail to help you convert your source code into a container image with best practices.

Creating the Buildpack

To get started, use the Pack CLI to create a new buildpack. In this example, the buildpack is named “my-js-buildpack”, uses API version 0.10, and is stored in a folder called js-buildpack with an initial version of 0.0.1:
After running this command, you should see output similar to:
If you inspect the js-buildpack folder, you’ll notice a buildpack.toml file containing metadata similar to:
The bin directory hosts two scripts: detect and build. The detect script determines if the buildpack applies to the application, while the build script handles the build logic.

Understanding the Detect Script

The default detect script is as follows:
If the detect script exits with a status code of 0, the build process continues to the build stage. To control whether your buildpack should be activated, you can conditionally exit with a nonzero status code. For example, to explicitly fail detection, you might modify the script to:
Exiting with status code 1 signals the builder that this buildpack should not be used. Since our buildpack is intended for Node.js applications, updating the detection logic to check for a package.json file makes it more robust:
This change ensures that if the package.json file is absent, the buildpack exits with code 100, indicating that it does not apply.

The Default Build Script

The default build script is minimal and only exits successfully:
For a Node.js application, the build process should perform the following tasks:
  1. Download and install Node.js.
  2. Install application dependencies using an npm command.
  3. Create a launch.toml file (in the CNB layers directory) specifying the start command for the application.

Updating the Build Script for Node.js

Enhance your bin/build script to download and install Node.js version 18.18.1, update the PATH during the build, install dependencies, and create a launch.toml file. Below is the updated script:
When running build commands, environment variable changes (like modifications to PATH) only persist during the build process. At runtime, these changes do not apply. Hence, we reference the full path (bin/node) in the launch command.
With these modifications, the build script will:
  • Download and extract Node.js into the current working directory.
  • Update the PATH so that Node.js and npm are accessible during the build.
  • Install application dependencies using npm ci.
  • Generate a launch.toml file that defines a web process with the command bin/node index.js.

Building the Image with the Custom Buildpack

With the updated detect and build scripts, you can now build the container image using your custom buildpack. For example, run:
During the build process, you should see output similar to:
At this point, your image is successfully created. The generated launch.toml file instructs the lifecycle to execute bin/node index.js when the container starts.

Running and Debugging the Container

To run your new image, you can use the following Docker command:
If you encounter issues such as the container stopping unexpectedly, list all containers with:
You might see an error in the logs similar to:
This error indicates that the runtime environment cannot locate Node.js because PATH changes during the build process are not propagated. The solution is to reference the full executable path (i.e., using "bin/node" in the launch command). Once the container is running with the correct launch command, test the application with:
If configured correctly, you should receive:

Process Overview

Below is a summary table of actions performed by the buildpack:

Conclusion

In this article, you learned how to create a custom Node.js buildpack that transforms source code into a runnable container image. We started by generating the buildpack boilerplate, modified the detect script to verify the presence of package.json, and enhanced the build script to: • Download and extract Node.js
• Install application dependencies via npm ci
• Generate a launch.toml that specifies the startup process
While this example buildpack provides a basic setup, it can be extended and optimized further to adhere to advanced best practices. Future articles will delve into additional optimizations and buildpack features. For more details on containerizing Node.js applications, check out the official Node.js documentation and Cloud Native Buildpacks documentation. Happy building!

Watch Video