cd /news/machine-learning/deploying-clearml-as-a-gcp-vertex-ai… · home topics machine-learning article
[ARTICLE · art-50115] src=dev.to ↗ pub= topic=machine-learning verified=true sentiment=· neutral

Deploying ClearML as a GCP Vertex AI Alternative on Ubuntu

A developer deployed ClearML, an open-source MLOps platform, as a self-hosted alternative to Google Cloud's Vertex AI on an Ubuntu server. The setup uses Docker Compose and Traefik to provide experiment tracking, pipelines, model registry, and Triton-based serving, covering the full ML lifecycle without vendor lock-in.

read7 min views1 publishedJul 7, 2026

Google Vertex AI is Google Cloud's managed ML platform with experiment tracking, training jobs, pipelines, a model registry, and endpoints, but it locks you into GCP-specific APIs and per-use billing. ClearML is an open-source MLOps platform that covers the same ground on any Docker host or Kubernetes cluster, capturing training metrics automatically with no code changes and keeping every byte of data on infrastructure you control. This guide deploys ClearML Server with Docker Compose and Traefik, registers an agent, runs an experiment, builds a pipeline, runs a hyperparameter sweep, and deploys a Triton-served model. By the end, you'll have a self-hosted Vertex AI replacement covering the full ML lifecycle.

GCP Vertex AI ClearML Equivalent Purpose
Vertex AI Workbench ClearML Web UI Browser-based monitoring and configuration
Vertex AI Experiments ClearML Experiment Manager Automatic hyperparameter/metric/artifact tracking
Vertex AI Training Job ClearML Agent + Tasks Any machine becomes a remote worker via queues
Vertex AI Pipelines ClearML Pipelines Python-native DAGs, no separate compile step
Vertex AI Model Registry ClearML Model Repository Versioned models with full lineage
Vertex AI Endpoints ClearML Serving (Triton) Self-hosted inference with canary/A-B support
Cloud Monitoring/Logging ClearML Scalars/Plots Built-in metrics and hardware dashboards

Prerequisite:Ubuntu host with Docker + Compose, DNS A records forapp.clearml.example.com

,api.clearml.example.com

,files.clearml.example.com

. NVIDIA Container Toolkit if you'll run GPU agents.

1. Raise Elasticsearch's virtual memory limit and restart Docker:

$ echo "vm.max_map_count=524288" | sudo tee /etc/sysctl.d/99-clearml.conf
$ sudo sysctl --system
$ sudo systemctl restart docker

2. Create persistent data directories with the correct ownership:

$ sudo mkdir -p /opt/clearml/{data/elastic_7,data/mongo_4/db,data/mongo_4/configdb,data/redis,data/fileserver,logs,config}
$ sudo chown -R 1000:1000 /opt/clearml

3. Download the official Compose file:

$ mkdir -p ~/clearml && cd ~/clearml
$ curl -fsSL https://raw.githubusercontent.com/clearml/clearml-server/master/docker/docker-compose.yml -o docker-compose.yml

4. Edit it: comment out the ports:

blocks under apiserver

, webserver

, and fileserver

(Traefik will handle external routing), and replace the networks:

section with named bridges:

networks:
  backend:
    name: clearml_backend
    driver: bridge
  frontend:
    name: clearml_frontend
    driver: bridge

5. Set the public hostnames:

$ nano .env
CLEARML_WEB_HOST=https://app.clearml.example.com
CLEARML_API_HOST=https://api.clearml.example.com
CLEARML_FILES_HOST=https://files.clearml.example.com

6. Start the stack:

$ docker compose up -d
$ docker compose ps
$ docker compose logs --tail 50

1. Create the Traefik directory and cert store:

$ mkdir -p ~/clearml/traefik && cd ~/clearml/traefik
$ mkdir -p letsencrypt && touch letsencrypt/acme.json && chmod 600 letsencrypt/acme.json

2. Set the ACME email:

$ nano .env
LETSENCRYPT_EMAIL=admin@example.com

3. Create the Traefik Compose file:

$ nano docker-compose.yml
services:
  traefik:
    image: traefik:v3.6
    container_name: traefik
    command:
      - "--log.level=INFO"
      - "--providers.file.filename=/etc/traefik/dynamic_conf.yml"
      - "--entryPoints.web.address=:80"
      - "--entryPoints.websecure.address=:443"
      - "--entryPoints.web.http.redirections.entrypoint.to=websecure"
      - "--certificatesResolvers.le.acme.httpChallenge.entryPoint=web"
      - "--certificatesResolvers.le.acme.email=${LETSENCRYPT_EMAIL}"
      - "--certificatesResolvers.le.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "./dynamic_conf.yml:/etc/traefik/dynamic_conf.yml:ro"
    networks:
      - clearml-frontend
    restart: unless-stopped

networks:
  clearml-frontend:
    name: clearml_frontend
    external: true

4. Route each subdomain to its ClearML service:

