Migrate Containers — painless Docker container migration between servers.
Mico is a CLI tool that packs all running Docker containers (images, configs, volumes, networks) into a single compressed archive on the source server, and restores everything on the target server with a single command.
- Full snapshot — captures images, container configs, named volumes, bind mounts, and networks
- Incremental mode — only pack containers changed since last run
- Selective packing — filter by container name
- Dependency-aware — respects Docker Compose
depends_onordering via topological sort - Concurrent operations — configurable worker count for faster packing/unpacking
- Integrity verification — SHA256 checksums auto-generated and verified on unpack
- S3 backup/restore — upload backups to S3-compatible storage, restore with a single command
- Multi-runtime — supports Docker, OrbStack and Podman
Note
Bind mounts (-v /host/path:/container/path) are converted to named volumes after migration, since the target server may not replicate the same directory paths.
brew tap ray-d-song/mico
brew install micocurl -fsSL https://raw.githubusercontent.com/Ray-D-Song/mico/main/install.sh | shirm https://raw.githubusercontent.com/Ray-D-Song/mico/main/install.ps1 | iexWarning
Windows Docker (WSL2) has not been tested.
go install github.com/Ray-D-Song/mico@latestRequires Go 1.24+.
# On the source server — pack everything
mico pack -o migration.zst
# On the target server — restore everything
mico unpack migration.zst
# Backup to S3
mico backup
# Restore from S3
mico unpack --s3Pack running Docker containers into a migration archive.
mico pack [flags]| Flag | Short | Default | Description |
|---|---|---|---|
--output |
-o |
mico-<timestamp>.zst |
Output archive path |
--containers |
-c |
(all) | Comma-separated container names |
--concurrent |
-j |
1 |
Number of concurrent workers |
--incremental |
false |
Only pack containers changed since last run |
Examples:
# Pack all running containers
mico pack
# Pack specific containers with 4 workers
mico pack -c web,db,redis -j 4
# Incremental pack (only changes since last run)
mico pack --incremental
# Custom output path
mico pack -o production-backup.zstRestore containers from a migration archive.
mico unpack [flags] <archive>| Flag | Short | Default | Description |
|---|---|---|---|
--s3 |
false |
Restore from S3 instead of local file | |
--bucket |
-b |
(from ~/.mico/s3.ini) | S3 bucket name |
--key |
-k |
(latest) | Specific backup key to restore |
--list |
-l |
false |
List available backups in S3 |
--no-verify |
false |
Skip checksum verification | |
--force |
-f |
false |
Force restore (overwrite existing) |
--concurrent |
-j |
1 |
Number of concurrent operations |
Examples:
# Unpack local archive
mico unpack migration.zst
# Restore latest backup from S3
mico unpack --s3
# List all backups in S3
mico unpack --s3 --list
# Restore specific backup from S3
mico unpack --s3 -k backup-2026/05/13/150405/s3_temp.zst
# Restore from S3 without checksum verification
mico unpack --s3 --no-verify
# Force restore with 4 concurrent workers
mico unpack -f -j 4 migration.zstPack containers and upload the archive to S3-compatible storage. Supports periodic backups.
mico backup [flags]| Flag | Short | Default | Description |
|---|---|---|---|
--bucket |
-b |
(from ~/.mico/s3.ini) | S3 bucket name |
--containers |
-c |
(all) | Comma-separated container names |
--interval |
-i |
0 |
Backup interval in hours (0 = run once) |
--retention |
-r |
0 |
Number of backups to keep (0 = keep all) |
--concurrent |
-j |
1 |
Number of concurrent operations |
Examples:
# One-time backup
mico backup
# Specific containers only
mico backup -c web,db
# Custom bucket, periodic every 6 hours, keep last 28
mico backup -b my-bucket -i 6 -r 28Place a config file at ~/.mico/s3.ini. Compatible with any S3-compatible object storage (AWS S3, RustFS, MinIO, etc.).
Example for RustFS:
[default]
region = us-east-1
endpoint = http://192.168.1.100:9000
bucket = my-backups
use_path_style = true
aws_access_key_id = your-access-key
aws_secret_access_key = your-secret-keySupported options:
| Key | Required | Description |
|---|---|---|
endpoint |
No | S3-compatible API endpoint (omit for AWS default) |
bucket |
No | Default bucket name (can be overridden by --bucket) |
use_path_style |
No | Set true for MinIO / RustFS / self-hosted S3 |
region |
No | AWS region |
aws_access_key_id |
No | Access key |
aws_secret_access_key |
No | Secret key |
All SDK-native options (region, aws_access_key_id, aws_secret_access_key, etc.) are loaded via the standard AWS credential chain.
If
~/.mico/s3.iniis not present, the program falls back to the default AWS credential chain (environment variables,~/.aws/credentials, IAM instance profiles, etc.).
- Scan all running containers (or filtered by
--containers) - Analyze Docker Compose
depends_onfrom container labels - Topological sort to determine start order
- Save images (
docker save), inspect configs, backup volumes & bind mounts - Bundle everything into a
.zst(Zstandard-compressed tar) archive - Generate SHA256 checksum
- Verify SHA256 checksum (optional)
- Decompress and extract the archive
- Check for port conflicts
- Load Docker images (
docker load) - Restore named volumes and bind mounts
- Recreate Docker networks
- Recreate and start containers in dependency order
migration.zst # Compressed archive
migration.zst.sha256 # SHA256 checksum sidecar (generated alongside archive)
Archive contents:
├── manifest.json # Package metadata & service definitions
└── services/
└── <service-name>/
├── config.json # Container inspect JSON
├── image.tar # Docker image save output
├── hostconfig.json
├── networks.json
└── mounts.json
- Docker Engine 20.10+ on both source and target servers
- Sufficient disk space for the archive (~ sum of all image sizes)
docker save/docker loadavailability
# Install dependencies
make deps
# Build
make build
# Run tests
make test
# Preview (build + pack)
make preview
# Clean build artifacts
make cleanMIT