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 falfrom fal.container import ContainerImagefrom 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 .venvENV 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-slimRUN apt-get update && apt-get install -y curlRUN 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-slimADD {json_url} /app/requirements.txtWORKDIR /appRUN 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", }, ),): ...