Why move
Domains on VMs drift, scale slowly and are patched by hand. On OKE, the domain is described as a model, built into an image, and the operator manages servers, scaling and rolling restarts.
1. Discover the existing domain
WebLogic Deploy Tooling turns a running domain into a portable model (YAML) plus an archive of applications:
$WDT_HOME/bin/discoverDomain.sh -oracle_home $ORACLE_HOME -domain_home /u01/domains/app_domain \
-archive_file /tmp/app_domain.zip -model_file /tmp/app_domain.yaml -variable_file /tmp/app_domain.properties
Review the model: datasources, JMS, security realms, file paths that only exist on the VM, hostnames and ports. Replace secrets with model tokens (@@SECRET:...@@) so they come from Kubernetes secrets.
2. Build the image
imagetool create --tag ocir.eu-frankfurt-1.oci.oraclecloud.com/<ns>/wls-base:14.1.1 \
--jdkVersion 11 --version 14.1.1.0.0 --latestPSU
imagetool createAuxImage --tag ocir.eu-frankfurt-1.oci.oraclecloud.com/<ns>/app-model:1.0 \
--wdtModel /tmp/app_domain.yaml --wdtArchive /tmp/app_domain.zip --wdtVariables /tmp/app_domain.properties
docker push ocir.eu-frankfurt-1.oci.oraclecloud.com/<ns>/app-model:1.0
Patching to the latest PSU requires My Oracle Support credentials for the tool. The auxiliary image pattern keeps the WebLogic install image separate from your domain model and apps.
3. Install the operator
helm repo add weblogic-operator https://oracle.github.io/weblogic-kubernetes-operator/charts
helm install weblogic-operator weblogic-operator/weblogic-operator -n weblogic-operator --create-namespace \
--set "domainNamespaceSelectionStrategy=LabelSelector" --set "domainNamespaceLabelSelector=weblogic-operator=enabled"
kubectl create ns app && kubectl label ns app weblogic-operator=enabled
4. Deploy the domain
apiVersion: weblogic.oracle/v9
kind: Domain
metadata: { name: app-domain, namespace: app }
spec:
domainHomeSourceType: FromModel
domainHome: /u01/domains/app-domain
image: ocir.eu-frankfurt-1.oci.oraclecloud.com/<ns>/wls-base:14.1.1
imagePullSecrets: [{ name: ocir-secret }]
webLogicCredentialsSecret: { name: app-domain-weblogic-credentials }
configuration:
model:
auxiliaryImages: [{ image: ocir.eu-frankfurt-1.oci.oraclecloud.com/<ns>/app-model:1.0 }]
runtimeEncryptionSecret: app-domain-runtime-encryption
secrets: [app-db-credentials]
clusters: [{ name: app-domain-cluster-1 }]
replicas: 3
---
apiVersion: weblogic.oracle/v1
kind: Cluster
metadata: { name: app-domain-cluster-1, namespace: app }
spec: { clusterName: cluster-1, replicas: 3 }
kubectl apply -f domain.yaml
kubectl get domain,pods -n app -w
5. Expose it
Use an ingress controller (OCI Native Ingress Controller or NGINX) or a LoadBalancer service with OCI LB annotations, with session affinity if the app relies on HTTP sessions. Keep the admin server internal only.
6. Data and state
- Datasources point at the database (Base DB, Autonomous) — open NSGs from the OKE pod/worker subnets.
- JMS file stores and transaction logs: move to JDBC stores in the database, or use persistent volumes.
- Logs: write to stdout or ship server logs with a sidecar to OCI Logging.
7. Cut over
Run old and new side by side behind a load balancer with weighted backends, shift traffic in steps, keep the VM domain stopped for the rollback window.
Checklist
- Domain discovered with WDT; secrets externalised
- Base and auxiliary images built with current PSU, pushed to OCIR
- Operator installed; domain healthy with probes
- JMS/TLOG stores moved out of local disk
- Traffic shifted; VMs retired