Docker Containers

Deploy any language or framework to Telbase with a Dockerfile. Java, Ruby, Rust, PHP, C#, Elixir — if it runs in a container, it runs on Telbase, on Google Cloud Run.

When to Use Docker

Python, Go and Node apps on Cloud Run build without a Dockerfile (buildpacks). When a Dockerfile only does what that build does, your agent deploys without it.

Paid plan required
Docker deployments are available on all paid plans. Starter: 1 container, Builder: 3, Pro: 15. See pricing for details.

Requirements

  1. Paid plan — Docker containers are available on all paid plans (Starter: 1, Builder: 3, Pro: 15)
  2. PORT environment variable — Cloud Run sets a PORT env var at runtime (8080 unless the deploy passes --port). Your container must listen on it.
  3. Dockerfile in the directory you deploy from — --source . uploads that directory, and Cloud Run builds its Dockerfile
bash
telbase apps create api --provider cloudrun
telbase apps info api    # prints the deploy command, run from the same directory:
telbase gcloud run deploy <service> --source . --region us-central1 --allow-unauthenticated --quiet

The ENTRYPOINT Pitfall

Docker's exec form (["command", "arg"]) does not expand environment variables. This means $PORT stays as a literal string, and your container fails to bind to the right port.

Dockerfile
# WRONG — exec form does not expand $PORT
ENTRYPOINT ["java", "-jar", "app.jar", "--server.port=$PORT"]

# RIGHT — shell form expands $PORT
CMD java -jar app.jar --server.port=$PORT

# RIGHT — explicit shell wrapper with exec form
ENTRYPOINT ["/bin/sh", "-c", "java -jar app.jar --server.port=$PORT"]
Rule of thumb
Use shell form (no brackets) for any CMD or ENTRYPOINT that references environment variables like $PORT.

Build Context

The build context is the directory you deploy from. All COPY and ADD paths in your Dockerfile are relative to it.

Dockerfile — deploying from project root
# Deploying from the project root
COPY backend/pom.xml .
COPY backend/src ./src
Dockerfile — deploying from subdirectory
# Deploying from ./backend
COPY pom.xml .
COPY src ./src

Example Dockerfiles

Quick-start Dockerfiles for common languages. Each uses a multi-stage build to keep the final image small.

Java / Spring Boot

Dockerfile — Java 21 + Spring Boot
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
CMD java -jar app.jar --server.port=$PORT

Ruby / Rails

Dockerfile — Ruby 3.3 + Rails
FROM ruby:3.3
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
RUN bundle exec rake assets:precompile
CMD bundle exec puma -p $PORT

Rust

Dockerfile — Rust (multi-stage)
FROM rust:1.77 AS build
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
COPY src ./src
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=build /app/target/release/myapp /usr/local/bin/
CMD myapp --port $PORT

PHP / Laravel

Dockerfile — PHP 8.3 + Laravel
FROM php:8.3-cli
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev
COPY . .
CMD php artisan serve --host=0.0.0.0 --port=$PORT

Migrating from Other Platforms

If you have an existing Dockerfile from Railway, Fly.io, or Render, it probably works with minimal changes:

Common Issues

IssueCauseFix
Container exits immediatelyNot listening on $PORTUse shell form CMD with $PORT
Build fails on COPYWrong build contextCheck which directory you're deploying from
Port mismatch at runtimeHardcoded port numberReplace with $PORT environment variable
Native dependencies missingAlpine base imageUse Debian-based image (e.g. bookworm-slim)
Build too slowNo dependency cachingCopy dependency files first, install, then copy source

Next Steps