Using existing images
This guide walks you through how to use an existing container image as a Modal Image.
sklearn_image = modal.Image.from_registry("huanjason/scikit-learn")
custom_image = modal.Image.from_dockerfile("./src/Dockerfile")
Load an image from a public registry with .from_registry
You can use an image from a public container registry like Docker Hub with Modal using Image.from_registry
, so long as:
- Python 3.9 or later is installed on the
$PATH
aspython
pip
is installed correctly- The image is built for the
linux/amd64
platform - The image has a valid
ENTRYPOINT
Just pass the image name, including any tags, to Image.from_registry
:
sklearn_image = modal.Image.from_registry("huanjason/scikit-learn")
@app.function(image=sklearn_image)
def fit_knn():
from sklearn.neighbors import KNeighborsClassifier
...
If an existing image does not have either python
or pip
set up properly, you
can still use it. Just provide a version number as the add_python
argument to
install a reproducible standalone build of Python:
ubuntu_image = modal.Image.from_registry("ubuntu:22.04", add_python="3.11")
valhalla_image = modal.Image.from_registry("gisops/valhalla:latest", add_python="3.12")
The from_registry
method can load images from all public registries, such as Nvidia’s nvcr.io
, AWS ECR, and GitHub’s ghcr.io
.
Load images from private registries
You can also use images defined in private container registries on Modal. The exact method depends on the registry you are using.
Docker Hub (Private)
To pull container images from private Docker Hub repositories, create an access token with “Read-Only” permissions and use this token value and your Docker Hub username to create a Modal Secret.
REGISTRY_USERNAME=my-dockerhub-username
REGISTRY_PASSWORD=dckr_pat_TS012345aaa67890bbbb1234ccc
Use this Secret with the modal.Image.from_registry
method.
Elastic Container Registry (ECR)
You can pull images from your AWS ECR account by specifying the full image URI as follows:
import modal
aws_secret = modal.Secret.from_name("my-aws-secret")
image = (
modal.Image.from_aws_ecr(
"000000000000.dkr.ecr.us-east-1.amazonaws.com/my-private-registry:latest",
secret=aws_secret,
)
.pip_install("torch", "huggingface")
)
app = modal.App(image=image)
As shown above, you also need to use a Modal Secret containing the environment variables AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
, and AWS_REGION
. The AWS IAM user account associated
with those keys must have access to the private registry you want to access.
Alternatively, you can use OIDC token authentication.
The user needs to have the following read-only policies:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["ecr:GetAuthorizationToken"],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:DescribeImages",
"ecr:BatchGetImage",
"ecr:GetLifecyclePolicy",
"ecr:GetLifecyclePolicyPreview",
"ecr:ListTagsForResource",
"ecr:DescribeImageScanFindings"
],
"Resource": "<MY-REGISTRY-ARN>"
}
]
}
You can use the IAM configuration above as a template for creating an IAM user. You can then generate an access key and create a Modal Secret using the AWS integration option. Modal will use your access keys to generate an ephemeral ECR token. That token is only used to pull image layers at the time a new image is built. We don’t store this token but will cache the image once it has been pulled.
Images on ECR must be private and follow image configuration requirements.
Google Artifact Registry and Google Container Registry
For further detail on how to pull images from Google’s image registries, see modal.Image.from_gcp_artifact_registry
.
Bring your own image definition with .from_dockerfile
You can define an Image from an existing Dockerfile by passing its path to Image.from_dockerfile
:
dockerfile_image = modal.Image.from_dockerfile("Dockerfile")
@app.function(image=dockerfile_image)
def fit():
import sklearn
...
Note that you can still extend this Image using image builder methods! See the guide for details.
Dockerfile command compatibility
Since Modal doesn’t use Docker to build containers, we have our own implementation of the Dockerfile specification. Most Dockerfiles should work out of the box, but there are some differences to be aware of.
First, a few minor Dockerfile commands and flags have not been implemented yet.
These include ONBUILD
, STOPSIGNAL
, and VOLUME
.
Please reach out to us if your use case requires any of these.
Next, there are some command-specific things that may be useful when porting a Dockerfile to Modal.
ENTRYPOINT
While the ENTRYPOINT
command is supported, there is an additional constraint to the entrypoint script
provided: when used with a Modal Function, it must also exec
the arguments passed to it at some point.
This is so the Modal Function runtime’s Python entrypoint can run after your own. Most entrypoint
scripts in Docker containers are wrappers over other scripts, so this is likely
already the case.
If you wish to write your own entrypoint script, you can use the following as a template:
#!/usr/bin/env bash
# Your custom startup commands here.
exec "$@" # Runs the command passed to the entrypoint script.
If the above file is saved as /usr/bin/my_entrypoint.sh
in your container,
then you can register it as an entrypoint with ENTRYPOINT ["/usr/bin/my_entrypoint.sh"]
in your Dockerfile, or with entrypoint
as an
Image build step.
import modal
image = (
modal.Image.debian_slim()
.pip_install("foo")
.entrypoint(["/usr/bin/my_entrypoint.sh"])
)
ENV
We currently don’t support default values in interpolations,
such as ${VAR:-default}