Out Plane LogoOut Plane

Dockerfile

Deploy any application using a custom Dockerfile on Out Plane

This guide explains how to deploy any application on Out Plane using a custom Dockerfile. Use this approach when you need full control over your build process or when your language isn't covered by our framework-specific guides.

Prerequisites

  • An Out Plane account
  • A GitHub account with your application code
  • A Dockerfile in your repository

Dockerfile Basics

A Dockerfile defines how to build your application container. Here's the basic structure:

# Base image
FROM node:20-alpine

# Set working directory
WORKDIR /app

# Copy dependency files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy application code
COPY . .

# Expose port
EXPOSE 3000

# Start command
CMD ["node", "server.js"]

Multi-Stage Builds

Use multi-stage builds to create smaller production images:

# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]

This separates build tools from the final image, reducing size significantly.

The .dockerignore File

Create a .dockerignore file to exclude unnecessary files from the build context:

# Dependencies
node_modules
vendor

# Version control
.git
.gitignore

# Environment files
.env
.env.*

# Build artifacts
dist
build
*.log

# IDE files
.vscode
.idea
*.swp

# OS files
.DS_Store
Thumbs.db

Deploy on Out Plane

Step 1: Push to GitHub

Ensure your repository contains:

  • Your application code
  • A Dockerfile in the root (or specified subdirectory)
  • A .dockerignore file (recommended)
git add .
git commit -m "Add Dockerfile"
git push origin main

Step 2: Create Application

  1. Go to console.outplane.com
  2. Navigate to Applications
  3. Click Deploy Application
  4. Install the GitHub App if prompted

Step 3: Select Repository

  1. Find and select your repository
  2. Choose the branch to deploy
  3. Set Root Directory (where Dockerfile is located)

Step 4: Configure Build

SettingValue
Build MethodSelect Dockerfile
Application NameEnter a unique name
PortThe port your app listens on

Step 5: Select Resources

InstancevCPURAMUse Case
op-200.5512 MBDevelopment
op-4611 GBSmall apps
op-8222 GBProduction
op-9444 GBHigh performance

Step 6: Configure Scaling

  • Min Scale: 0 for scale-to-zero, 1+ for always-on
  • Max Scale: Maximum instances (1-10)

Step 7: Environment Variables

Add any environment variables your application needs.

Step 8: Deploy

Click Create Application to start the deployment.

Requirements for Your Application

Your application must:

1. Listen on the PORT environment variable

// Node.js
const port = process.env.PORT || 3000;
# Python
port = int(os.environ.get("PORT", 8000))
// Go
port := os.Getenv("PORT")
if port == "" {
    port = "8080"
}

2. Bind to 0.0.0.0

Bind to all interfaces, not just localhost:

// Node.js
app.listen(port, '0.0.0.0');
# Python/Uvicorn
uvicorn main:app --host 0.0.0.0 --port $PORT

3. Log to stdout

Write logs to standard output. Out Plane captures and displays these in the console.

Best Practices

Use Specific Base Image Tags

# Good - specific version
FROM python:3.12-slim

# Avoid - mutable tag
FROM python:latest

Leverage Layer Caching

Order your Dockerfile commands from least to most frequently changed:

# Dependencies change less often
COPY requirements.txt .
RUN pip install -r requirements.txt

# Source code changes frequently
COPY . .

Run as Non-Root User

RUN adduser -D appuser
USER appuser
CMD ["./app"]

Use EXPOSE for Documentation

EXPOSE 8080

Note: The actual port is configured in Out Plane settings.

Language-Specific Examples

Ruby on Rails

FROM ruby:3.2-alpine AS builder
RUN apk add --no-cache build-base postgresql-dev
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install --deployment --without development test

FROM ruby:3.2-alpine
RUN apk add --no-cache postgresql-client
WORKDIR /app
COPY --from=builder /app/vendor/bundle vendor/bundle
COPY . .
ENV RAILS_ENV=production
EXPOSE 3000
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

Rust

FROM rust:1.75 AS builder
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=builder /app/target/release/myapp /usr/local/bin/
EXPOSE 8080
CMD ["myapp"]

PHP Laravel

FROM php:8.2-fpm-alpine AS builder
RUN apk add --no-cache composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

FROM php:8.2-fpm-alpine
RUN docker-php-ext-install pdo pdo_pgsql
WORKDIR /app
COPY --from=builder /app/vendor vendor
COPY . .
EXPOSE 8000
CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"]

Troubleshooting

Build fails

  1. Check build logs in the deployment detail page
  2. Verify Dockerfile syntax
  3. Ensure all dependencies are available

App not accessible

  1. Verify your app binds to 0.0.0.0
  2. Check that PORT environment variable is used
  3. Ensure the port in Out Plane matches your app

Image too large

  1. Use multi-stage builds
  2. Use Alpine-based images
  3. Add unnecessary files to .dockerignore

Next Steps