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.
Vertex AI → ClearML Mapping
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 dashboardsPrerequisite: Ubuntu host with Docker + Compose, DNS A records for
app.clearml.example.com,api.clearml.example.com,files.clearml.example.com. NVIDIA Container Toolkit if you’ll run GPU agents.
Deploy the ClearML Server
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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
5. Set the public hostnames:
$ nano .env
Enter fullscreen mode Exit fullscreen mode
CLEARML_WEB_HOST=https://app.clearml.example.com
CLEARML_API_HOST=https://api.clearml.example.com
CLEARML_FILES_HOST=https://files.clearml.example.com
Enter fullscreen mode Exit fullscreen mode
6. Start the stack:
$ docker compose up -d
$ docker compose ps
$ docker compose logs --tail 50
Enter fullscreen mode Exit fullscreen mode
Front the Stack with Traefik
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
Enter fullscreen mode Exit fullscreen mode
2. Set the ACME email:
$ nano .env
Enter fullscreen mode Exit fullscreen mode
[email protected]
Enter fullscreen mode Exit fullscreen mode
3. Create the Traefik Compose file:
$ nano docker-compose.yml
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
4. Route each subdomain to its ClearML service:
$ nano dynamic_conf.yml
Enter fullscreen mode Exit fullscreen mode
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"}]
Enter fullscreen mode Exit fullscreen mode
5. Start Traefik and confirm certificates issued:
$ docker compose up -d
$ docker logs traefik 2>&1 | grep -i certificate
Enter fullscreen mode Exit fullscreen mode
Create the Admin Account and API Credentials
- Open
https://app.clearml.example.com, enter a username and company name, and click Create Account. - Settings → Workspace → Create new credentials.
- Copy the generated block — you’ll need it for the agent and SDK:
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"
}
}
Enter fullscreen mode Exit fullscreen mode
Register a ClearML Agent
$ 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
Enter fullscreen mode Exit fullscreen mode
Paste the credentials block when prompted; press Enter to accept defaults for the rest. Then start the daemon:
$ clearml-agent daemon --queue default --detached
Enter fullscreen mode Exit fullscreen mode
For GPU workloads:
$ clearml-agent daemon --gpus 0,1 --queue default --detached
Enter fullscreen mode Exit fullscreen mode
Confirm registration in Workers & Queues → Workers.
Install the SDK and Run a First Experiment
$ source ~/clearml-agent/clearml_venv/bin/activate
$ pip install clearml scikit-learn joblib pandas
$ clearml-init
Enter fullscreen mode Exit fullscreen mode
Paste the credentials block again when prompted.
$ mkdir -p ~/clearml/experiments && cd ~/clearml/experiments
$ nano 01_first_experiment.py
Enter fullscreen mode Exit fullscreen mode
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()
Enter fullscreen mode Exit fullscreen mode
$ python3 01_first_experiment.py
Enter fullscreen mode Exit fullscreen mode
The output prints a task URL — open it to see execution details, hyperparameters, artifacts, console output, and scalar charts under the ClearML Tutorial project.
Build a Pipeline
$ nano 02_pipeline.py
Enter fullscreen mode Exit fullscreen mode
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)
Enter fullscreen mode Exit fullscreen mode
$ python3 02_pipeline.py
Enter fullscreen mode Exit fullscreen mode
Run a Hyperparameter Sweep
$ nano 03_hpo.py
Enter fullscreen mode Exit fullscreen mode
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', {}))
Enter fullscreen mode Exit fullscreen mode
$ python3 03_hpo.py
Enter fullscreen mode Exit fullscreen mode
Monitor progress in the Web UI under ClearML Tutorial.
Deploy a Model with ClearML Serving
$ cd ~/clearml
$ git clone https://github.com/clearml/clearml-serving.git
$ pip install clearml-serving
$ clearml-serving create --name "serving-example"
Enter fullscreen mode Exit fullscreen mode
Set the serving .env:
$ nano clearml-serving/docker/.env
Enter fullscreen mode Exit fullscreen mode
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"
Enter fullscreen mode Exit fullscreen mode
Start the Triton serving stack:
$ cd ~/clearml/clearml-serving/docker
$ docker compose --env-file .env -f docker-compose-triton.yml up -d
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
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"}'
Enter fullscreen mode Exit fullscreen mode
Verify Everything
$ 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/
Enter fullscreen mode Exit fullscreen mode
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.
Migrating from Vertex AI
Vertex AI concept ClearML replacementgoogle.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
Next Steps
ClearML is running with tracking, agents, pipelines, HPO, and Triton serving. From here you can:
- Add GPU agents and dedicate queues per hardware profile
- Migrate GCS-backed datasets using ClearML Data’s explicit versioning
- Wire ClearML into CI so every training run is tracked automatically
For the full guide with additional tips, visit the original article on Vultr Docs.
답글 남기기