Skip to main content
Closed beta. ankra migrate is gated by the backups feature, which is in closed beta. The workflow is stable but the surface may still change, and the feature is enabled per organisation on request. Until it is enabled for yours, the vault commands the migration depends on answer Backups are not enabled for this organisation. Contact support to have it turned on for your organisation.
ankra migrate up takes a directory holding a Docker Compose file and moves the whole deployment into a cluster Ankra runs: it converts the services into a stack, applies the stack, and then moves the data out of the deployment’s PostgreSQL, MySQL and MariaDB databases into the databases it just deployed. A bare Dockerfile and the running Docker daemon work as sources too.
The command is re-runnable, so the usual shape is to rehearse it against a live source, check the result, and then run it once more with --stop-source to cut over.

Prerequisites

  • A logged-in session: ankra login, or ANKRA_API_TOKEN in the environment.
  • A target cluster in the organisation running an Ankra agent new enough to run data restores. An older agent makes the platform refuse the restore with 409: The cluster's agent does not support data restores yet; upgrade the agent first.
  • The backups feature enabled for the organisation, and a backup vault in the ready state. The dumps travel through the vault’s bucket. ankra backup vaults list shows what you have, ankra backup vaults provision creates one. With exactly one ready vault the CLI picks it; with several, name one with --vault.
  • Docker reachable from wherever the command runs. Locally that is the daemon on your machine; for a deployment on another host, point at it with --option docker-host=ssh://root@host.

Plan first

--plan prints what the run would do and changes nothing:
The plan names:
  • The module detected in the source directory, the target cluster, the stack (new, or an existing one that will be updated) and the namespace. The stack defaults to the source directory’s name and the namespace to the stack’s name. ankra migrate detect ./app reports which modules recognise a directory, and ankra migrate modules lists the ones available.
  • The output directory (--out, default ankra-migration): the conversion is written to <out>/stack and the dumps to <out>/data. A directory holding nothing but an earlier run’s stack/ and data/ is reused, so running the same command again needs no extra flag.
  • Every database server it found, with its engine, version and user, and each database on it with the size read from the running container (pg_database_size on PostgreSQL, information_schema on MySQL and MariaDB).
  • The estimated dump size against the free disk where the dumps will be written. The run refuses rather than filling the disk.
  • Warnings, such as a database above 625 GiB (more than a single upload can carry), or the postgres maintenance database being skipped. If postgres really is your application database, say so with --option databases.<workload>=postgres.
  • A not carried list: files in the volumes of non-database workloads, and data in engines the export does not dump.
Without --plan the same summary is printed and the run waits for a confirmation. --yes skips the prompt.

Run it

1

Convert

The source is converted into a stack, exactly as ankra migrate convert would, and written to <out>/stack.
2

Deploy

The stack is applied to the cluster under its name, the same write ankra cluster apply performs, and the command waits for the platform to accept it.
3

Wait for the databases

Each database workload has to have a running, ready pod before anything is restored into it.
4

Export

The dumps are taken from the source, as ankra migrate export would, into <out>/data.
5

Restore

The dumps are uploaded through the vault, verified, restored in-cluster, and the command waits for the restore to finish.
The summary at the end says where the deployment now runs, the import id for the restore, the URLs for any workload given one with --option ingress.<workload>=<host>, what is still running on the source, and whether the run was a rehearsal. To publish a workload and get TLS for it, pass the host and the issuer:

Flags

Rehearse, then cut over

Nothing about the run requires the source to be stopped, so rehearse with it live, look at what landed in the cluster, and repeat until you are happy. When you are, cut over:
Running again over the same output directory needs no extra flag: a directory holding nothing but an earlier run’s stack/ and data/ is reused. --force is only for an output directory that holds something else, and the refusal names the file that is in the way: <out> holds notes.txt, which no earlier run of this command wrote; pass --force to overwrite it or --out for another directory.
--stop-source stops the source’s non-database services before the final dump is taken, so nothing writes to the source databases while they are being read. The databases themselves stay up for the dump. The summary prints the docker start ... command that brings the source back if you need to roll back. Once you are satisfied, move DNS to the cluster.

Running the steps separately

