# 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](/docs/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. ```ts check import { 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")); ``` ```python check from withruntime import Sandbox with 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") ``` - `dev` is 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:3306` publishes 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. - `mysql` prints 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 `env` on the command: `env` values are never echoed back, and Runtime's journals record a hash of them ([run commands](/docs/javascript#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](/glossary/sandbox-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 ```bash no-run runtime sandbox port-forward 13306:3306 mysql -h 127.0.0.1 -P 13306 -uroot -p app ``` The forward carries any TCP port through Runtime's API, authenticated with your key, and works on the free trial ([forward ports](/docs/editors#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](/docs/sandbox-environment#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-docker` installs Docker once per sandbox. A [custom image](/docs/images) whose recipe runs `enable-docker --no-start` skips it ([Docker in a sandbox](/how-to/run-docker-in-a-sandbox)). For MySQL next to the app that uses it, see [Docker Compose integration tests](/integrations/docker-compose). ## 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.