---
title: "How to deploy a React Router app in 2026: the template's Dockerfile, one command and HTTPS | Pethost"
description: "Deploy a React Router app with server rendering: pethost deploy builds the template's own Dockerfile and serves it over HTTPS in 11 seconds, for €9.99 a month."
---

[Blog](https://pethost.dev/blog/) · Deploy guides

# How to deploy a React Router app in 2026: the template's Dockerfile, one command and HTTPS

By the Pethost team · 10 October 2026 · 7 min read

You made an app with `create-react-router`, it renders on the server, and you want it online at an address with HTTPS. The default template already has a Dockerfile, and on Pethost that is all a project needs: run `pethost deploy` in the app's folder. The template was built and started in 11 seconds the first time, and answered 200 at its new address.

**In short**

- **One command:** `pethost deploy` in the folder that `create-react-router` made. Nothing is added to the app and no build settings are filled in.
- **What it does:** uploads the folder, builds the template's own Dockerfile on your machine and starts `react-router-serve`.
- **The port:** the server listens on 3000. Pethost finds that and sends the address there, over HTTPS.
- **The address:** `https://my-app.yourname.pethost.app` at once. Your own domain is one DNS record.
- **The price:** €9.99 a month for a machine of 2 vCPU, 3 GB and 30 GB that runs this app and every other project you have. There is no free tier.

## What you need to deploy a React Router app in 2026

Three things: the app, the `pethost` command and a Pethost account.

**The app** here is the default template, with server rendering and Tailwind CSS:

```
npx create-react-router@latest my-app
```

It leaves `package.json`, `package-lock.json`, the `app/` folder and a `Dockerfile`. Its scripts are the ones the Dockerfile runs:

```
"scripts": {
  "build": "react-router build",
  "dev": "react-router dev",
  "start": "react-router-serve ./build/server/index.js",
  "typecheck": "react-router typegen && tsc"
}
```

**The command** is one program, installed by one line. Every command it has is in the [CLI's reference](https://pethost.dev/docs/cli/).

```
curl -fsSL https://pethost.dev/install.sh | sh      # macOS, Linux
irm https://pethost.dev/install.ps1 | iex           # Windows, in PowerShell
```

**The account** needs a plan. If you are not signed in, `pethost deploy` opens your browser and signs you in. If you have no plan yet, it shows you where to choose one, and waits.

## Deploy the React Router app with one command

Go to the app's folder and run `pethost deploy`. This is the whole screen, for the default template:

```
$ cd my-app
$ pethost deploy
Name it [my-app]:    it will live at https://my-app.sam.pethost.app
✓ Packed 22 files, 174 KB   (left out node_modules)
✓ Uploaded straight to your machine
✓ Built and started in 11 s
  · wrote compose.yaml for the Dockerfile: the service app, reading .env
✓ app listens on 3000 → https://my-app.sam.pethost.app
  It answers 200.

https://my-app.sam.pethost.app

Wrote .pethost (commit it). Next:   pethost logs -f   ·   pethost open
```

1. **It asks one thing** The project's name, which is the first word of its address. Enter takes the folder's name.
2. **The folder goes to your machine** Without `node_modules`: the build installs them there, from `package-lock.json`.
3. **The machine builds the Dockerfile** It is the template's own, unchanged. The line under it says the one thing the machine added: a Compose file around the Dockerfile, with a service called `app`.
4. **The app starts and is asked** The machine sees that the server listens on 3000 and sends the address there. Then pethost asks the address itself, and prints what it answered: 200.

We asked the deployed template what a visitor asks. The home page answered 200 with the server-rendered HTML, `/favicon.ico` answered 200, and an address with no route answered 404 with React Router's own error page.

The file `.pethost` says which project this folder is. Commit it, and the next deploy asks nothing.

## The Dockerfile of the React Router template

This is the file `create-react-router` wrote, which the machine built as it is:

```
FROM node:24-alpine AS development-dependencies-env
COPY . /app
WORKDIR /app
RUN npm ci

FROM node:24-alpine AS production-dependencies-env
COPY ./package.json package-lock.json /app/
WORKDIR /app
RUN npm ci --omit=dev

FROM node:24-alpine AS build-env
COPY . /app/
COPY --from=development-dependencies-env /app/node_modules /app/node_modules
WORKDIR /app
RUN npm run build

FROM node:24-alpine
COPY ./package.json package-lock.json /app/
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
WORKDIR /app
CMD ["npm", "run", "start"]
```

Three things to know about it on Pethost:

- **It needs the lockfile.** Both `npm ci` steps read `package-lock.json`, so keep it in the folder and in your repository.
- **No port is declared.** The file has no `EXPOSE` line and needs none: the machine finds the port the running server listens on.
- **The app is small when it runs.** The last stage holds the production dependencies and the build. The running template took 79 MB of memory.

An app that has no Dockerfile is not stuck. In a folder with neither a Dockerfile nor a Compose file, `pethost deploy` writes the Dockerfile for the kinds of project it knows, as it does for a [Nuxt app](https://pethost.dev/blog/deploy-nuxt-app/), and for any other folder it says why it wrote none.

## Change a route and deploy again

Edit a route and run the same command. The second deploy of the template took 6 seconds, because the machine keeps the build's layers:

```
$ pethost deploy
my-app (.pethost)
✓ Packed 23 files · uploaded · built and started in 6 s
  · wrote compose.yaml for the Dockerfile: the service app, reading .env
  · kept the project's x-pethost
  It answers 200.
https://my-app.sam.pethost.app
```

To deploy on every push instead, connect the repository once:

```
pethost github sam/my-app          # from now on, every push deploys itself
```

Pethost reads only the repositories you gave its GitHub App. If a deploy goes wrong, `pethost rollback` puts the version before it back, and your machine keeps the three versions before the current one. An AI agent can do all of this for you through Pethost's MCP server: [how an agent deploys and looks after a project](https://pethost.dev/blog/hosting-for-ai-coding-agents/).

## Environment variables and your own domain

A variable that a loader or an action reads on the server is one command. It asks for the value without showing it, puts it into the project's `.env` file on the machine, and later deploys keep it:

```
pethost env set SESSION_SECRET
```

Any name under your account's domain is an address at once, with HTTPS. A domain you own takes one command and one DNS record:

```
pethost domain add app.example.com
```

The command prints the record to make: a CNAME from your name to your machine's name. The certificate comes by itself once the name resolves, and renews itself. `pethost password` puts a password page in front of the whole app, for one that is not public yet.

## What you get for the price

Pethost is €9.99 a month for everything you host, on 2 vCPU, 3 GB of memory and 30 GB of disk. The template's server took 79 MB of that memory, so the machine has room for the app's database, a worker and your other projects. There is [no fee per project](https://pethost.dev/blog/unlimited-projects-flat-monthly-fee/) and [nothing metered](https://pethost.dev/blog/paas-without-usage-based-billing/): server rendering is not billed by the request, and a busy month costs what a quiet one does.

- **€9.99** a month for the whole machine
- **11 s** to build and start the template, the first time
- **79 MB** of memory for the running app

What is already done on it: HTTPS with certificates that renew themselves, deploys from GitHub, nightly backups kept for 14 days, SSH into any container, and every request counted, with the busiest paths and the error rate of the last 30 days. The machine is always on, so the first request of the morning [never waits for a cold start](https://pethost.dev/blog/always-on-hosting-no-cold-starts/). The plans are on the [pricing](https://pethost.dev/#pricing) part of the first page.

**Every project, labeled.** Six projects on one Starter machine, each with its address and its requests of the last day.

![The Pethost panel's first page: the machine's CPU, memory and disk, and six projects as cards.](https://pethost.dev/shots/projects.webp)

### Pethost is the best pick for

- **Developers with a full-stack React app**: the server-rendered app and its database on one machine, on one bill
- **Solo developers** with several side projects, each at an address of its own
- **People whose agent deploys for them**: Claude Code or Codex puts the app online and reads its logs
- **Early startups** who want a fixed monthly cost while the product is small

### Look elsewhere if

- Your application needs several regions or autoscaling

## Questions

### Where can I host a React Router app with server rendering?

On any host that runs a Node server or a Docker container. On Pethost you run `pethost deploy` in the app's folder: the machine builds the template's Dockerfile, starts `react-router-serve` and serves the app over HTTPS.

### Do I need to change the Dockerfile that create-react-router writes?

No. The machine built the default template's Dockerfile as it is. It has no `EXPOSE` line and needs none: Pethost finds the port the server listens on, 3000.

### Can I deploy a React Router app from GitHub on every push?

Yes. Deploy the folder once with `pethost deploy`, then run `pethost github owner/repository`. From then on every push to the repository deploys itself, and `pethost rollback` goes back to an earlier commit.

### How do I set environment variables for a React Router app?

Run `pethost env set NAME` in the app's folder. It asks for the value without showing it and puts it into the project's `.env` file on the machine, which the server reads and every later deploy keeps.

### What does it cost to host a React Router app on Pethost?

€9.99 a month for the Starter machine of 2 vCPU, 3 GB and 30 GB, with no fee per project and no charge per request: the same machine runs your other apps, sites and databases. There is no free tier. Prices are without VAT.

The screens are deploys of the default template that `create-react-router` writes, with React Router 8.4.0 and pethost 0.2.1, on a test machine of ours. The account in them is the example one, `sam`.

1. [React Router: installation](https://reactrouter.com/start/framework/installation)
2. [React Router: deploying](https://reactrouter.com/start/framework/deploying)
3. [React Router: the official templates](https://github.com/remix-run/react-router-templates)
4. [pethost, the command line of Pethost](https://pethost.dev/docs/cli/)

## Put your projects online today

A machine of your own, as many projects as fit, one flat price. Nothing metered, nothing billed on top.

[Host all your projects for €9.99/mo](https://console.pethost.dev/)

## Keep reading

- 10 October 2026 [How to deploy a TanStack Start app in 2026: Nitro, a start script and one command](https://pethost.dev/blog/deploy-tanstack-start-app/) Deploy TanStack Start on a Node server: add Nitro and a start script, run pethost deploy, and the app is online over HTTPS in 29 seconds, for €9.99 a month.
- 10 October 2026 [How to deploy a VitePress site in 2026: one command, HTTPS and a Dockerfile you keep](https://pethost.dev/blog/deploy-vitepress-site/) Deploy a VitePress site with one command: pethost deploy writes the Dockerfile, builds the site and serves it over HTTPS, on a machine that is €9.99 a month.
- 10 October 2026 [How to deploy an Eleventy site in 2026: one command, HTTPS and a Dockerfile you keep](https://pethost.dev/blog/deploy-eleventy-site/) Deploy an Eleventy (11ty) site with one command: pethost deploy writes the Dockerfile, builds _site and serves it over HTTPS, on a machine for €9.99 a month.
- 10 October 2026 [How to self-host RSSHub in 2026: its Compose file, one command and HTTPS](https://pethost.dev/blog/self-host-rsshub/) Self-host RSSHub with its own Docker Compose file, unchanged: run pethost deploy and get HTTPS, with Redis and Browserless running, for €9.99 a month.

[All articles](https://pethost.dev/blog/) · [About Pethost](https://pethost.dev/about/) · [Pricing](https://pethost.dev/#pricing)

Pethost · Stephan Gomer · NIP 1133096755

[Home](https://pethost.dev/) [About](https://pethost.dev/about/) [Blog](https://pethost.dev/blog/) [Terms](https://pethost.dev/terms/) [Privacy](https://pethost.dev/privacy/) [Refunds](https://pethost.dev/refunds/) [support@pethost.dev](mailto:support@pethost.dev)