$ nano dynamic_conf.yml
http:
  routers:
    clearml-web:
      rule: "Host(`app.clearml.example.com`)"
      entryPoints: [websecure]
      service: clearml-web
      tls: {certResolver: le}
    clearml-api:
      rule: "Host(`api.clearml.example.com`)"
      entryPoints: [websecure]
      service: clearml-api
      tls: {certResolver: le}
    clearml-files:
      rule: "Host(`files.clearml.example.com`)"
      entryPoints: [websecure]
      service: clearml-files
      tls: {certResolver: le}
  services:
    clearml-web:
      loadBalancer:
        servers: [{url: "http://clearml-webserver:80"}]
    clearml-api:
      loadBalancer:
        servers: [{url: "http://clearml-apiserver:8008"}]
    clearml-files:
      loadBalancer:
        servers: [{url: "http://clearml-fileserver:8081"}]

5. Start Traefik and confirm certificates issued:

$ docker compose up -d
$ docker logs traefik 2>&1 | grep -i certificate

https://app.clearml.example.com

, enter a username and company name, and click

api {
  web_server: https://app.clearml.example.com
  api_server: https://api.clearml.example.com
  files_server: https://files.clearml.example.com
  credentials {
    "access_key" = "YOUR_ACCESS_KEY"
    "secret_key" = "YOUR_SECRET_KEY"
  }
}
bash
$ mkdir -p ~/clearml-agent && cd ~/clearml-agent
$ sudo apt install python3.12-venv -y
$ python3 -m venv clearml_venv
$ source clearml_venv/bin/activate
$ pip install clearml-agent
$ clearml-agent init

Paste the credentials block when prompted; press Enter to accept defaults for the rest. Then start the daemon:

$ clearml-agent daemon --queue default --detached

For GPU workloads:

$ clearml-agent daemon --gpus 0,1 --queue default --detached

Confirm registration in Workers & Queues → Workers.

$ source ~/clearml-agent/clearml_venv/bin/activate
$ pip install clearml scikit-learn joblib pandas
$ clearml-init

Paste the credentials block again when prompted.

$ mkdir -p ~/clearml/experiments && cd ~/clearml/experiments
$ nano 01_first_experiment.py
python
import joblib
from clearml import Task
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report

task = Task.init(project_name='ClearML Tutorial', task_name='01_First_Experiment',
                 tags=['tutorial', 'random-forest'])

hyperparams = {'n_estimators': 100, 'max_depth': 5, 'random_state': 42}
task.connect(hyperparams)

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.2, random_state=42)

clf = RandomForestClassifier(**hyperparams).fit(X_train, y_train)
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
report = classification_report(y_test, y_pred, target_names=iris.target_names, output_dict=True)

logger = task.get_logger()
logger.report_scalar(title='Performance', series='Accuracy', value=accuracy, iteration=1)
for label, metrics in report.items():
    if isinstance(metrics, dict):
        for metric_name, value in metrics.items():
            logger.report_scalar(title=f'Class: {label}', series=metric_name, value=value, iteration=1)

model_path = 'iris_rf_model.pkl'
joblib.dump(clf, model_path)
task.upload_artifact(name='trained_model', artifact_object=model_path)
task.close()
bash
$ python3 01_first_experiment.py

The output prints a task URL — open it to see execution details, hyperparameters, artifacts, console output, and scalar charts under the ClearML Tutorial project.

$ nano 02_pipeline.py
python
from clearml import PipelineController

def step_one(pickle_data_url):
    import pickle, pandas as pd
    from clearml import StorageManager
    pickle_data_url = pickle_data_url or 'https://github.com/allegroai/events/raw/master/odsc20-east/generic/iris_dataset.pkl'
    local_iris_pkl = StorageManager.get_local_copy(remote_url=pickle_data_url)
    with open(local_iris_pkl, 'rb') as f: iris = pickle.load(f)
    df = pd.DataFrame(iris['data'], columns=iris['feature_names']); df['target'] = iris['target']
    return df

def step_two(data_frame, test_size=0.2, random_state=42):
    from sklearn.model_selection import train_test_split
    y = data_frame['target']; X = data_frame.drop(columns=['target'])
    return train_test_split(X, y, test_size=test_size, random_state=random_state)

def step_three(data):
    from sklearn.linear_model import LogisticRegression
    X_train, X_test, y_train, y_test = data
    return LogisticRegression(solver='lbfgs', max_iter=1000).fit(X_train, y_train)

if __name__ == '__main__':
    pipe = PipelineController(project='ClearML Tutorial', name='02_Pipeline_Experiment',
                              version='1.0', add_pipeline_tags=True)
    pipe.add_parameter('url', 'https://github.com/allegroai/events/raw/master/odsc20-east/generic/iris_dataset.pkl')
    pipe.add_function_step('step_one',   step_one,   function_kwargs={'pickle_data_url': '${pipeline.url}'}, function_return=['data_frame'])
    pipe.add_function_step('step_two',   step_two,   function_kwargs={'data_frame': '${step_one.data_frame}'}, function_return=['processed_data'])
    pipe.add_function_step('step_three', step_three, function_kwargs={'data': '${step_two.processed_data}'}, function_return=['model'])
    pipe.start_locally(run_pipeline_steps_locally=True)
