Skip to main content
Version: v1.0.0-rc.1 (pre-release)

Deploy a Prebuilt Container Image

This guide walks you through deploying a prebuilt container image to OpenChoreo. This is useful when you have existing container images built by external CI/CD pipelines and want to deploy them without using OpenChoreo's Workflow Plane.

Overview​

OpenChoreo supports deploying applications from prebuilt container images, commonly referred to as "Bring Your Own Image" (BYOI). You can deploy images from:

  • Public registries - No additional configuration needed
  • Private registries - Requires setting up image pull credentials

Prerequisites​

Before you begin, ensure you have:

  • OpenChoreo installed in your Kubernetes cluster
  • kubectl configured to access your cluster
  • A container image to deploy

Deploy from a Public Registry​

Deploying an image from a public registry is straightforward - simply create the Component and Workload resources.

Example​

kubectl apply -f - <<EOF
---
apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-app
namespace: default
spec:
autoDeploy: true
componentType:
kind: ClusterComponentType
name: deployment/service
owner:
projectName: default
parameters: {}
---
apiVersion: openchoreo.dev/v1alpha1
kind: Workload
metadata:
name: my-app-workload
namespace: default
spec:
owner:
componentName: my-app
projectName: default
container:
image: "nginx:latest"
endpoints:
http:
port: 80
type: HTTP
visibility: ["project", "external"]
EOF

Replace the following values with your own:

  • nginx:latest - Your image reference
  • 80 - The port your application listens on
  • Add environment variables as needed by your application

Verify the Deployment​

Check that the component is created:

kubectl get component my-app

Check that the workload is created:

kubectl get workload my-app-workload

Check that pods are running:

kubectl get pods -A | grep my-app

Test Your Application​

Once the deployment is ready, test your application:

curl http://development-default.openchoreoapis.localhost:19080/my-app-http

Deploy from a Private Registry​

Deploying from a private registry requires three steps before you can create your Component and Workload:

  1. Store your registry credentials in your dataplane secret store
  2. Configure your ClusterComponentType to sync those credentials as an image pull secret
  3. Deploy the Component and Workload pointing to your private image

Step 1 β€” Store Registry Credentials​

note

This example uses the default ClusterSecretStore included with the default OpenChoreo installation. For production environments, see Secret Management to configure a proper secret backend.

Generate the auth string (base64-encoded username:password or username:access-token):

echo -n "your-dockerhub-username:your-access-token" | base64

Store the credentials in OpenBao (default local dev setup):

kubectl exec -n openbao openbao-0 -- sh -c '
export BAO_ADDR=http://127.0.0.1:8200 BAO_TOKEN=root
bao kv put secret/registry-credentials \
value="{\"auths\":{\"https://index.docker.io/v1/\":{\"auth\":\"<your-base64-auth-string>\"}}}"
'

Replace <your-base64-auth-string> with the output from the previous command. For other secret backends, store the same Docker config JSON under the key registry-credentials.

Step 2 β€” Configure Your ClusterComponentType​

The deployment/service ClusterComponentType needs two additions to support private registry pulls:

An ExternalSecret to sync the credentials from your secret store into the workload namespace:

- id: registry-pull-secret
template:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: registry-pull-secret
namespace: ${metadata.namespace}
spec:
refreshInterval: 15s
secretStoreRef:
name: ${dataplane.secretStore}
kind: ClusterSecretStore
target:
name: registry-pull-secret
creationPolicy: Owner
template:
type: kubernetes.io/dockerconfigjson
data:
- secretKey: .dockerconfigjson
remoteRef:
key: registry-credentials
# For OpenBao local dev setup, secrets are stored under the 'value' property
property: value

imagePullSecrets in the Deployment template so pods can authenticate when pulling:

- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${metadata.name}
namespace: ${metadata.namespace}
spec:
template:
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: main
image: ${workload.container.image}
# ... rest of container config

Step 3 β€” Deploy the Component and Workload​

Once credentials are stored and your ClusterComponentType is updated, deploy the Component and Workload the same way as a public image β€” just point the image field to your private registry:

kubectl apply -f - <<EOF
---
apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-private-app
namespace: default
spec:
autoDeploy: true
componentType:
kind: ClusterComponentType
name: deployment/service
owner:
projectName: default
parameters:
exposed: true
port: 80
replicas: 1
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
---
apiVersion: openchoreo.dev/v1alpha1
kind: Workload
metadata:
name: my-private-app
namespace: default
spec:
owner:
componentName: my-private-app
projectName: default
container:
image: "docker.io/your-dockerhub-username/your-private-image:v1"
endpoints:
http:
port: 80
type: HTTP
visibility: ["project", "external"]
EOF

Replace docker.io/your-dockerhub-username/your-private-image:v1 with your actual private image reference.

Verify the Deployment​

Check that pods are running and the image was pulled successfully:

kubectl get pods -A | grep my-private-app

If the pod is in ImagePullBackOff state, verify your credentials were stored correctly:

kubectl get externalsecret -A | grep registry-pull-secret
kubectl describe externalsecret registry-pull-secret -n <workload-namespace>

Test Your Application​

curl http://development-default.openchoreoapis.localhost:19080/my-private-app-http

Summary​

You've learned how to deploy prebuilt container images using the OpenChoreo BYOI (Bring Your Own Image) flow from both public and private registries.

Next Steps​