Skip to main content

Deploying Jobs

This guide covers how to get a job running on a cloud GPU and the common patterns around it: environment, CI, chaining, exec, and debugging.

Deployment Workflows

Two ways to get your code onto a remote VM.

tip

Use the decorator for fast Python iteration on code you'll change often — no image rebuild between runs. Use a prebuilt image + submit for non-Python workloads or hermetic CI-built images.

Function Decorator (Python SDK)

What it is: The @anycloud.function() decorator uses git-based code sync — your repo is cloned at the current commit on the remote VM. Think of it as COPY . /app in your Dockerfile, but always up to date. Your image holds dependencies (PyTorch, CUDA, etc.); your code comes from git. No rebuild between runs, and function arguments are passed directly — no argparse wiring.

When to use: Python workloads where you iterate on code frequently and want to skip the rebuild loop entirely.

Requirements: Python SDK, code committed and pushed to GitHub, git installed in the image.

Example:

@anycloud.function(image="ghcr.io/acme/base:latest", gpu="h100:8")
def train(learning_rate: float, epochs: int = 100):
# Your code is synced here via git — not baked into the image
...

job = train.submit(0.001, epochs=50)

See Python SDK — Function Decorator for the full API.

Prebuilt Image + Submit (CLI, Python SDK)

What it is: The standard Docker workflow — your code is baked into the image via COPY in a Dockerfile, pushed to a registry, then submitted. The running container is a hermetic artifact pinned to a specific image digest, so the same build is reproducible across runs.

When to use: Non-Python workloads or CI/CD pipelines where one image is deployed many times.

Requirements: A pullable image reference. Public registries work without auth; for private images, use GHCR — anycloud login authenticates via GitHub OAuth and anycloud uses the token to pull on the VM.

Examples:

# CLI — submit an image you've already built and pushed to GHCR
anycloud submit ghcr.io/you/repo:latest --credentials my-aws --gpu-type h100
# Python
client.submit("ghcr.io/you/repo:latest", gpu="h100")

How They Relate

The decorator is built on top of submit. Under the hood, @anycloud.function() calls Client.submit() with your image plus a bootstrap script that clones your repo at the exact commit. Either way, you build and push the image yourself — locally or in GitHub Actions (recommended for repeatable builds) — and anycloud pulls it from the registry to run.


GPUs & Resource Limits

Pick GPUs by type (--gpu-type / gpu=) and let anycloud choose the instance, or pin an exact --vm-type. Pass standard Docker runtime flags for shared memory, memory, CPUs, and IPC.

# CLI
# 8 H100 GPUs; anycloud picks the instance.
# Expose all GPUs and give PyTorch DataLoader workers more shared memory.
anycloud submit ghcr.io/you/train:latest \
--credentials my-aws \
--gpu-type h100:8 \
--gpus all \
--shm-size 8g \
--disk-size 200
# Python
job = ac.submit(
"ghcr.io/you/train:latest",
gpu="h100:8", # 8× H100; anycloud picks the instance
docker_options={"shmSize": "8g"},
cloud_config=CloudConfig(credentials="my-aws", disk_size_gb=200),
)

Full lists: Docker runtime options and CloudConfig parameters.

Environment & CI

Environment Variables

# Single variable
anycloud submit my-image -e API_KEY=secret123

# Read from current shell
anycloud submit my-image -e API_KEY

# From .env file
anycloud submit my-image --env-file .env

# Combine (flags take precedence over file)
anycloud submit my-image --env-file .env -e API_KEY=override

CI Pipeline

Every CLI command is flag- and env-driven — there are no prompts to navigate. In CI, pass the GitHub token and credentials name via env vars and the rest as flags:

GITHUB_TOKEN=ghp_... ANYCLOUD_CREDENTIALS_NAME=my-aws \
anycloud submit ghcr.io/user/my-app:latest \
--gpu-type h100 \
--spot
Env VarDescription
GITHUB_TOKENGitHub token for auth
ANYCLOUD_CREDENTIALS_NAMENamed credentials to use (alternative to --credentials)

Chaining Jobs

Chain jobs by waiting for each step before submitting the next:

prep = ac.submit("prep:latest")
prep.wait()

train = ac.submit("train:latest", gpu="h100:8")
train.wait()

eval_job = ac.submit("eval:latest")
eval_job.wait()

For parallel fan-out / fan-in, see Python SDK — JobGroup. To pass data between jobs via buckets (including fan-in to a shared output bucket and cross-cloud storage), see Bucket Sync. For copy-pasteable versions of these patterns, see Examples.

Running Commands

Run commands in your job's execution environment:

job = ac.submit("train:latest", gpu="h100:8", persist=True)
job.wait()

print(job.exec("nvidia-smi")) # run a command in the job environment
print(job.exec("python --version"))

See Python SDK — Job Methods and CLI — anycloud exec.

Debugging a Job

Use status for lifecycle and error details. While the job execution environment is still available, use exec for targeted inspection commands:

anycloud status <deployment-id> --verbose
anycloud exec <deployment-id> "pwd && ls -la"

For @anycloud.function() jobs, the logs label where a failure happened:

  • ERROR: git … (e.g. git is not installed in this container image., git clone failed:) — the VM couldn't fetch your repo. Check that the image has git installed and that your commit is pushed.
  • ERROR: anycloud could not set up your code: — the repo was fetched, but anycloud couldn't check out the commit, import your module, or find the function. Usually a path or module-name mismatch.
  • ERROR: your function '<name>' raised an exception: — your function ran; the traceback below is from your own code.

For other failure modes — credential and quota errors, jobs stuck in queued, or GPU-vs-VM confusion — see Troubleshooting.