docs/user/builds/railpack-and-dockerfiles.md
title: Railpack and Dockerfiles description: Build your app without a Dockerfile, or with yours, and set commands, build-time variables and CPU types.
Ployz builds your app with Railpack, so you don't need a Dockerfile. Railpack reads your repository, works out the language and framework, and builds an image that installs, builds and starts your app. If you'd rather use your own Dockerfile, you can.
Build without a Dockerfile
Every service you add from GitHub starts on Railpack, even when the repository has a Dockerfile. Railpack detects Node, Python, Ruby, PHP, Go, Rust, Java, Elixir and more; its docs list the files it looks for. Build settings are under the service's Settings → Build, and changes to them are staged until you deploy, except Preferred Builder, which applies at once.

Change the build and start commands
When Railpack picks the wrong build step:
- Open the service and go to Settings → Build.
- Click Build command and enter the command, like
pnpm run build. - Deploy.
Railpack still works out the rest, like installing dependencies. To change how your app
starts, set Start command under Settings → Deploy, like node server.js. It runs in a
shell, so $PORT and && work.
For anything else, like extra system packages, add a railpack.json to the root directory or
set Railpack's own RAILPACK_* variables on the service.
Build with a Dockerfile
Use your Dockerfile when you already have one that works, or when your app needs more than Railpack can work out.
The build starts in the service's root directory: COPY . . copies that folder, and
Dockerfile path is relative to it. To build one app of a monorepo, set its root directory
first; see Deploy a monorepo.
- Open the service and go to Settings → Build.
- Set Build method to Dockerfile.
- If your Dockerfile isn't
Dockerfilein the root directory, enter its path in Dockerfile path. - Deploy.
Dockerfile path suggests paths from the top of the repository, so with a root directory set, shorten them to start from it.
A Start command on a Dockerfile build replaces the Dockerfile's ENTRYPOINT and CMD and runs
without a shell, as on an image service. See
Override the start command.
Use variables at build time
Every variable of the service reaches its build, secrets included, with references to other services filled in. Changing one rebuilds the service.
Railpack gives them to every build step and keeps their values out of the image's metadata.
A Dockerfile gets them as build arguments. Declare each one a step needs with
ARG:dockerfile1 ARG NEXT_PUBLIC_API_URL 2 RUN npm run build
Warning
A build can keep what it reads. Docker saves the build arguments a RUN step uses in the
image's history, and any step can print a value into the build log or write it into the
image. Don't pass long-lived secrets to a Dockerfile as ARGs.
Builds on GitHub Actions get your variables too.
Install private packages
Builds have no SSH keys or registry logins of their own. Give the build a token through a
secret variable instead. For a private npm package, add a variable NPM_TOKEN and an .npmrc
next to your package.json:
| 1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} |
Railpack builds see NPM_TOKEN as it is. A Dockerfile needs ARG NPM_TOKEN before the
install step, so give it a short-lived token. Private Git dependencies work the same way, over
HTTPS with a token in the URL.
A token can't get a Dockerfile FROM a private image: use a public base image.
What a build can reach
Build steps reach the internet over IPv4, so package registries and Git hosts work. They can't reach the server running the build, the private network Ployz runs between your servers, or your services on it. Fetch what a build needs from the internet, and talk to your services after deploy.
A build step can still reach any port your services publish on a public address, like a web address on 80 and 443, and your other servers' public addresses. Don't leave anything on those addresses open without a login. It can't reach the build server's local network, like a cloud VPC or office LAN, any other private address, or the cloud's metadata service, even through a port published there. Its DNS keeps working, so port 53 stays open to any address, private ones too.
A Dockerfile ADD of a URL or Git repository reaches the internet, and nothing on the server
running the build or your servers' private network, except the image servers Ployz uses to share
build images between your servers. Unlike a build step, it still reaches the build server's local
network. If Ployz can't put that limit in place, the build fails instead of running without it.
When your servers mix x86 and ARM
- With Railpack, there's nothing to do: Ployz builds the service for both.
- With a Dockerfile, the image only runs on the kind of CPU of the server that built it. A deploy that would start it on the other kind fails before it changes anything.
To deploy a Dockerfile service, switch it to Railpack, or run it on one kind of server:
Turn off services on the servers of the other kind: on each one's page, under Services, turn off Run services here. This applies to every service on that server, and your next deploy moves this one off it.
Build on the kind that's left: make a server of that kind the service's Preferred Builder, or build on GitHub Actions.
Good to know
- Keep files out of the build with a
.dockerignorein the root directory. It works with Railpack and with Dockerfiles. - Keep secrets on your computer by listing them in
.gitignore. A.dockerignorekeeps a file out of your image, butployz upstill uploads it. In a Git checkout,ployz upleaves out every file Git ignores, so add.envto.gitignore. If you committed.envbefore, Git still keeps it, so also rungit rm --cached .env. Outside a Git checkout it uploads every file, so move.envout of the directory first. See Deploy a directory.