Sign In
Getting Started

Rivet Containers

Rivet Containers allows you to deploy any application packaged as a Docker container to the cloud. Deploy web servers, game backends, or any custom service with complete control over your runtime environment.

Rivet Cloud is currently intended for enterprise clients that need a scalable, high-performance way to deploy Rivet Functions, Actors, and Containers.

Please reach out for access for access to Rivet Cloud. To deploy RivetKit without Rivet Cloud, see our self-hosting documentation.

What are containers good for?

  • High-Memory Workloads: Applications requiring substantial RAM for processing large data. For example, PDF Processing with document parsing and transformation.
  • CPU-Heavy Workloads: Tasks demanding significant computational resources. For example, Media Transcoding with FFmpeg for video conversion.
  • Browser Automation: Headless browsers for testing, scraping, or rendering. For example, Web Scraping with Puppeteer or Playwright.
  • Sandboxed Code Execution: Safely running untrusted code in isolated environments. For example, MMOs or First-Person Shooters.
  • Headless Game Servers: Game backends without rendering requirements. For example, Turn-Based Game Logic for chess or card games.
  • Custom Dependencies: Applications requiring specific system libraries or tools. For example, Computer Vision Processing with OpenCV dependencies.

Quickstart

Step 1: Writing a Dockerfile

Create a simple HTTP server in your project:

server.js
const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end("Hello from Rivet Container!");
});

const port = process.env.PORT_HTTP;
server.listen(port, () => {
  console.log(`HTTP server running on port ${port}`);
});

Create a Dockerfile in your project directory:

Dockerfile
FROM node:22-alpine

WORKDIR /app

COPY package.json ./
RUN npm install

COPY . .

# Create rivet user and set proper permissions
RUN addgroup -S rivet && \
    adduser -S -G rivet rivet && \
    chown -R rivet:rivet /app

# Switch to non-root user
USER rivet

CMD ["node", "server.js"]

We'll pass the ports & env vars used in the Dockerfile in Step 3. Read more in the API docs for actors.create.

Step 2: Deploying a container

Specify the Dockerfile in your rivet.json:

rivet.json
{
  "containers": {
    "my-container": {
      "dockerfile": "Dockerfile"
    }
  }
}

Now deploy your container with:

Command Line
rivet deploy

Step 3: Starting a container

In this step, you're requesting Rivet to launch your containerized application in the cloud:

TypeScript
import { RivetClient } from "@rivet-gg/api";

// Initialize the Rivet client with your API token
// You can get this from the Rivet dashboard
const client = new RivetClient({
  token: process.env.RIVET_TOKEN
});

// Create a container - this launches your container on Rivet's infrastructure
const { actor } = await client.actors.create({
  // Your project and environment IDs from the Rivet dashboard
  project: "your-project-id",
  environment: "your-environment-id",
  body: {
    // Tags help identify this specific container instance
    // You can query containers by these tags later
    tags: { name: "my-container" },
    
    // buildTags determine which container code to run
    // This should match tags in your rivet.json build configuration
    // The current tag is automatically assigned on deploy
    buildTags: { name: "my-container", current: "true" },
    
    // Network configuration for your container
    network: {
      ports: {
        http: {
          // The protocol used for communication
          protocol: "https",
        }
      }
    },
    
    // Optional: Specify a region for lower latency to specific users
    // If not specified, Rivet will choose the optimal region
    // region: "atl",
    
    // Container resources specification
    resources: {
      cpu: 1000,       // Number of CPU thousanths of a core
      memory: 1024,    // Memory in MB
    }
  }
});

// The actor.id is a unique identifier for this container instance
console.log("Created container:", actor.id);

While this feature is called "Containers" in the UI and documentation, the underlying API uses the term "actors" (e.g., client.actors.create). This is because there is a lot of overlap between the actor & container APIs.

What happens during creation:

  • Rivet finds the latest build matching your buildTags
  • It provisions resources in the specified region (or chooses the best one)
  • It starts your container with the provided environment variables
  • The container starts running based on your Dockerfile's CMD or ENTRYPOINT

See actors.create for more options.

Step 4: Connecting to a container

Once your container is running, you can access its URL directly from the container object:

TypeScript
// The actor response includes the URL information
// You can access it for any port you configured
const httpUrl = actor.network.ports.http.url;

// The URL is a public endpoint to your container
console.log("Container HTTP URL:", httpUrl);

// Use the URL to communicate with your container
// In this example, we're calling our HTTP server
const response = await fetch(httpUrl);
const text = await response.text();
console.log("Response from container:", text);

What happens during connection:

  • Each port configured for your container gets a unique URL
  • These URLs are accessible based on your container's security settings
  • The URL routes to your container regardless of which region it's in
  • For additional security, you can use getConnection to generate temporary, authenticated URLs

See actors.get for more details.

Step 5: Destroying a container

When you're finished using the container, it's important to destroy it to free up resources:

TypeScript
// Destroy the container to free up resources and stop billing
await client.actors.destroy(actor.id, {
  project: "your-project-id",
  environment: "your-environment-id",
});

console.log("Container destroyed");

What happens during destruction:

  • Rivet sends a termination signal to your container
  • Your container gets a short grace period to clean up resources
  • All compute resources associated with the container are freed
  • You stop being billed for the container's runtime

See actors.destroy for more details.

Always destroy containers when you're done with them to avoid unnecessary costs. Containers will continue running and billing will continue until explicitly destroyed.

Configuration Options

When configuring your Docker-based build in rivet.json, you have access to the following options under builds:

OptionDescriptionExample
dockerfilePath to the Dockerfile relative to your project"Dockerfile", "docker/prod.Dockerfile"
imageUse an existing image instead of building"node:22-alpine"
build_pathDirectory containing your build context".", "./backend"
build_targetTarget stage in multi-stage builds"production", "development"
build_argsKey-value pairs passed as build arguments{ "NODE_ENV": "production" }

See the configuration documentation for all available options.

Non-Root User Requirement

For security reasons, Rivet containers cannot run as root. You must explicitly set a non-root user in your Dockerfile.

Different base images require different commands to create non-root users:

RUN addgroup -S rivet && \
    adduser -S -G rivet rivet && \
    chown -R rivet:rivet /app
USER rivet

Runtime Details

Memory & CPU Overcommit

Understanding Rivet's memory and CPU resource allocation helps you optimize performance and avoid unexpected container termination.

Monitor your container's resource usage through the Rivet dashboard to ensure you stay within your allocated limits and avoid performance issues or unexpected termination.

Memory Limits

Rivet uses a two-tier memory allocation system:

  • Soft limit: This is the memory amount you've reserved on the host machine for your container. This is the target amount you should stay under during normal operation.
  • Hard limit: This is set 50% higher than your reserved amount to provide a buffer for unexpected memory spikes. For example, if you reserved 1 GB, your hard limit would be approximately 1.5 GB. Exceeding this hard limit will likely cause your container to be killed.

CPU Throttling

CPU allocation works similarly to memory:

  • The CPU percentage you see in monitoring represents what you should follow to avoid getting throttled during periods of resource contention on the host.
  • Like memory, the CPU has a mechanism that allows for temporary spikes above your allocated amount, but sustained high usage may result in throttling if there's resource contention.
Suggest changes to this page