Image migration script
The migrate-images.sh script automates the process of pulling OpenIAM Docker images from the official source registry, retagging them, and pushing them to a target registry (such as a self-hosted Harbor instance). This is useful for:
- Air-gapped / offline Kubernetes environments that cannot access the internet.
- Internal enterprise registries for security compliance.
- Version-controlled image promotion between environments (dev, staging, prod).
- Disaster recovery — maintaining a local mirror of all required images.
The script interactively prompts for all credentials, auto-detects the current image tag from the live Kubernetes cluster, and automatically creates Harbor projects if they do not exist.
Prerequisites
Ensure all of the following are in place before running the script.
Software requirements
| Component | Minimum Version | Notes |
|---|---|---|
| Docker | 20.10+ | Must be installed and running on the machine executing the script |
| Docker Compose | v2.0+ (plugin) | Required only for Harbor setup, not for migration itself |
| Bash | 4.0+ | Script uses associative arrays and mapfile — sh is not supported |
| Python 3 | 3.6+ | Used for auto-detecting image tag from kubectl JSON output |
| kubectl | 1.20+ | Optional — needed for auto tag detection from cluster; if absent, tag is prompted manually |
| curl | Any | Required for Harbor project auto-creation via REST API |
Network requirements
- Outbound HTTPS (port 443) to
registry.openiam.comfrom the migration host - Outbound access to
hub.docker.com(port 443) for public images:busyboxandhashicorp/consul-k8s-control-plane - Inbound/outbound access to the target registry (default port 80 for Harbor HTTP, 443 for HTTPS)
- If using HTTP (insecure) for target registry — Docker daemon must be configured with
insecure-registries
Credentials required
| Registry | Credential Type | Where to Obtain |
|---|---|---|
| registry.openiam.com | Username + Password | Provided by OpenIAM support / your license agreement |
| Target Registry (Harbor) | Username + Password | Harbor admin account — default: admin / Harbor12345 |
| Docker Hub (public images) | Not required | busybox and hashicorp images are pulled anonymously |
Disk space
To clean up local images after a successful migration run the following.
# Remove all pulled openiam images after migrationdocker images | grep 'registry.openiam.com' | awk '{print $3}' | xargs docker rmi -f# Check remaining disk usagedocker system df
Docker insecure registry (HTTP only)
If the target registry runs on HTTP (not HTTPS), Docker must be configured to allow insecure connections. Skip this step if using HTTPS with a valid certificate.
# Edit or create /etc/docker/daemon.jsoncat > /etc/docker/daemon.json << 'EOF'{"insecure-registries": ["<TARGET_REGISTRY_IP_OR_HOST>:<PORT>"]}EOF# Restart Docker to applysudo systemctl restart docker# Verifydocker info | grep -A5 'Insecure Registries'
Harbor target registry setup
If using Harbor as the target registry, it can be set up on the same Linux host using the harbor-setup.sh script. Harbor requires:
- Linux host (RHEL 8/9/10, Ubuntu 20.04+, or CentOS 8+)
- Docker 20.10+ and Docker Compose v2+
- Minimum 4 GB RAM, 2 vCPUs, 80 GB disk for Harbor data
- Port 80 (HTTP) or 443 (HTTPS) available — not used by another service
For other Linux distributions, please manually install the required prerequisites (such as Docker Compose and other dependencies) using the appropriate package manager and commands for your operating system. Once the prerequisites are installed, you can use the script to complete the Harbor setup.
Image Inventory
The following 46 images are migrated by the script. This list was captured from the live Kubernetes cluster on June 2026.
Infrastructure images (openiam_infra)
| Image | Purpose |
|---|---|
| openiam_infra/activiti | Workflow engine (BPMN) |
| openiam_infra/cassandra | NoSQL database for IAM data |
| openiam_infra/certificate-generator | TLS/SSL certificate provisioning |
| openiam_infra/chown | Init container — file permission fixer |
| openiam_infra/consul | Service mesh and config store |
| openiam_infra/curator | OpenSearch index lifecycle manager |
| openiam_infra/flyway | Database schema migration tool |
| openiam_infra/iamscripts | Bootstrap and initialization scripts |
| openiam_infra/janusgraph | Graph database for identity relationships |
| openiam_infra/medusa | Secrets and config management |
| openiam_infra/nfs-provisioner | Kubernetes NFS storage provisioner |
| openiam_infra/nginx | Reverse proxy / ingress |
| openiam_infra/opensearch-k8 | Search and analytics engine |
| openiam_infra/postgres-k8 | PostgreSQL relational database |
| openiam_infra/rabbitmq-k8 | Message queue broker |
| openiam_infra/redis-k8 | In-memory cache |
| openiam_infra/redis-sentinel | Redis high-availability sentinel |
| openiam_infra/vault | HashiCorp Vault secrets manager |
| openiam_infra/vault-bootstrap | Vault initialization and unseal job |
Service images (openiam_service)
| Image | Purpose |
|---|---|
| openiam_service/audit-log-manager | Audit trail and compliance logging |
| openiam_service/auth-manager | Authentication and token management |
| openiam_service/business-rule-manager | Policy and business rule engine |
| openiam_service/email-manager | Email notification service |
| openiam_service/esb | Enterprise Service Bus — event routing |
| openiam_service/groovy-manager | Groovy script execution engine |
| openiam_service/idm | Identity management core service |
| openiam_service/idp | Identity Provider / SSO / SAML |
| openiam_service/jdbc-connector-rabbitmq | JDBC database connector via RabbitMQ |
| openiam_service/ldap-connector-rabbitmq | LDAP directory connector via RabbitMQ |
| openiam_service/linux-connector-rabbitmq | Linux system connector via RabbitMQ |
| openiam_service/machine-learning | ML-powered risk and anomaly detection |
| openiam_service/reconciliation | Account reconciliation service |
| openiam_service/reportviewer | Reports and dashboard viewer |
| openiam_service/rproxy | Reverse proxy for service routing |
| openiam_service/scim-connector-rabbitmq | SCIM protocol connector |
| openiam_service/script-connector-rabbitmq | Custom script connector via RabbitMQ |
| openiam_service/selfservice | End-user SelfService portal |
| openiam_service/selfservice-ext | SelfService portal extensions |
| openiam_service/selfservice-v2-ui | SelfService UI v2 (React) |
| openiam_service/synchronization | Identity synchronization engine |
| openiam_service/ui-static | Static UI assets server |
| openiam_service/webconsole | Admin web console |
| openiam_service/workflow | Workflow orchestration engine |
Public / Third-party images
| Image | Purpose |
|---|---|
| busybox:latest | Lightweight init/debug container |
| hashicorp/consul-k8s-control-plane:1.6.3 | HashiCorp Consul Kubernetes controller |
Environment Variables
All credentials and settings can be pre-set as environment variables to avoid interactive prompts. This is recommended for CI/CD pipelines or automated deployments.
| Variable | Default | Description |
|---|---|---|
| SOURCE_REGISTRY | registry.openiam.com | OpenIAM source registry hostname |
| SOURCE_USER | (prompted) | Username for source registry login |
| SOURCE_PASS | (prompted) | Password for source registry login |
| TARGET_REGISTRY | (prompted) | Target registry IP:port or hostname (e.g. 10.1.0.10:80) |
| TARGET_USER | (prompted) | Username for target registry login |
| TARGET_PASS | (prompted) | Password for target registry login |
| SOURCE_TAG | (auto-detect) | Override auto-detected source image tag |
| NEW_TAG | (same as source) | New tag to apply on target registry (for version bumps) |
Usage
Interactive mode (recommended for first run)
Download the repository which contains the migration script and Harbor repository setup.
git clone https://github.com/openiam-platform/kubernetes-docker-configuration.gitcd kubernetes-docker-configurationgit checkout RC-2026.6.2
Run the script (migrate-images.sh) without any environment variables. It will prompt for all required inputs:
bash migrate-images.sh# The script will ask for:# Source registry URL (default: registry.openiam.com)# Source username# Source password (hidden — no echo)# Target registry URL (e.g. 10.1.0.10:80)# Target username# Target password (hidden — no echo)# New tag (Enter to keep same as detected source tag)
Non-interactive mode
Set environment variables before running. The script skips prompts for any pre-set variables.
export SOURCE_REGISTRY="registry.openiam.com"export SOURCE_USER="openiam_user"export SOURCE_PASS="openiam_password"export TARGET_REGISTRY="10.1.0.10:80"export TARGET_USER="admin"export TARGET_PASS="Harbor12345"export SOURCE_TAG="2026.5.1-prod"export NEW_TAG="2026.6.0-prod" # New version tag on target# Run non-interactively (auto-confirm)bash migrate-images.sh <<< "yes"
Mirror same version (no tag change)
To simply mirror images with the same tag (no version bump):
export NEW_TAG="" # Leave empty — script keeps same tagbash migrate-images.sh# Or press Enter when prompted for new tag
Upgrading to new OpenIAM version
When OpenIAM releases a new version (e.g. 2026.6.1), simply update the NEW_TAG:
# Script auto-detects current cluster tag: 2026.5.1-prod# Set the new version as target tagexport NEW_TAG="2026.6.0-prod"bash migrate-images.sh <<< "yes"# Result:# Pulls: registry.openiam.com/openiam_infra/cassandra:2026.5.1-prod# Pushes: 10.1.0.10:80/openiam_infra/cassandra:2026.6.0-prod
How the script works
The script follows this workflow for each image:
| Step | Action | Detail |
|---|---|---|
| 1 | Collect inputs | Prompts or reads env vars for source/target registry, credentials, and tags. |
| 2 | Auto-detect tag | Runs kubectl get pods to find the current OpenIAM image tag from the live cluster. |
| 3 | Login | Runs docker login for both source and target registries. |
| 4 | Create projects | Calls Harbor REST API to create openiam_infra, openiam_service, public projects if missing. |
| 5 | Pull | docker pull from source registry for each image. |
| 6 | Retag | docker tag — applies target registry URL and new tag |
| 7 | Push | docker push to target registry |
| 8 | Summary | Prints success/failure count, timing, and list of any failed images |
Troubleshooting
Pull failed: unauthorized
Source registry credentials are incorrect or the account does not have pull access. Verify:
- Username and password are correct
- Account has pull permissions on
registry.openiam.com - Check with OpenIAM support if the account is active
Push failed: project does not exist
The target registry is not Harbor, or the Harbor API is not reachable. Manually create the projects:
# Manually create projects via Harbor APIfor PROJECT in openiam_infra openiam_service public; docurl -u admin:Harbor12345 -X POST http://10.1.0.10:80/api/v2.0/projects \-H 'Content-Type: application/json' \-d "{\"project_name\": \"${PROJECT}\", \"public\": true}"done
Push failed: server gave HTTP response to HTTPS client
Docker is trying to use HTTPS but the registry is running HTTP. Add the registry to insecure-registries in /etc/docker/daemon.json and restart Docker. See Section 2.5.
Auto tag detection not working
kubectl is not installed or not configured with the correct kubeconfig. Either:
- Install
kubectland configure it:export KUBECONFIG=/path/to/kubeconfig - Set the
SOURCE_TAGenvironment variable manually before running the script
No space left on device during pull
Free up disk space on the migration host. See Section 2.4 for cleanup commands. Alternatively, migrate in batches by temporarily commenting out image entries in the build_image_list function.
Quick reference
# ── First time setup ─────────────────────────────────────────sudo bash harbor-setup.sh # Install Harborbash migrate-images.sh # Run migration (interactive)# ── Check Harbor status ──────────────────────────────────────cd /opt/harbor && docker compose ps# ── Stop / Start Harbor ──────────────────────────────────────cd /opt/harbor && docker compose downcd /opt/harbor && docker compose up -d# ── Verify images in Harbor ──────────────────────────────────curl -s -u admin:Harbor12345 \http://10.1.0.10:80/api/v2.0/repositories?page_size=50 \| python3 -m json.tool | grep name# ── Refresh image list from cluster ─────────────────────────kubectl get pods -o json | python3 -c "import json,sys; data=json.load(sys.stdin); imgs=set()[imgs.add(c['image']) for i in data['items']for c in i['spec'].get('containers',[])+i['spec'].get('initContainers',[])][print(i) for i in sorted(imgs) if i]"# ── Next version upgrade ─────────────────────────────────────NEW_TAG="2026.6.0-prod" bash migrate-images.sh <<< "yes"