Custom Base Images

This guide shows how to create and import custom base images for Firecase. Base images are ext4 filesystem images that serve as starting points for instances — pre-loaded with your OS, packages, and configuration.

Why Custom Base Images?

The default base image includes Ubuntu 22.04 with common tools. But you may want:

  • Language-specific images — Python ML stack with PyTorch, CUDA, and Jupyter pre-installed
  • Framework images — Rails, Django, or Next.js with all dependencies cached
  • Security-hardened images — Locked-down images with minimal attack surface
  • Corporate images — Internal tools, VPN configs, certificates pre-installed

Custom images eliminate setup time — every instance forked from your image starts with everything ready.

Building an Image with Docker

The recommended workflow: build a Docker image, export it as an ext4 filesystem, then import it into Firecase.

1. Create a Dockerfile

Dockerfile
FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

# System packages
RUN apt-get update && apt-get install -y \
    build-essential \
    curl \
    git \
    python3 \
    python3-pip \
    nodejs \
    npm \
    vim \
    wget \
    && rm -rf /var/lib/apt/lists/*

# Python ML packages
RUN pip3 install \
    numpy \
    pandas \
    scikit-learn \
    matplotlib \
    jupyter

# Create a default user
RUN useradd -m -s /bin/bash user

# Set up the working directory
WORKDIR /home/user

# Add any config files
COPY .bashrc /home/user/.bashrc

# The guest agent will be injected by Firecase at boot
# Don't worry about it in the Dockerfile

2. Build and Export to ext4

Bash
# Build the Docker image
docker build -t my-base-image .

# Create a container (don't start it)
docker create --name temp-container my-base-image

# Export the filesystem to a tar archive
docker export temp-container > rootfs.tar

# Clean up the container
docker rm temp-container

# Create an ext4 image from the tar
# Size should be larger than the tar to leave room for writes
truncate -s 4G my-image.ext4
mkfs.ext4 my-image.ext4

# Mount and extract
mkdir -p /mnt/image
mount -o loop my-image.ext4 /mnt/image
tar -xf rootfs.tar -C /mnt/image

# Ensure the guest agent directory exists
mkdir -p /mnt/image/usr/local/bin

# Unmount
umount /mnt/image
rmdir /mnt/image

3. Import into Firecase

Upload the ext4 image to the control plane server, then import it:

Bash
curl -X POST https://api.firecase.ai/images/import \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ml-python",
    "description": "Python 3 with NumPy, Pandas, Scikit-learn, Matplotlib, and Jupyter",
    "image_path": "/data/images/my-image.ext4",
    "tags": ["python", "ml", "jupyter"],
    "is_default": false
  }'

The import process:

  1. Reads the ext4 file
  2. Splits it into 16 MiB chunks
  3. Uploads each chunk to S3
  4. Creates a manifest mapping chunk indices to chunk IDs
  5. Registers the base image in the database

4. Use Your Image

Bash
curl -X POST https://api.firecase.ai/instances \
  -H "Authorization: Bearer $API_KEY" \
  -d '{
    "name": "ml-workspace",
    "base_image_id": "{your_image_id}"
  }'

The instance inherits all chunks from your base image via copy-on-write. No data is copied — creation is instant.

Image Sizing Guidelines

Use CaseRecommended Size
Minimal (Alpine-like)512 MiB - 1 GiB
Standard dev tools2 - 4 GiB
ML/Data Science stack4 - 8 GiB
Full IDE + frameworks8 - 16 GiB

Leave at least 20% free space in the image for runtime writes. The ext4 filesystem needs room for journals, temporary files, and user data.

Best Practices

Keep Images Lean

Every byte in the image is a chunk in S3. Smaller images = faster prefetch on first boot.

Dockerfile
# Good: clean up package caches
RUN apt-get update && apt-get install -y python3 \
    && rm -rf /var/lib/apt/lists/*

# Bad: leaves cache around
RUN apt-get update
RUN apt-get install -y python3

Layer Wisely

Since Firecase uses 16 MiB chunks, try to keep related changes in the same filesystem region. In practice, this means:

  • Install all packages in one RUN command
  • Don't create then delete large temporary files (the chunks are still uploaded)

Test Locally First

Before importing, test your image locally:

Bash
# Test with QEMU
qemu-system-x86_64 -m 1024 -drive file=my-image.ext4,format=raw -nographic

Version Your Images

Use descriptive names with versions:

Bash
curl -X POST https://api.firecase.ai/images/import \
  -d '{"name": "ml-python-v2", "tags": ["python", "ml", "v2"]}'

Managing Base Images

List all images

Bash
curl https://api.firecase.ai/base-images \
  -H "Authorization: Bearer $API_KEY"

Delete an image

Bash
curl -X DELETE https://api.firecase.ai/base-images/{id} \
  -H "Authorization: Bearer $API_KEY"

Deleting a base image removes the image record and template instance. Chunks in S3 are preserved because they may be shared with instances that were created from this image.

Next Steps

  • See the Base Images API for all operations
  • Learn about Instances and how they use base images
  • Explore Profiles to set resource limits for different image types