bash
$ python3 02_pipeline.py
bash
$ nano 03_hpo.py
python
from clearml import Task
from clearml.automation import HyperParameterOptimizer, DiscreteParameterRange, UniformIntegerParameterRange, RandomSearch

tasks = Task.get_tasks(project_name='ClearML Tutorial',
                       task_filter={'status': ['completed', 'published']},
                       task_name='01_First_Experiment')
base_task_id = tasks[-1].id

Task.init(project_name='ClearML Tutorial', task_name='03_Hyperparameter_Optimization',
          task_type=Task.TaskTypes.optimizer)

optimizer = HyperParameterOptimizer(
    base_task_id=base_task_id,
    hyper_parameters=[
        UniformIntegerParameterRange('General/n_estimators', min_value=10, max_value=200, step_size=20),
        DiscreteParameterRange('General/max_depth', values=[3, 5, 7, 10]),
    ],
    objective_metric_title='Performance', objective_metric_series='Accuracy',
    objective_metric_sign='max', optimizer_class=RandomSearch,
    max_number_of_concurrent_tasks=2, total_max_jobs=6,
)
optimizer.start(); optimizer.wait()
top = optimizer.get_top_experiments(1)
if top:
    print(top[0].id, top[0].get_parameters_as_dict().get('General', {}))
bash
$ python3 03_hpo.py

Monitor progress in the Web UI under ClearML Tutorial.

$ cd ~/clearml
$ git clone https://github.com/clearml/clearml-serving.git
$ pip install clearml-serving
$ clearml-serving create --name "serving-example"

Set the serving .env

:

$ nano clearml-serving/docker/.env
CLEARML_WEB_HOST="https://app.clearml.example.com"
CLEARML_API_HOST="https://api.clearml.example.com"
CLEARML_FILES_HOST="https://files.clearml.example.com"
CLEARML_API_ACCESS_KEY="YOUR_ACCESS_KEY"
CLEARML_API_SECRET_KEY="YOUR_SECRET_KEY"
CLEARML_SERVING_TASK_ID="SERVING_SERVICE_ID"

Start the Triton serving stack:

$ cd ~/clearml/clearml-serving/docker
$ docker compose --env-file .env -f docker-compose-triton.yml up -d

Train and register a sample model:

$ pip install -r ~/clearml/clearml-serving/examples/pytorch/requirements.txt
$ python3 ~/clearml/clearml-serving/examples/pytorch/train_pytorch_mnist.py

Copy the Model ID from the task's Artifacts tab, then add the endpoint:

$ clearml-serving --id SERVING_SERVICE_ID model add \
    --engine triton \
    --endpoint "test_model_pytorch" \
    --preprocess "clearml-serving/examples/pytorch/preprocess.py" \
    --model-id MODEL_ID \
    --input-size 1 28 28 --input-name "INPUT__0" --input-type float32 \
    --output-size 10 --output-name "OUTPUT__0" --output-type float32

$ docker compose --env-file .env -f docker-compose-triton.yml restart

Test inference:

$ curl -X POST "http://SERVER_IP:8080/serve/test_model_pytorch" \
    -H "Content-Type: application/json" \
    -d '{"url": "https://raw.githubusercontent.com/clearml/clearml-serving/main/examples/pytorch/5.jpg"}'
bash
$ curl -s https://api.clearml.example.com/debug.ping | head -c 100
$ curl -s -o /dev/null -w "%{http_code}" https://files.clearml.example.com/

In the Web UI: confirm the agent shows under Workers & Queues, the first experiment has metrics/artifacts, and cloning + re-enqueuing an experiment gets picked up by the agent.

Vertex AI concept ClearML replacement
google.cloud.aiplatform experiment tracking
clearml.Task — auto-captures Git state, deps, uncommitted changes
Custom Training Jobs
clearml.Task + task.execute_remotely() , or enqueue via UI
Vertex AI Workbench notebooks Standard Jupyter/JupyterHub — Task.init() works identically
Kubeflow-based Vertex Pipelines
PipelineController / @pipeline — Python-native, no compile step
Vizier hyperparameter tuning
HyperParameterOptimizer — runs on your own agents
Model Registry
OutputModel — full lineage to source experiment
Vertex AI Endpoints ClearML Serving + Triton — canary/A-B on your own infra
Batch Prediction Jobs No direct equivalent — migrate to standard Tasks writing to object storage
GCS data access ClearML works with GCS paths directly, or migrate to any storage
IAM + ADC auth API keys via clearml.conf or CLEARML_API_ACCESS_KEY /SECRET_KEY
AIP_* env conventions
Not needed — agents use standard Python/Docker, no Vertex-specific vars
MLflow tracking calls ClearML's MLflow compatibility layer routes mlflow.log_* without a rewrite

ClearML is running with tracking, agents, pipelines, HPO, and Triton serving. From here you can:

For the full guide with additional tips, visit the original article on ** Vultr Docs**.

── more in #machine-learning 4 stories · sorted by recency
── more on @clearml 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/deploying-clearml-as…] indexed:0 read:7min 2026-07-07 ·