The three built-in templates cover most first steps, but sooner or later a team wants its own environment: pinned library versions, a serving stack, a CI toolchain, or a legacy project that only builds in one exact setup. A custom Docker image GPU cloud deployment on Cloudj lets you bring that environment as a public image. This guide explains the rules, how to choose a CUDA base image that works with the host's driver, why image size matters more than you think, and what to do when an image is refused.
The rules for custom images on Cloudj
The console offers three templates: Ubuntu 22.04 + CUDA (SSH), PyTorch + JupyterLab, and Custom image. For the custom one:
- Public images only. You enter a public image reference, for example
pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime. Private registries and local images are not supported, so there is nowhere to enter registry credentials. - Higher account level. Custom images need a higher account level than a new account has. If the option is not available to you, contact Cloudj support from the console.
- Some images are blocked. The console refuses certain images. If yours is refused, choose a different image or build your own on a common base.
- Same billing and limits. Per-minute billing, a disk size fixed at deploy, an end date per machine, and no hardware SLA all still apply.
Keep secrets out of a public image. API keys, tokens and private data belong in environment files or downloads at run time, never in image layers anyone can pull.
Choose a CUDA base that the host driver supports
A container brings its own CUDA runtime libraries, but it uses the host machine's NVIDIA driver. Each driver supports CUDA runtimes up to a certain version. If your image needs a newer CUDA than the host driver supports, GPU code fails at start-up even though the container runs.
Practical rules:
- Do not chase the newest CUDA. Pick the CUDA version your framework actually needs. A slightly older, widely used CUDA 12.x base works on more hosts than the newest release.
- Check the driver after deploy. Run
nvidia-smi; the header shows the highest CUDA version the driver supports. Your image's CUDA should be at or below it. - Hosts differ. Every listing is an independent machine, so drivers vary. If you redeploy elsewhere, check again.
- Prefer runtime over devel images unless you compile CUDA code inside the container.
NVIDIA's CUDA compatibility documentation explains how driver and runtime versions relate.
Image size and load time
Before your container starts, the host must pull your image. Large images take longer to start, and you are paying while the instance runs. Each result in the deploy list shows the machine's download speed in Mbps, which is a good hint for how long the pull will take.
Ways to keep images lean:
| Practice | Why it helps |
|---|---|
Start from a runtime tag, not devel | Devel images include compilers and headers you may not need |
| Use multi-stage builds | Build tools stay in the build stage |
| Do not bake model weights into the image | Download weights to the instance disk at start |
| Clean package caches in the same layer | apt-get clean and pip install --no-cache-dir |
| Pin versions | Reproducible builds and fewer surprise rebuilds |
Weights especially deserve care: a model of tens of gigabytes inside an image means every redeploy pulls it again. Plan disk size for weights separately, since it cannot be resized later.
A minimal example
A small image with a pinned PyTorch base and your code:
FROM pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime
RUN apt-get update && apt-get install -y --no-install-recommends tmux git \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r /app/requirements.txt
COPY . /app
WORKDIR /app
Build and push to a public repository:
docker build -t yourname/gpu-app:1.0 .
docker run --rm --gpus all yourname/gpu-app:1.0 python -c "import torch; print(torch.cuda.is_available())"
docker push yourname/gpu-app:1.0
Testing locally with --gpus all, if you have an NVIDIA GPU, catches most mistakes before you pay for a cloud instance. If you are new to Docker, installing Docker on a VPS is a good place to practise building images, and the Docker documentation covers multi-stage builds.
Then, on the GPU deploy page, choose your machine, select the Custom image template, enter yourname/gpu-app:1.0, pick disk size and your SSH key, and deploy. The instance page shows status and the last lines of the container logs, which is the first place to look if the image does not start.
When a custom image is worth it
- Serving stacks. A pinned vLLM or other serving image avoids reinstalling on every redeploy; a vLLM inference server in the US discusses both the pip and image routes.
- CI for ML code. A fixed image makes GPU test runs reproducible; a GPU CI runner for ML tests builds on this.
- Legacy projects that need an exact old toolchain.
When it is not worth it: for exploration, the PyTorch + JupyterLab template is quicker. Running PyTorch with the Jupyter template covers that path.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Image refused in the console | Private image, typo, or blocked image | Make it public, check the reference, or use another base |
| Long wait before start | Large image, slow host download | Slim the image; pick a host with higher download speed |
CUDA driver version is insufficient | Image CUDA newer than host driver | Use an older CUDA base |
| Container exits immediately | Image command ends at once | Check the logs on the instance page and test locally |
FAQ
Can I use a private registry?
No. Only public images are supported.
Why can't I select Custom image?
It needs a higher account level. Contact Cloudj support from the console.
Which CUDA version should my image use?
The one your framework needs, kept at or below what the host driver supports. Check with nvidia-smi.
Should model weights go in the image?
Usually not. Download them to the instance disk, sized at deploy.
Next step
Build and test your image locally, push it to a public repository, then open the GPU deploy page and deploy it with the Custom image template. Live "from" prices for every model are on GPU cloud.