Skip to main content

Deploy guide

Deploy any app with a Dockerfile to TOSE

Any language works on TOSE when the repository has a Dockerfile. TOSE builds it and runs the container on the project port.

Before you start

  • A GitHub repository with a file named Dockerfile at its root.
  • The container serves HTTP on one port, 3000 unless you change the project port.
  • A TOSE account and a workspace at app.tose.sh, with the repository connected through the TOSE GitHub App.
  • Node.js, to install the TOSE CLI: npm install -g @tosesh/tose. You can also do every step in the dashboard.

The example

These files are the example app in the tose-web repository. Its test builds the image for linux/amd64, starts the container and requests the page.

Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY server.js ./
USER node
ENV PORT=3000
EXPOSE 3000
CMD ["node", "server.js"]
server.js
const http = require('node:http');

const port = Number(process.env.PORT || 3000);

http
  .createServer((req, res) => {
    res.writeHead(200, { 'content-type': 'text/plain' });
    res.end('Hello from a Dockerfile on TOSE\n');
  })
  .listen(port, '0.0.0.0', () => console.log(`listening on 0.0.0.0:${port}`));

Deploy it

  1. 1. Put the Dockerfile at the root of the repository

    TOSE builds the file named Dockerfile at the repository root.

  2. 2. Check the image locally

    TOSE builds for linux/amd64. Build for the same platform and open http://localhost:3000.

    docker build --platform linux/amd64 -t my-app .
    docker run --rm -p 3000:3000 my-app
  3. 3. Create the project

    In the dashboard, create a project from the GitHub repository and keep port 3000, or run tose up in the repository and answer its questions. Either way you do this once.

    tose up
  4. 4. Deploy and check

    Every later deploy is one command. Use the build log when the build fails and the live log when the app does not answer.

    tose deploy my-workspace/my-app --json
    tose status my-workspace/my-app --json
    tose logs my-workspace/my-app --build -n 200
    tose logs my-workspace/my-app -n 100
  5. 5. Set environment variables

    Select the project, set variables, then redeploy so the container starts with them. Never commit secrets to the repository.

    tose use my-workspace/my-app
    tose env set DATABASE_URL=… API_BASE_URL=…
    tose redeploy

app.tose.sh

Notes for this stack

  • The example is a Node.js server, but the rules are the same for Python, Ruby, PHP, Rust or Java: bind 0.0.0.0, listen on the project port, and keep data you need on a persistent disk.
  • Without a Dockerfile, TOSE detects common stacks (package.json, go.mod and others) and generates one. Commit your own when you need a predictable build.

Size and cost

  • A new project gets 1 vCPU, 2 GB RAM and 1 replica. You can change vCPU and RAM in the dashboard to 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16.
  • Until the workspace wallet has a positive balance, a project can use at most 2 vCPU and 2 GB RAM.
  • At the base price, the default size costs $29.20 for a month of 730 hours.

Prices and calculator

When something fails

"no Dockerfile in project and OPENROUTER_KEY not configured for AI generation"
TOSE found no Dockerfile. Add one named exactly Dockerfile at the repository root.
"AI Dockerfile generation failed"
TOSE could not generate a Dockerfile for this repository. Commit your own, starting from the example on this page.
The deploy finishes but the app does not answer or keeps restarting
The app must listen on 0.0.0.0 and on the project port (3000 by default). TOSE does not set PORT for you; set it in the Dockerfile or with tose env set. Read tose logs for the crash.
The build stops without an error from your code
Builds get 2 GB of memory, 2 CPUs and 45 minutes. Cut build memory (for example fewer parallel jobs) or install fewer dependencies.
"exec format error" when the container starts
The image or a binary in it is not for linux/amd64. Use base images that publish amd64 and do not pin another platform.

Next