Building a Docker container

Index Cloud Partners
Last Updated: September 09, 2026

Before you begin: Complete Build a gRPC RTD service. Also read the Publisher request payload reference, and the DSP bid response payload reference if you are implementing bid shading, to understand which signals are available to your logic.

This topic covers packaging your gRPC service as a Docker container that meets Index Cloud's requirements. Read the constraints below carefully before making language or architecture decisions, particularly the no-egress requirement and security constraints, which have significant implications for how you structure your service.

Networking and security constraints

The following constraints are enforced by Index Cloud and cannot be changed. They affect both how you write your GetMutations implementation and how you package your container, so read them before writing any code.

  • No egress. Your container cannot make outbound network calls at runtime. Ingress to your container is only available within Index Cloud. Everything your logic needs at runtime, including lookup tables and your own configuration, must be built into the image. The one exception is model data, which Index mounts at MODEL_PATH. Any architecture that relies on external API calls or database lookups during request handling will not work. This does not prevent you from updating model data after deployment: Index syncs those files from your Amazon S3 bucket and mounts them into your container, so your container only ever reads a local path. See Updating models in containers without rebuilding.

  • Read-only filesystem. Your container runs with a read-only filesystem.

  • Non-root execution. Containers run as user 1000, group 1000. Ensure your base image and entrypoint are compatible.

  • Vulnerability scanning. All images are scanned on download and on an ongoing basis. A CVSS score of 9 or higher blocks deployment. Choose base images carefully.

  • Cryptographically signed code. Containers run in isolated environments per partner.

  • Model data. This is mounted at MODEL_PATH. See Environment variables.

Logging

Logs from your container should be written to STDOUT or STDERR, as appropriate. Index Exchange (Index) collects these logs and reserves the right to decide what log information to make available to you.

Note: Prefer metrics over verbose logging. Use metrics, not logs, to capture container performance.

Recommended base images

Choose a minimal base image to keep your image under 1 GiB and reduce vulnerability surface. Recommended options are gcr.io/distroless/base-nossl (Go, Rust) and alpine:latest. Avoid full OS images such as ubuntu or debian unless necessary, because these are more likely to contain packages with a CVSS score of 9 or higher that would block deployment. Ensure the base image is compatible with non-root execution (user 1000, group 1000) and x86 architecture.

Container resource profile

Your container must meet the following requirements:

RequirementSpecification

Architecture

x86

Max image size

1 GiB

Max model data size

5 GiB

Response SLA

tmax fixed at 5ms. p95 must stay under 30ms at the Publisher Request extension point, or under 5ms at DSP Bid Response. See the Latency section in Build a gRPC RTD service.

Max error rate

< 3%

Required endpoints

Containers must expose the endpoints described below. GRPC_PORT is used for the gRPC service and the required gRPC healthcheck protocol. SERVER_PORT is used for the required HTTP metrics endpointClosed A URL which is configured to interact with a server in a specific way..

Orchestration endpoints

Containers MUST implement the gRPC healthcheck protocol (grpc.health.v1.Health) on GRPC_PORT per the gRPC Health Checking Protocol. Index and the testing tool probe this endpoint using Kubernetes' native gRPC probe support. For how Kubernetes calls it and what a failed check does to your container, see Kubernetes: Configure Liveness, Readiness and Startup Probes.

Your container is queried for two distinct checks against this endpoint:

  • Liveness MUST report SERVING while the main thread is running, and NOT_SERVING otherwise.

  • Readiness MUST report SERVING only once the application, including model load, is ready to serve traffic, and NOT_SERVING otherwise.

Metrics endpoint

Containers MUST expose an HTTP metrics endpoint at /metrics, which provides runtime metrics in Prometheus format. See Validating a container for the required metric, permitted tags, and an example response.

Environment variables

Index sets the following environment variables in your container at runtime. Do not hardcode these values. Read them from the environment at startup.

VariableDescription

SERVER_PORT

Port for your container's HTTP metrics endpoint (/metrics). Set by Index at container start. Always read it from the environment. There is no fixed default, unlike GRPC_PORT, which defaults to 50051.

GRPC_PORT

Port your gRPC service listens on. Set by Index at container start. Default: 50051.

MODEL_PATH

Directory where model data files are mounted. Your container reads model files from here at startup. Ensure this directory exists by creating it with mkdir -p $MODEL_PATH in your Dockerfile. The read-only filesystem constraint applies at runtime, so creating the directory at build time this way is fine.

Usage examples

The following examples show how to read these variables at startup.

Go

grpcPort := os.Getenv("GRPC_PORT")
if grpcPort == "" { grpcPort = "50051" }
serverPort := os.Getenv("SERVER_PORT")
modelPath := os.Getenv("MODEL_PATH")

Rust

let grpc_port = std::env::var("GRPC_PORT").unwrap_or("50051".into());
let server_port = std::env::var("SERVER_PORT").expect("SERVER_PORT must be set");
let model_path = std::env::var("MODEL_PATH").expect("MODEL_PATH must be set");

Recommended languages

The following table summarizes how each language performs against the latency profile this integration requires:

LanguageRecommendationNotes

Rust

Recommended

Best raw throughput. No GC pauses, predictable latency. Maximizes QPSClosed Queries Per Second (QPS). The number of bid requests a DSP processes per second. Also known as impressions per second. per core.

Go

Recommended

Strong concurrency model, excellent gRPC ecosystem. ARTF reference implementations are in Go and Rust.

C++, Java

Use with care

Require more care around latency consistency.

Python

Not recommended

Difficult to meet the 5ms latency requirement without offloading request processing to native code.

The ARTF reference implementations are available at github.com/IABTechLab/agentic-rtb-framework.

Architectural patterns

Apply the following patterns when structuring your service.

Do

  • Pre-load at startup. All data should be integrated into the image or loaded from mounted files at boot. Only signal readiness once everything is fully loaded.

  • Cache aggressively. Use memory for lookup tables, model weights, and pre-computed decisions.

  • Minimize per-request allocation. Object pooling, pre-allocated buffers, and arena patterns reduce GC pressure (Go) and allocation overhead (Rust).

  • Keep the gRPC handler minimal. Deserialize, run logic, build mutations, return. Log and aggregate telemetry asynchronously.

  • Design for graceful restarts. Signal readiness only once the model is fully loaded.

Don't

  • Make external network calls during request handling.

  • Use heavy per-request logging. Use metrics counters instead.

  • Load models dynamically after startup.

  • Ship large images built from unnecessary dependencies.

Next: Continue to Validate your image to start testing what you have built.