Railpack Documentation

repository·main·Indexed 22 days ago

https://github.com/railwayapp/railpack

Railpack is a tool for building optimized container images from source code with minimal configuration. Designed as the successor to Nixpacks and leveraging production learnings from Railway, it provides automated build detection and optimization for various environments, including Node.js, Bun, Elixir, and Gleam.

Tokens
42.2K
Snippets
179
Records
288
Agent score
76%

What's inside railpack

  1. What is Railpack

    main

    Railpack is a zero-config application builder designed to automatically analyze your source code and transform it into a container image. It functions as a custom BuildKit frontend, utilizing BuildKit LLB for efficient image construction.

    Key capabilities include:

    • Multi-language support: Out-of-the-box support for Node, Python, Go, PHP, Java, Ruby, and more.
    • Framework awareness: First-class support for modern web frameworks like Vite, Astro, Next.js, and Create React App (CRA) static sites.
    • Customization: Users can configure build behavior using environment variables or a configuration file.
  2. Compare Railpack to other build technologies

    main

    Railpack is designed as a modern alternative to Heroku builders and Cloud Native Buildpacks (CNB) with the following characteristics:

    • Open Source: Completely open source and serves as the default builder for Railway.
    • Unified Builder: A single builder for all languages, removing the need to manage multiple language-specific CNB builders.
    • Parallel Execution: Built on Docker LLB, allowing many aspects of the build to run in parallel.
    • Tooling Alignment: Built on mise, enabling you to align development, CI, and production tooling.
    • Testing Strategy: Every change is tested across hundreds of example projects to ensure stability.
  3. Distinguish between Environment Variables and Secrets

    main

    Railpack treats environment variables and secrets differently based on their lifecycle and visibility:

    • Environment Variables: These are saved in the final image and are available at runtime. They should not contain sensitive information. Providers can use these to inject runtime configuration.
    • Secrets: These are only available at build time and are never saved to the final image or logged in build logs. They are supplied via BuildKit secrets mounts.
  4. How Providers manage language support

    main

    Language support is implemented via Providers (e.g., node, python, php). A provider performs two main functions:

    1. Detect: It analyzes the application directory to determine if it matches the provider's criteria (e.g., the node provider looks for a package.json).
    2. Build: It modifies the build context by injecting the necessary steps, commands, caches, and configurations required to build for that specific language or framework.
  5. How Layer Caching works in Railpack

    main

    Railpack utilizes BuildKit's layer caching to optimize build speeds by avoiding redundant work. The cache is preserved unless a 'cache busting' event occurs.

    Cache busting is triggered by:

    • Copying files from the local context to the build context
    • Changing environment variables
    • Adding new generated files to the build context
    • Executing shell commands in the build context
  6. How BuildKit LLB Generation works in Railpack

    main

    Railpack generates build definitions using the BuildKit LLB (Low-Level Builder) Go API instead of transpiling build plans into standard Dockerfiles. This LLB definition is then either sent to the BuildKit daemon via the CLI or consumed by the BuildKit frontend.

    Using direct LLB generation provides several technical advantages over Dockerfile generation:

    • Custom Frontend Integration: Enables integration with BuildKit's frontend gateway, allowing the platform to interact with the BuildKit daemon directly or through Docker.
    • Caching and Optimization: Provides fine-grained control over the build cache, enabling more complex caching strategies than Dockerfiles allow.
    • Secret Management: Offers more secure and flexible mounting of secrets during the build process.
    • Type Safety: Build definitions are validated at compile-time using the official BuildKit Go library.
  7. How Deno builds and starts work in Railpack

    main

    Railpack builds Deno applications using a zero-configuration approach. The build process follows these steps:

    1. Installation: Installs the specified Deno version.
    2. Dependency Caching: Runs deno cache to prepare dependencies.
    3. Start Command: Determines the entry point to run with deno run --allow-all.

    Determining the Entry Point

    Railpack selects the file to run in this order:

    1. It looks for a main.ts, main.js, main.mjs, or main.mts file in the project root.
    2. If no such file exists, it uses the first .ts, .js, .mjs, or .mts file found in the project.
  8. How Railpack's architecture works

    main

    Railpack is composed of three main components that work together to transform an application into a container image:

    • Core: Acts as a compiler. It analyzes your application and generates a platform-independent Build Plan (a JSON object).
    • BuildKit: Acts as the backend. It consumes the Build Plan to generate BuildKit LLB (Low-Level Builder) and executes the build to produce a final image.
    • CLI: The primary entry point for users to interact with the system.

    The architecture is designed so that the Build Plan is decoupled from the specific backend (currently BuildKit), allowing for future extensibility.

  9. How Bun is detected in Railpack

    main

    Railpack automatically detects Bun as the JavaScript runtime and package manager using the following priority logic:

    1. Explicit Declaration: The packageManager field in package.json explicitly declares bun.
    2. Implicit Detection: If no higher-priority package manager is configured, Railpack looks for:
      • An engines.bun field in package.json.
      • A bun.lock file.
      • A bun.lockb file.
    3. Command Invocation: Bun is also installed if a package script or a configured start command explicitly invokes the bun binary.