One container, one instance
An instance is one container from your image on its own isolated computer. YourENTRYPOINT is its main process, its disk persists, and every port it listens on has an HTTPS URL derived from its id. There is no Docker to run inside an instance: whatever you docker run today becomes its own instance, created with one API call.
Three commands move a container:
https://{instanceId}-{port}.agent37.app with the same header. A port that must answer without a key (a webhook, an embed) gets a public port.
docker to Agent37
A
docker-compose.yml maps the same way, service by service. Services that call each other over HTTP each become an instance; route those calls through your own server, which holds the key, or give the called service a public port with its own authentication in front. Point the app at a managed database, or run the database in the same instance as its app with its data under /home/node; your instances reach anything on the public internet.
Why it costs less
A rented server bills every hour it exists. Most containers on it do nothing for most of those hours: a per-user session waits for the user, a worker waits for a job, a preview waits for someone to open it. An instance created withauto_sleep: true sleeps once it has been idle for idle_timeout_seconds and wakes on the next request, usually in well under a second. Idle means no traffic through the instance’s URLs or exec, so set idle_timeout_seconds to the longest gap you expect between requests. Awake minutes bill the compute rate; asleep minutes bill disk alone. A 2 vCPU / 4 GB instance awake an hour a day costs about $0.54 per month, against $4.76 always-on. Either price includes the URL, TLS, restarts, and the API to manage it. See Billing and Auto-sleep.
One team kept an 8 vCPU / 16 GB server up around the clock for up to 13 coding-session containers, whether or not anyone was in a session. As instances with auto-sleep, each session bills compute only while its user is working in it.
If your app launches containers for its users
Products that create a container per user, per session, or per job (a coding sandbox, a preview environment, an agent runner) carry a layer of machinery to do it. A pool of servers, an agent on each that talks to Docker, a registry, a scheduler, a watchdog, a router that maps each user to a server and port. On Agent37 that layer is the API. The plan:- Publish the image you launch. Your session image, unchanged, becomes a workspace template with the port your users hit as its
default_port. Each image you launch is its own template. - Replace
docker runwith create. Where your scheduler starts a container, callPOST /v1/instanceswith the container’s environment asenv, and store the returned instanceidwhere you kept the container id. Where it stops one, callDELETE. Put your own session id innameormetadataso you can find the instance again from your side. - Point your reverse proxy at the instance URL. Wherever you forward a user to
server-ip:port, forward tohttps://{instanceId}.agent37.appinstead and add theX-Agent37-Keyheader with your key. WebSockets pass through, so live reload and terminals keep working. Your own domain, cookies, and login stay as they are; your proxy is still the front door. - Delete the fleet. Server provisioning, the per-server agent, capacity planning, the registry, the watchdog, and the wildcard certificate have nothing left to do.
Make the image at home here
Most images need nothing. Two habits make the move smooth:- Let the entrypoint run again on the same disk. A restart, a stop followed by a start, or a wake that boots fresh runs your
ENTRYPOINTagain with last time’s files still on disk. Skip work that is already done: a repository that is already cloned, a migration that already ran, a directory that already exists. - Fetch short-lived secrets at boot.
envis set when the instance is created and replayed on every start. Long-lived configuration belongs there. Fetch a credential that expires, such as a one-hour installation token, from your own server when the container starts.
root included. Bind services to 0.0.0.0, as you would for any container.