The same work is available as individual commands when you want to inspect what each one produced:
ankra migrate data ./app --cluster production --wait runs steps 3 and 4 together. A restore that was started without --wait can be followed with ankra migrate restore-status <import-id> --wait.

Options

--option is repeatable, and ankra migrate up accepts both sets. The conversion takes: The export takes:

How the data travels

The dump runs inside each database container, through the container’s own shell. The password is read from the container’s environment, *_FILE secrets are honoured, and no credential is ever put on the host’s command line.
  • PostgreSQL: pg_dump -Fc per database, plus pg_dumpall --globals-only --no-role-passwords for the roles.
  • MySQL and MariaDB: mysqldump --single-transaction --routines --triggers --events --databases, as root where a root password exists and otherwise as the application user.
The workloads recognised as databases are the images whose names start with postgres, postgis, pgvector or timescaledb, and mysql, mariadb or percona. Sidecars are left alone: an image whose name contains exporter, proxy, bouncer, backup, operator, client or admin is never dumped from. Dumps are written 0600 alongside a manifest.json and a SHA256SUMS. On the way in, the CLI uploads straight to the vault’s own bucket using presigned URLs the platform mints under imports/<import-id>/. A dump above 1 GiB goes up in parts of 64 MiB, each retried on its own, so one stalled part costs a part rather than the whole upload. The platform starts the multipart upload and the CLI completes it, aborting it if it cannot finish, so the vault is never left holding half an artifact. The progress line names the size and the part count:
The platform verifies each object’s size with a HEAD, and then the cluster’s agent runs a Kubernetes Job in the target namespace: an init container downloads the artifacts and checks them against their SHA-256 sums, and the engine client (postgres:<major>-alpine, or mysql/mariadb:<version>) waits for the database to accept connections and restores into it. Roles and globals go first, then each database, with pg_restore --clean --if-exists --no-owner or mysql < file. The Job connects using the Service and Secret the conversion generated.
Ankra never holds your data: it goes from your source to your vault’s bucket to your cluster. No vault credential is handed to the cluster, and nothing on the machine running the command needs kubectl or a database client.

The dumps a restore leaves in the vault

Every restore keeps its upload under imports/<import-id>/ in the vault, so the same import can be restored again without dumping the source a second time. The dumps stay there until you remove them.
list gives each import’s id, stack, status, databases, size and when it was created. delete removes the dumps from the vault and forgets the import, and refuses one whose restore is still running; --yes skips its confirmation. A restore that completes prints the delete command for the import it just finished, so the cleanup is there when you want it. Deleting the vault itself also removes the dumps of every import it held, on a bucket you own.

What is not carried

The migration moves workloads and relational database contents. It does not move everything.
  • Files in the volumes of non-database workloads. Uploads, caches and other on-disk state have to be copied into the PVC yourself.
  • Data in engines the export does not dump: Redis, Valkey, MongoDB, Elasticsearch and OpenSearch, RabbitMQ, MinIO, ClickHouse, InfluxDB, Neo4j, Cassandra and CouchDB. Their workloads are converted and deployed; they simply come up empty. The plan names each one it found.
  • A single artifact above 625 GiB, which is the 10,000 parts of 64 MiB one upload can carry. ankra migrate restore refuses a larger one before it registers the import, saying an upload carries at most 625.0 GiB.
  • PostgreSQL role passwords. Roles are restored without them. The application user keeps the password from the cluster Secret, so the application works; any other login role needs an ALTER ROLE ... PASSWORD afterwards.
A pg_restore that finishes with “errors ignored” (exit code 1) is reported as a warning and the restore is treated as successful, which is the normal outcome when the target database already holds some of the objects.

Troubleshooting

A failed restore keeps its Job in the namespace for an hour. The agent already tails the Job’s log into the failed step, so the reason usually travels with the operation, and the CLI reports the restore of import <import-id> failed: .... To read the Job yourself while it is still there, through Ankra (with the cluster selected via ankra cluster select <cluster>):

Next steps

Backup vaults

Provision the vault the dumps travel through.

Stacks

Understand the stack the conversion produced.

Ankra CLI

Install the CLI and browse the rest of its commands.

Import a cluster

Connect the cluster you are migrating into.