How to run MySQL in a cloud sandbox
Run the official mysql image with Docker in a microVM, load your dump via /docker-entrypoint-initdb.d, query it, and mysqldump it back.
On Runtime, every MySQL gets a whole machine and disappears with it. A Firecracker microVM with its own kernel runs Docker and the database, so an agent can run migrations, drop tables or load a customer's dump without any route to your real servers. Each sandbox you start is a fresh server with nothing left over, from $0.03125 an hour for 2 vCPU and 4 GiB while it idles and $0.08 with both CPUs busy (pricing).
Which MySQL
On 25 September 2026:
| Source | Version | Start it with |
|---|---|---|
Docker Official Image mysql |
9.7.2 (tags 9.7, lts); 8.4.11 (8.4) |
docker run mysql:9.7, after sudo enable-docker |
Ubuntu 24.04 package mysql-server |
8.0.46 | sudo apt-get install -y mysql-server |
| Clients | PyMySQL 1.2.3 and mysql-connector-python 26.7.0 on PyPI; mysql2 3.24.4 on npm |
pip install, npm install |
The samples use the Docker image: it has the current long-term release, and its entrypoint creates the database, the user and your schema from environment variables and files.
Load a dump and query it
Files in /docker-entrypoint-initdb.d ending in .sql, .sql.gz or .sh run
in alphabetical order the first time the container starts.
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 1800 });await sbx.exec("sudo enable-docker", { check: true, timeoutMs: 600_000 });await sbx.files.upload("./dump.sql", "/workspace/init/01-dump.sql");await sbx.exec( "docker run -d --name db -e MYSQL_ROOT_PASSWORD=dev -e MYSQL_DATABASE=app " + "-p 127.0.0.1:3306:3306 -v /workspace/init:/docker-entrypoint-initdb.d:ro mysql:9.7", { check: true, timeoutMs: 600_000 },);await sbx.exec( "timeout 300 bash -c 'until docker exec db mysqladmin ping -h 127.0.0.1 -uroot -pdev --silent; do sleep 2; done'", { check: true, timeoutMs: 330_000 },);const rows = await sbx.exec( `docker exec db mysql -uroot -pdev app -e "SELECT COUNT(*) FROM orders"`, { check: true },);console.log(rows.stdout);await sbx.exec("docker exec db mysqldump -uroot -pdev app > /workspace/after.sql", { check: true, timeoutMs: 300_000,});await writeFile("after.sql", await sbx.files.read("/workspace/after.sql"));Pythonfrom withruntime import Sandboxwith Sandbox.create(disk_mib=8192, timeout_seconds=1800) as sbx: sbx.exec("sudo enable-docker", check=True, timeout_ms=600_000) sbx.files.upload("dump.sql", "/workspace/init/01-dump.sql") sbx.exec("docker run -d --name db -e MYSQL_ROOT_PASSWORD=dev -e MYSQL_DATABASE=app " "-p 127.0.0.1:3306:3306 -v /workspace/init:/docker-entrypoint-initdb.d:ro mysql:9.7", check=True, timeout_ms=600_000) sbx.exec("timeout 300 bash -c 'until docker exec db mysqladmin ping -h 127.0.0.1 " "-uroot -pdev --silent; do sleep 2; done'", check=True, timeout_ms=330_000) print(sbx.exec('docker exec db mysql -uroot -pdev app -e "SELECT COUNT(*) FROM orders"', check=True).stdout) sbx.exec("docker exec db mysqldump -uroot -pdev app > /workspace/after.sql", check=True, timeout_ms=300_000) sbx.files.download("/workspace/after.sql", "after.sql")devis a throwaway password for a server that lives and dies with the sandbox. Nothing on the internet can connect in to a sandbox, and-p 127.0.0.1:3306:3306publishes the port inside it only.- The loop waits until the server answers over TCP. A big dump takes longer to load, so raise the 300 seconds to match.
mysqlprints a warning about a password on the command line to stderr; it does not change the result.- For a password that matters, such as one for a real database, pass it as
envon the command:envvalues are never echoed back, and Runtime's journals record a hash of them (run commands).
Let an agent try a migration safely
A sandbox is cheap enough to throw away after every attempt. Load the dump once, then fork the sandbox so each migration attempt starts from the same loaded database, with MySQL already running in every copy. A copy that breaks the schema is stopped, and the next attempt starts from the fork's source again. Forks make 1 to 10 copies per call.
Open it in MySQL Workbench or DBeaver
Terminalruntime sandbox port-forward <id> 13306:3306mysql -h 127.0.0.1 -P 13306 -uroot -p appThe forward carries any TCP port through Runtime's API, authenticated with
your key, and works on the free trial
(forward ports). In code:
sbx.forwardPort(3306, { localPort: 13306 }) or
sbx.forward_port(3306, local_port=13306).
Pull data from a MySQL outside the sandbox
To copy tables from a staging database into the sandbox, run mysqldump in
the sandbox against that host. MySQL listens on 3306, so this needs a paid
sandbox: the free trial reaches ports 80 and 443 only. A paid sandbox reaches
any public host on any port once the account has made a purchase, and a
network allow list can hold it to that one database
(the network).
Sizing
- Disk. The image and its data live on the sandbox's disk. The default 4 GiB disk had about 2.5 GiB free on 24 September 2026, so the samples ask for 8 GiB; the free trial allows up to 10 GiB.
- Memory. A sandbox has the memory you ask for with
memoryMiB; InnoDB's buffer pool should fit inside it. - Startup.
sudo enable-dockerinstalls Docker once per sandbox. A custom image whose recipe runsenable-docker --no-startskips it (Docker in a sandbox).
For MySQL next to the app that uses it, see Docker Compose integration tests.
Sources
- MySQL Docker Official Image, https://hub.docker.com/_/mysql, read 25 September 2026
- Docker Hub tags for mysql, https://hub.docker.com/v2/repositories/library/mysql/tags, read 25 September 2026
- Ubuntu 24.04 mysql-server package, https://packages.ubuntu.com/noble/mysql-server, read 25 September 2026
- PyPI PyMySQL and mysql-connector-python, and npm mysql2, read 25 September 2026
Facts on this page were checked on 25 September 2026.