Custom Snapshot Setup
The SDK also allows us to set up a snapshot with specific instructions and configurations, which can be reused across different instances. Eacg setup step is also cached as a snapshot, meaning that redundant steps are skipped in subsequent runs. This is particularly useful for creating a consistent environment for running tasks or applications.
Example: Docker and Nginx Setup
The example below installs Docker, configures a Docker network, runs two containerized services (a headless Chrome and an NGINX proxy), then creates a final snapshot. An instance is then started using the snapshot, and a browser service is exposed for running a task.
- Python
- TypeScript
#!/usr/bin/env python3
# Example: Custom Snapshot Setup with Morph Cloud
import os
import asyncio
from morphcloud.api import MorphCloudClient
client = MorphCloudClient()
# Create a snapshot with resource requirements and an identifying digest.
snapshot = client.snapshots.create(
vcpus=1,
memory=4096,
disk_size=8192,
digest="chromebox-1-1",
)
# Chain setup steps; each step is cached.
snapshot = (
snapshot.setup("apt update -y")
.setup("apt install -y docker.io")
.setup("systemctl enable docker")
.setup("systemctl start docker")
.setup("docker network create morph-net")
.setup(
"docker run -d --network morph-net --name headless-chrome "
"zenika/alpine-chrome "
"--headless --no-sandbox --disable-gpu --disable-dev-shm-usage "
"--remote-debugging-port=9222 --remote-debugging-address=0.0.0.0"
)
.setup(
"""\
cat <<'EOF' > /tmp/default.conf
server {
listen 80;
location / {
proxy_pass http://headless-chrome:9222;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host localhost;
}
location /json/ {
proxy_pass http://headless-chrome:9222;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host localhost;
proxy_set_header Accept-Encoding "";
sub_filter_types application/json;
sub_filter_once off;
sub_filter "ws://localhost" "wss://$http_host";
}
}
EOF
"""
)
.setup(
"docker run -d --network morph-net --name chrome-proxy "
"-p 9222:80 "
"-v /tmp/default.conf:/etc/nginx/conf.d/default.conf:ro "
"nginx:alpine"
)
)
# Start an instance using the snapshot.
with client.instances.start(snapshot.id, ttl_seconds=3600) as instance:
url = instance.expose_http_service("browser", 9222)
print(f"Instance ID: {instance.id}")
print(f"Browser service URL: {url}")
browser = Browser(config=BrowserConfig(cdp_url=url))
try:
yield browser
finally:
pass
#!/usr/bin/env ts-node
// Example: Custom Snapshot Setup with Morph Cloud
import { MorphCloudClient } from 'morphcloud';
const client = new MorphCloudClient();
// Create a snapshot with resource requirements and a unique digest.
let snapshot = await client.snapshots.create({
vcpus: 1,
memory: 4096,
diskSize: 8192,
digest: "chromebox-1-1",
});
// Chain setup steps; each step is cached.
snapshot = await snapshot.setup("apt update -y");
snapshot = await snapshot.setup("apt install -y docker.io");
snapshot = await snapshot.setup("systemctl enable docker");
snapshot = await snapshot.setup("systemctl start docker");
snapshot = await snapshot.setup("docker network create morph-net");
snapshot = await snapshot.setup(
`docker run -d --network morph-net --name headless-chrome \
zenika/alpine-chrome \
--headless --no-sandbox --disable-gpu --disable-dev-shm-usage \
--remote-debugging-port=9222 --remote-debugging-address=0.0.0.0`
);
snapshot = await snapshot.setup(
`cat <<'EOF' > /tmp/default.conf
server {
listen 80;
location / {
proxy_pass http://headless-chrome:9222;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host localhost;
}
location /json/ {
proxy_pass http://headless-chrome:9222;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host localhost;
proxy_set_header Accept-Encoding "";
sub_filter_types application/json;
sub_filter_once off;
sub_filter "ws://localhost" "wss://$http_host";
}
}
EOF`
);
snapshot = await snapshot.setup(
`docker run -d --network morph-net --name chrome-proxy \
-p 9222:80 \
-v /tmp/default.conf:/etc/nginx/conf.d/default.conf:ro \
nginx:alpine`
);
// Start an instance using the snapshot.
const instance = await client.instances.start({ snapshotId: snapshot.id });
Explanation
-
Snapshot Creation:
A snapshot is created with defined resources (vCPUs, memory, disk) and a digest identifier (chromebox-1-1
). -
Chained Setup:
The.setup()
method is chained to perform commands such as updating packages, installing Docker, and configuring services. Each step is cached so that subsequent runs skip steps that haven’t changed. -
Instance Startup:
An instance is started with the snapshot, and a browser service is exposed for use. The instance is automatically managed by the context manager.