Skip to content
NebulaCtrldocs
Guides

Build without a Dockerfile

Deploy a Node, Go, Python, Ruby, PHP, Rust or static project from Git with no Dockerfile, built by Railpack, and choose the builder when you need to.

A service that builds from Git does not need a Dockerfile. When there is none at the configured path, NebulaCtrl reads a few marker files from the repository, recognizes the project, and builds it with Railpack. With the default Detect automatically, a Dockerfile at the configured path wins. This page shows how to rely on that, and how to force a builder. The rules are in Build detection.

Before you begin

  • A Git service, set up as in Deploy from Git. A public repository works, too.
  • A cluster whose agent supports Railpack builds. If it does not, the build fails and says that the cluster's build policy, Build CRD or agent predates Railpack builds. Update the agent as in Update an agent.

Check the repository

Railpack builds a repository that has one of these files at its root: package.json, go.mod, Cargo.toml, pyproject.toml, requirements.txt, Gemfile, composer.json or index.html. If a repository has none, the build fails and tells you to add a Dockerfile or one of these files.

Add the service and read the preview

  1. Add the repository as in Deploy from Git. A new service starts with Build engine set to Detect automatically.
  2. To see what NebulaCtrl detects before you create the service, select Custom service in Add to canvas, and under Source choose Git repository or Public repository. When the repository has no nebula.toml, a card reads, for example, Detected Node (nextjs) — builds automatically with Railpack. The Git repository option of Add to canvas shows no card.
  3. Select Show details for the package manager, the start command, the port and the facts detection used.

The preview does not check for a Dockerfile. If there is one at the configured path, the build uses it.

A repository whose host NebulaCtrl cannot read, such as a self-hosted GitLab that is not connected, shows no preview, and the build itself decides after it clones.

Make the app listen on the right port

A Railpack image has no way to declare its port, so NebulaCtrl sets it:

  • When the service has exactly one http process, the release sets the variable PORT to that process's port. A new service's default web process uses port 8080. Make the app listen on $PORT.
  • When detection finds a port hard-coded in a package.json script, such as --port 4000 in scripts.start, the release routes traffic to that port for the one http process, even when the process is set to another port. The script ignores PORT, so NebulaCtrl follows the script and records the change in the rollout log. Set the process port to the script's port to make it explicit.
  • A variable named PORT that you set replaces the injected value.

Choose the builder yourself

The default, Detect automatically, builds a Dockerfile when one exists and Railpack when none does. To fix the choice for a service:

  1. Open the service's Settings tab and select Edit… under Source.
  2. Set Build engine to Dockerfile or Railpack.
  3. Select Save changes.

To fix the choice from the repository, set builder in the service's nebula.toml:

nebula.toml
[build]
builder = "railpack"

A builder in the file wins over the service's setting. With Railpack, the build uses Railpack even when a Dockerfile exists, and does not fail when detection recognizes nothing. With Dockerfile, the build fails when no Dockerfile exists at the configured path. A build target and [build.args] apply only to a Dockerfile build. target and [build.args] in nebula.toml are refused together with builder = "railpack". A Build target set on the service is hidden in the console while Build engine is Railpack, and a Railpack build ignores it.

Run as a different user

NebulaCtrl runs every process of a Railpack-built release as user 1000 when nothing else sets one. To use another user, set run_as_user on the process in nebula.toml, for example under [processes.web], or set Run as user when you edit the process under Processes in the service's Settings tab. An explicit 0 runs the process as root.

Verify

Deploy the service. In the service's Deployments tab, open the deployment and read its Build logs. The detect step records which builder ran:

  • A line that starts no Dockerfile at Dockerfile; detected and ends building with Railpack means detection chose Railpack.
  • A line that starts builder = "railpack" (explicit) means the setting chose it.
  • A line that starts NebulaCtrl can't read this repository's files means the repository's host is one NebulaCtrl cannot read, and the build job chooses after cloning.

In the Settings tab, Build engine under nebula.toml reads Railpack followed by the detected provider, for example Railpack — node (nextjs). The release then runs as user 1000 with PORT and HOME set.

If the build fails with no Dockerfile at Dockerfile on main and nothing recognizable to build automatically, the repository has no marker file at its root. Add one, or add a Dockerfile.

Next steps

On this page