> ## Documentation Index
> Fetch the complete documentation index at: https://docs.streamnative.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Runner Images for BYOC Pro

<Note title="BYOC Pro Feature">
  This feature is available for **BYOC Pro clusters only** with trusted mode enabled. To enable trusted mode, [submit a support ticket](https://support.streamnative.io/hc/en-us/requests/new) through StreamNative support.
</Note>

BYOC Pro users can build and use custom runner images for Pulsar functions and IO connectors when trusted mode is enabled. This capability provides the following benefits:

* Include custom dependencies and libraries
* Use specific versions of runtime environments
* Customize the execution environment for your workloads
* Package application-specific configurations

<Warning title="Configuration Impact">
  Custom runner images provide low-level control over the execution environment. **Incorrect image configuration affects the normal operation of Pulsar functions and IO connectors.** Test thoroughly in development environments before deploying to production.
</Warning>

## Prerequisites

* **BYOC Pro cluster** with trusted mode enabled
* Docker installed and configured
* Access to a Docker registry (Docker Hub, private registry, etc.)
* Basic understanding of Dockerfile syntax and container concepts

## Base Images

StreamNative provides official base images for different runtime environments:

### Java Functions

* **Registry**: [streamnative/pulsar-functions-pulsarctl-java-runner](https://hub.docker.com/r/streamnative/pulsar-functions-pulsarctl-java-runner)

```dockerfile theme={null}
FROM streamnative/pulsar-functions-pulsarctl-java-runner:4.0.5.2
```

### Python Functions

* **Registry**: [streamnative/pulsar-functions-pulsarctl-python-runner](https://hub.docker.com/r/streamnative/pulsar-functions-pulsarctl-python-runner)

```dockerfile theme={null}
FROM streamnative/pulsar-functions-pulsarctl-python-runner:4.0.5.2
```

<Note title="Version Selection">
  Use the appropriate base image version that matches your StreamNative Cloud cluster version. Check the [release notes](/release-notes/) for compatibility information.
</Note>

## Building Custom Images

### 1. Create Dockerfile

Create a Dockerfile that extends the StreamNative base image:

```dockerfile theme={null}
FROM streamnative/pulsar-functions-pulsarctl-java-runner:4.0.5.2

# Install additional system packages if needed
USER root
RUN apt-get update && apt-get install -y your-package
USER $UID
# Copy your function JAR and dependencies
COPY --chown=$UID:$GID example-function.jar /pulsar/
COPY --chown=$UID:$GID dependencies/ /pulsar/lib/
```

<Warning title="File Ownership">
  Always use `--chown=$UID:$GID` when copying files. The `$UID` and `$GID` environment variables are provided by StreamNative base images and ensure proper file permissions. **Do not change these values.**
</Warning>

### 2. Build and Push Image

```bash theme={null}
# Build the Docker image
docker build -t your-registry/custom-function:v1.0 .

# Push to your registry
docker push your-registry/custom-function:v1.0
```

### 3. Deploy Function with Custom Image

Use the `runnerImage` parameter in [`custom-runtime-options`](/cloud/process/pulsar-functions/function-config#trusted-mode-configuration):

```bash theme={null}
snctl pulsar admin functions create \
  --tenant your-tenant \
  --namespace your-namespace \
  --name custom-function \
  --jar example-function.jar \
  --classname com.example.MyFunction \
  --inputs input-topic \
  --output output-topic \
  --custom-runtime-options '{"runnerImage": "your-registry/custom-function:v1.0"}'
```

## Examples

### Java Function with Custom Dependencies

```dockerfile theme={null}
FROM streamnative/pulsar-functions-pulsarctl-java-runner:4.0.5.2

# Copy function JAR and custom dependencies
COPY --chown=$UID:$GID target/my-function.jar /pulsar/
COPY --chown=$UID:$GID target/lib/*.jar /pulsar/lib/

# Copy additional configuration files
COPY --chown=$UID:$GID config/logging.properties /pulsar/conf/
```

## Configuration with Other Trusted Mode Options

Combine custom images with other trusted mode configurations:

```json theme={null}
{
  "runnerImage": "your-registry/custom-function:v1.0",
  "javaOPTs": ["-Dmy.custom.config=value"]
}
```

## Best Practices

### Security

* Use minimal base images to reduce attack surface
* Scan images for vulnerabilities before deployment
* Use private registries for proprietary code
* Follow principle of least privilege for container permissions

### Performance

* Optimize image layers for efficient caching
* Remove unnecessary files and packages
* Use multi-stage builds for smaller final images
* Consider image pull time in high-throughput scenarios

### Maintenance

* Tag images with semantic versions
* Maintain compatibility with StreamNative base image updates
* Document custom dependencies and configurations
* Test images thoroughly before production deployment

## Troubleshooting

### Common Issues

**Image Pull Failures**

* Verify registry credentials and access permissions
* Check network connectivity from cluster to registry
* Ensure image tag exists and is properly formatted

**Permission Errors**

* Verify `--chown=$UID:$GID` is used for all COPY operations
* Check that files have correct permissions within the image
* Ensure service account has proper Kubernetes permissions

**Runtime Failures**

* Validate base image compatibility with cluster version
* Check that required dependencies are properly installed
* Verify classpath and module path configurations

For additional troubleshooting support, [contact StreamNative support](https://support.streamnative.io/hc/en-us/requests/new) with your custom image configuration details.
