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
- Add the repository as in Deploy from Git. A new service starts with Build engine set to Detect automatically.
- 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. - 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
httpprocess, the release sets the variablePORTto that process's port. A new service's defaultwebprocess uses port 8080. Make the app listen on$PORT. - When detection finds a port hard-coded in a
package.jsonscript, such as--port 4000inscripts.start, the release routes traffic to that port for the onehttpprocess, even when the process is set to another port. The script ignoresPORT, 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
PORTthat 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:
- Open the service's Settings tab and select Edit… under Source.
- Set Build engine to Dockerfile or Railpack.
- Select Save changes.
To fix the choice from the repository, set builder in the service's 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; detectedand endsbuilding with Railpackmeans 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 filesmeans 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
- Build detection lists every language, framework and default.
- Configure a service from its repository covers the rest of
nebula.toml. - Builds explains how a build becomes a release.
Deploy a container image
Run an image from a public or private registry as a service, deploy new tags and digests, and trigger a deploy from a Git push.
Import a Docker Compose file
Review a repository's Compose files in four steps and stage their services, databases, secrets and wiring in one change set.