Skip to content
Dashboard

Use a Custom Container Image

The easiest way to understand how to run a containerized application is to see an example. Let’s convert the example from the previous section into a containerized application.

import fal
from fal.container import ContainerImage
from fal.toolkit import Image, optimize
from pydantic import BaseModel, Field
dockerfile_str = """
FROM python:3.11
RUN apt-get update && apt-get install -y ffmpeg
RUN python -m venv .venv
ENV PATH="$PWD/.venv/bin:$PATH"
RUN pip install "accelerate" "transformers>=4.30.2" "diffusers>=0.26" "torch>=2.2.0"
"""
class Input(BaseModel):
prompt: str = Field(
description="The prompt to generate an image from.",
examples=[
"A cinematic shot of a baby racoon wearing an intricate italian priest robe.",
],
)
class Output(BaseModel):
image: Image = Field(
description="The generated image.",
)
class FalModel(
fal.App,
image=ContainerImage.from_dockerfile_str(dockerfile_str),
kind="container",
):
machine_type = "GPU"
def setup(self) -> None:
import torch
from diffusers import AutoPipelineForText2Image
# Load SDXL
self.pipeline = AutoPipelineForText2Image.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
torch_dtype=torch.float16,
variant="fp16",
)
self.pipeline.to("cuda")
# Apply fal's spatial optimizer to the pipeline.
self.pipeline.unet = optimize(self.pipeline.unet)
self.pipeline.vae = optimize(self.pipeline.vae)
# Warm up the model.
self.pipeline(
prompt="a cat",
num_inference_steps=30,
)
@fal.endpoint("/")
def text_to_image(self, input: Input) -> Output:
result = self.pipeline(
prompt=input.prompt,
num_inference_steps=30,
)
[image] = result.images
return Output(image=Image.from_pil(image))

Voila! 🎉 The highlighted changes are the only modifications you need to make; the rest remains your familiar fal application.

fal Specific Considerations

When deploying your application on fal, you don’t need to worry about enabling Docker Buildx or BuildKit. We take care of it for you. However, you can follow the guidelines mentioned above to create efficient Dockerfiles that will help speed up the build process and reduce resource consumption.

1. File Upload Instead of COPY

COPY and ADD (from local filesystem) are not supported as of now to copy files into the container from the host. Instead you can use fal’s fal.toolkit to upload files and refer them in the container using links.

json_url = File.from_path("my-file.json", repository="cdn").url
dockerfile_str = f"""
FROM python:3.11-slim
RUN apt-get update && apt-get install -y curl
RUN curl '{json_url}' > my-file.json
"""

or you can use ADD to directly download the file from the URL:

json_url = File.from_path("requirements.txt", repository="cdn").url
dockerfile_str = f"""
FROM python:3.11-slim
ADD {json_url} /app/requirements.txt
WORKDIR /app
RUN pip install -r requirements.txt
"""

Using Private Docker Registries

To use private docker registries, you need to provide registry credentials like so:

Dockerhub

class FalModel(
fal.App,
kind="container",
image=ContainerImage.from_dockerfile_str(
"FROM myuser/image:tag",
registries={
"https://index.docker.io/v1/": {
"username": "myuser",
"password": "$DOCKERHUB_TOKEN", # use `fal secrets set` first to create this secret
},
},
),
)
...

Google Artifact Registry

class FalModel(
fal.App,
kind="container",
image=ContainerImage.from_dockerfile_str(
"FROM europe-west1-docker.pkg.dev/myuser/image:tag",
registries={
"https://europe-west1-docker.pkg.dev": {
"username": "oauth2accesstoken",
"password": "$GCP_TOKEN", # use `fal secrets set` first to create this secret
},
},
),
)
...

Amazon Elastic Container Registry

class FalModel(
fal.App,
kind="container",
image=ContainerImage.from_dockerfile_str(
"FROM 123456789012.dkr.ecr.us-east-1.amazonaws.com/image:tag",
registries={
"https://1234567890.dkr.ecr.us-east-1.amazonaws.com": {
"username": "AWS",
# Use `aws ecr get-login-password --region us-east-1` to get a token. Note that they only last
# 12 hours so it is better to just create them dynamically here instead of creating one and
# setting it as a `fal secret`.
# https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html
"password": aws_token,
},
},
),
)
...

Build Secrets

We currently only support secret mounts.

class FalModel(
fal.App,
kind="container",
image=ContainerImage.from_dockerfile_str(
"""
FROM python:3.11
RUN --mount=type=secret,id=aws-key-id,env=AWS_ACCESS_KEY_ID \
--mount=type=secret,id=aws-secret-key,env=AWS_SECRET_ACCESS_KEY \
--mount=type=secret,id=aws-session-token,env=AWS_SESSION_TOKEN \
aws s3 cp ...
""",
secrets={
# use `fal secrets set` first to create these secrets
"aws-key-id": "$AWS_ACCESS_KEY_ID",
"aws-secret-key": "$AWS_SECRET_ACCESS_KEY",
"aws-session-token": "$AWS_SESSION_TOKEN",
},
),
):
...

Next steps