What you’ll learn
In this tutorial, you’ll learn how to:- Create a Dockerfile that extends a Runpod base image.
- Add Python dependencies to an existing base image.
- Pre-package ML models into your custom template.
- Build and push Docker images with the correct platform settings.
- Deploy and test your custom template as a Pod.
Requirements
Before you begin, you’ll need:- A Runpod account.
- Docker installed on your local machine.
- A Docker Hub account for hosting your custom images.
- At least $5 in Runpod credits for testing.
- Basic familiarity with Docker and command-line operations.
Step 1: Create a custom Dockerfile
First, you’ll create a Dockerfile that extends a Runpod base image with additional dependencies:- Create a new directory for your custom template:
- Create a new Dockerfile:
- Open the Dockerfile in your preferred text editor and add the following content:
pip install
again after Pod restarts.
When building custom templates, always start with a Runpod base image that matches your CUDA requirements. The base image includes essential components like the
/start.sh
script that handles Pod initialization.CMD
or ENTRYPOINT
in the Dockerfile. Runpod base images include a carefully configured startup script (/start.sh
) that handles Pod initialization, SSH setup, and service startup. Overriding this can break Pod functionality.
Step 2: Add system dependencies
If your application requires system-level packages, add them before the Python dependencies:Always clean up package lists with
rm -rf /var/lib/apt/lists/*
after installing system packages to reduce image size.Step 3: Pre-bake ML models
To reduce Pod setup overhead, you can pre-download models during the Pod initialization process. Here are two approaches:Method 1: Simple model download script
Create a Python script that downloads your model:- Create a file named
download_model.py
in the same directory as your Dockerfile:
- Update your Dockerfile to include and run this script:
Method 2: Using the Hugging Face CLI
For more control over model downloads, use the Hugging Face CLI:Pre-baking large models will significantly increase your Docker image size and build time. Consider whether the faster Pod startup time justifies the larger image size for your use case.
Step 4: Build and push your Docker image
Now you’re ready to build your custom image and push it to Docker Hub:- Build your Docker image with the correct platform specification:
The
--platform=linux/amd64
flag is crucial for Runpod compatibility. Runpod’s infrastructure requires AMD64 architecture images.- Tag your image for Docker Hub (replace
YOUR_USERNAME
with your Docker Hub username):
- Push the image to Docker Hub:
If you haven’t logged into Docker Hub from your command line, run
docker login
first and enter your Docker Hub credentials.Step 5: Create a Pod template in Runpod
Next, create a Pod template using your custom Docker image:- Navigate to the Templates page in the Runpod console.
- Click New Template.
- Configure your template with these settings:
- Name: Give your template a descriptive name (e.g., “My Custom PyTorch Template”).
- Container Image: Enter your Docker Hub image name (e.g.,
YOUR_USERNAME/my-custom-template:latest
). - Container Disk: Set to at least 20 GB to accommodate your custom dependencies.
- Volume Disk: Set according to your storage needs (e.g., 20 GB).
- Volume Mount Path: Keep the default
/workspace
. - Expose HTTP Ports: Add
8888
for JupyterLab access. - Expose TCP Ports: Add
22
if you need SSH access.
- Click Save Template.
Step 6: Deploy and test your custom template
Now you’re ready to deploy a Pod using your custom template to verify everything works correctly:- Go to the Pods page in the Runpod console.
- Click Deploy.
- Choose an appropriate GPU (make sure it meets the CUDA version requirements of your base image).
- Click Change Template and select your custom template under Your Pod Templates.
- Fill out the rest of the settings as desired, then click Deploy On Demand.
- Wait for your Pod to initialize (this may take 5-10 minutes for the first deployment).
Step 7: Verify your custom template
Once your Pod is running, verify that your customizations work correctly:- Find your Pod on the Pods page and click on it to open the connection menu. Click Jupyter Lab under HTTP Services to open JupyterLab.
- Create a new Python notebook and test your pre-installed dependencies:
- Run the cell to confirm everything is working as expected.
Advanced customization options
Setting environment variables
You can set default environment variables in your template configuration:- In the template creation form, scroll to Environment Variables.
- Add key-value pairs for any environment variables your application needs:
- Key:
HUGGINGFACE_HUB_CACHE
- Value:
/workspace/hf_cache
- Key:
Adding startup scripts
To run custom initialization code when your Pod starts, create a startup script:- Create a
startup.sh
file in your project directory:
- Add it to your Dockerfile:
Using multi-stage builds
For complex applications, use multi-stage builds to reduce final image size:Troubleshooting
Here are solutions to common issues when creating custom templates:Build failures
- Platform mismatch: Always use
--platform=linux/amd64
when building. - Base image not found: Verify the base image tag exists on Docker Hub.
- Package installation fails: Check that package names are correct and available for the Python version in your base image.
Pod deployment issues
- Pod fails to start: Check the Pod logs in the Runpod console for error messages.
- Services not accessible: Ensure you’ve exposed the correct ports in your template configuration.
- CUDA version mismatch: Make sure your base image CUDA version is compatible with your chosen GPU.
Performance issues
- Slow startup: Consider pre-baking more dependencies or using a smaller base image.
- Out of memory: Increase container disk size or choose a GPU with more VRAM.
- Model loading errors: Verify that pre-baked models are in the expected cache directories.
Best practices
Follow these best practices when creating custom templates:Image optimization
- Use
.dockerignore
to exclude unnecessary files from your build context. - Combine RUN commands to reduce image layers.
- Clean up package caches and temporary files.
- Use specific version tags for dependencies to ensure reproducibility.
Security considerations
- Don’t include sensitive information like API keys in your Docker image.
- Use Runpod Secrets for sensitive configuration.
- Regularly update base images to get security patches.
Version management
- Tag your images with version numbers (e.g.,
v1.0.0
) instead of justlatest
. - Keep a changelog of what changes between versions.
- Test new versions thoroughly before updating production templates.
Next steps
Now that you have a working custom template, consider these next steps:- Automate builds: Set up GitHub Actions or similar CI/CD to automatically build and push new versions of your template.
- Share with team: If you’re using a team account, share your template with team members.
- Create variations: Build specialized versions of your template for different use cases (development vs. production).
- Monitor usage: Track how your custom templates perform in production and optimize accordingly.