Configure and Deploy Confluent Gateway using Docker
Configure and deploy Confluent Gateway using Docker. You can use this deployment path to run Confluent Gateway on-premises, in VPCs, and across hybrid environments.
For general requirements and considerations, see Requirements and considerations. For Docker-specific requirements, see Docker software requirements.
Deploy Confluent Gateway using Docker with the following steps:
Configure Confluent Gateway by defining streaming domains, routes, and administration settings in a Docker Compose file.
Deploy Confluent Gateway by pulling the Confluent Gateway Docker image and starting the service with Docker Compose.
After deployment, configure security and reconfigure clients to use the Confluent Gateway endpoint. For more information, see Next steps.
Configure Confluent Gateway using Docker Compose
Provide the configuration settings in a Docker Compose YAML file. This guide
uses docker-compose.yaml as an example.
The top-level layout for the Confluent Gateway configuration file is as follows:
gateway:
name: --- [1]
streamingDomains: [] --- [2]
secretStores: [] --- [3]
routes: [] --- [4]
admin: {} --- [5]
[1] The Confluent Gateway instance identifier.
[2] A list of streaming domains that represent Apache Kafka® clusters. For more information, see Streaming domains configuration.
[3] A list of secret stores. Required for authentication swapping. For details, see Secret store configuration.
[4] A list of client routing rules. For more information, see Routes configuration.
[5] Admin and metrics configuration. For more information, see Administration and metrics configuration.
The Confluent Gateway Docker image is not a Confluent Gateway configuration setting. Set it
with the image key on the Docker Compose service. Use
confluentinc/confluent-gateway:<version_tag>, where <version_tag> is the
Confluent Gateway version.
Streaming domains configuration
Streaming domains are logical representations of your Kafka clusters in Confluent Gateway.
gateway:
streamingDomains:
- name: --- [1]
type: --- [2]
kafkaCluster: --- [3]
name: --- [4]
bootstrapServers: --- [5]
- id: --- [6]
endpoint: --- [7]
ssl: --- [8]
nodeIdRanges: --- [9]
- name: --- [10]
start: --- [11]
end: --- [12]
[1] A unique name for the streaming domain.
[2] The type of the streaming domain. Set to
kafkaby default.[3] A Kafka cluster, including Confluent Server, or Apache Kafka®, that the Confluent Gateway can route traffic to.
[4] The name of the Kafka cluster.
[5] A list of Kafka bootstrap servers in the format
host:port. At minimum, one bootstrap server is required per Kafka cluster. For each listener, you can define one bootstrap server.[6] A unique identifier for the bootstrap server. Use the protocol name, such as
SASL_PLAINTEXT,SSL, orPLAINTEXT_SASL_PLAIN, for clear distinction between the TLS channel type and SASL mechanism.[7] The bootstrap endpoint of the Kafka broker in the format:
host:port.[8] Only required for SSL/SASL_SSL configuration. Supported certificate types are
JKS,PKCS12, andPEM.For details, see SSL configuration.
[9] The node ID ranges. Only required for port-based broker identification. These should be the broker IDs defined in the Kafka deployment.
[10] The name of the node ID range.
[11] The start of the node ID range, inclusive.
[12] The end of the node ID range, inclusive.
An example configuration for a Confluent Gateway streaming domain:
streamingDomains:
- name: sales # unique across gateway
type: kafka # default: kafka
kafkaCluster:
name: sales-cluster # default: <streamingDomain.name>
bootstrapServers:
- id: PLAINTEXT-1
endpoint: kafka0.example.com:9092
- id: SASL_SSL-1
endpoint: kafka0.example.com:9093
ssl: # required when using SASL_SSL/SSL
ignoreTrust: false
truststore:
type: PKCS12 # default: JKS
location: /opt/ssl/client-truststore.p12
password:
file: /opt/secrets/client-truststore.password
keystore: # gateway's identity when needed
type: PKCS12 # default: JKS
location: /opt/ssl/gw-keystore.p12
password:
file: /opt/secrets/gw-keystore.password
keyPassword:
value: inline-password
nodeIdRanges:
- name: default
start: 0 # inclusive
end: 3 # inclusive
passwordcan be a file path or an inline value. For details, see Password configuration.ignoreTrustskips certificate validation. Not recommended for production. Whentrue, Confluent Gateway ignores thetruststoresetting.
Routes configuration
Routes are Confluent Gateway endpoints where client applications connect to stream data.
Confluent Gateway uses routes to define how client applications connect to Kafka clusters. Clients connect to Confluent Gateway as if it were a Kafka cluster, while Confluent Gateway handles routing and governance.
gateway:
routes:
- name: --- [1]
endpoint: --- [2]
mode: --- [3]
brokerIdentificationStrategy: --- [4]
type: --- [5]
pattern: --- [6]
streamingDomain: --- [7]
name: --- [8]
bootstrapServerId: --- [9]
streamingDomains: --- [10]
- name: --- [11]
bootstrapServerId: --- [12]
rules: --- [13]
security: --- [14]
[1] The unique name for the route. The name can’t contain spaces.
[2] The
host:portcombination that Confluent Gateway listens on. This is the external address clients use to bootstrap to the Kafka cluster.[3] Early Access. Optional. The routing mode of the route. Set to
STATICorDYNAMIC. The value isn’t case-sensitive.STATIC: The route is bound to a single streaming domain ([7]).DYNAMIC: The route uses topic-based routing. You bind it to a list of streaming domains ([10]), and it routes each topic to the streaming domain that owns it.
If you omit
mode, Confluent Gateway infers it from the streaming domain binding:streamingDomain([7]) sets the mode toSTATIC, andstreamingDomains([10]) sets the mode toDYNAMIC. If you setmode, it must match the binding. For example,mode: DYNAMICwithstreamingDomainis invalid.[4] Specifies the strategy for mapping client requests to a specific Kafka broker.
[5] The type of broker identification strategy. Set to
port(the default) orhost. A dynamic route ([10]) supports only thehoststrategy. Confluent Gateway assigns its own node IDs to the brokers of the bound clusters, so overlapping broker IDs across clusters don’t conflict.portstrategy: Each Kafka broker is identified using a unique port number. This is the default strategy.Clients connect to different ports to reach specific brokers. For example, port 9092 to connect with broker-0, port 9093 to connect with broker-1.
The
nodeIdRangesfrom the streaming domain configured in Streaming domains configuration is used. ThenodeIdRangesmust be present in the streaming domain associated with the route.hoststrategy: Each Kafka broker is represented using a unique hostname.Clients use different host names to reach specific brokers, such as
broker-0.kafka.company.comandbroker-1.kafka.company.com, and Confluent Gateway routes based on the Server Name Indication (SNI) header. Because SNI is part of the TLS handshake, configure TLS on the route. For more information, see SSL configuration.The
hoststrategy uses thepatternsetting ([6]).
[6] The pattern for the broker identification strategy. Required if the type ([5]) is
host. For example,broker-$(nodeId).eu-gw.sales.example.com:9092.[7] The reference to a streaming domain. Use this setting for a static route. Required if the route doesn’t use
streamingDomains([10]).[8] The name of the streaming domain. Must be a valid name from the
gateway.streamingDomains[].name.[9] The bootstrap server ID. Must match
kafkaCluster.bootstrapServers[].id.[10] Early Access. The list of references to streaming domains that the route is bound to. Use this setting for a dynamic route. Required if the route doesn’t use
streamingDomain([7]). SettingstreamingDomainsmakes the route a dynamic route. You can’t bind the same streaming domain more than once, and the list can’t contain null entries.[11] The name of a streaming domain to bind to the route. Must be a valid name from the
gateway.streamingDomains[].name.[12] The bootstrap server ID to use for the streaming domain ([11]). Must match
kafkaCluster.bootstrapServers[].id.[13] Optional. The routing rules (Early Access) and fencing rules of the route. For more information, see Routing rules configuration (Early Access) and Fencing rules configuration.
[14] The security configuration. For more information, see Configure Security for Confluent Gateway.
Each route must specify exactly one of streamingDomain ([7]) or
streamingDomains ([10]). Specifying both or neither is invalid.
The following examples show a static route and a dynamic route:
A static route binds one streaming domain with streamingDomain.
gateway:
routes:
- name: eu-sales
endpoint: eu-gw.sales.example.com:9092
brokerIdentificationStrategy:
type: host
pattern: broker-$(nodeId).eu-gw.sales.example.com:9092
streamingDomain:
name: sales
bootstrapServerId: SASL_SSL-1
A dynamic route binds a list of streaming domains with
streamingDomains and requires rules.routing. For more
information, see Routing rules configuration (Early Access).
gateway:
routes:
- name: migration-route
endpoint: migration-gw.example.com:9092
mode: DYNAMIC
brokerIdentificationStrategy:
type: host
pattern: broker-$(nodeId).migration-gw.example.com:9092
streamingDomains:
- name: cp
bootstrapServerId: cp-bootstrap
- name: cc
bootstrapServerId: cc-bootstrap
rules:
routing:
coordination:
group: cc
default: cp
Routing rules configuration (Early Access)
Configure rules.routing on dynamic routes (mode: DYNAMIC) to map
topics to specific streaming domains. For more information, see
Routes configuration.
You configure routing rules in the rules.routing setting of the route. A
dynamic route requires rules.routing, and a static route can’t use it.
To learn how to migrate a topic with routing rules, see Migrate topics between clusters.
To review the limitations, see Limitations.
Note
Topic-based routing is an Early Access feature. Property names and YAML structure might change before General Availability (GA), and the changes might not be backward compatible.
gateway:
routes:
- name:
streamingDomains:
rules:
routing: --- [1]
coordination: --- [2]
group: --- [3]
conditions: --- [4]
- topics: --- [5]
topicPatterns: --- [6]
streamingDomain: --- [7]
conditionsFile: --- [8]
default: --- [9]
[1] The routing rules that map topics to the streaming domains that own them. Required on a dynamic route.
[2] Required. Pins consumer group coordination to a streaming domain.
[3] Required. The name of the streaming domain that coordinates all consumer groups on the route, including their committed offsets. Must be a streaming domain bound to the route. All consumer group offsets for the route are stored on this cluster. Disable consumer offset sync on the cluster link, and on any other replicator that you use, so that replication doesn’t overwrite offsets that clients commit through Confluent Gateway.
[4] Optional. The list of conditions that map topics to streaming domains. Confluent Gateway evaluates the conditions in order, and the first condition that matches a topic decides which streaming domain owns it. You can’t use
conditionswithconditionsFile([8]).[5] A list of exact topic names. Confluent Gateway matches topic names literally.
[6] A list of Java regular expressions. A pattern must match the entire topic name. For example, the pattern
teamA.*matchesteamA-orders, but the patternteamAdoesn’t. Confluent Gateway validates the patterns when it loads the configuration.To match a literal period, escape it with a backslash. How you write the backslash depends on the type of YAML string:
In a double-quoted string, write the backslash twice, for example
"teamA\\..*".In a single-quoted or unquoted string, write the backslash once, for example
'teamA\..*'.
Both examples match topics that start with
teamA..A condition matches a topic if the topic is listed in
topics([5]) or matches any pattern intopicPatterns([6]). Each condition requires at least one oftopicsortopicPatterns.[7] Required for each condition. The name of the streaming domain that owns the matching topics. Must be a streaming domain bound to the route.
[8] Optional. The path to a YAML file that contains the list of conditions, as an alternative to inline
conditions([4]). The path is resolved against the working directory of Confluent Gateway inside the container, so mount the file into the container, for example with avolumesentry indocker-compose.yaml. The file must be readable and contain at least one condition. Confluent Gateway reads the file when it loads the configuration and watches only the main configuration file, so a change to the conditions file takes effect only after the configuration reloads.[9] Optional. The name of the streaming domain that owns every topic that no condition matches. Must be a streaming domain bound to the route. If you omit
default, the route is strict. Confluent Gateway doesn’t show clients a topic that no condition matches, and it rejects requests to create, delete, read, or write that topic.
Every streaming domain that you reference in coordination, conditions,
and default must be one of the streaming domains in the route’s
streamingDomains list.
The following example shows the rules.routing settings of a route:
gateway:
routes:
- name: migration-route
rules:
routing:
coordination:
group: cc
conditions:
- topics: ["payments"]
streamingDomain: cp
- topicPatterns: ["teamA\\..*"]
streamingDomain: cc
default: cp
For an example of a complete route, see the configure step and the reroute step of the migration procedure.
To keep the conditions in a separate file, set conditionsFile to the path of
a YAML file instead of listing conditions. The file contains the list of
conditions, with the same fields as the inline conditions list:
- topics: ["payments"]
streamingDomain: cp
- topicPatterns: ["teamA\\..*"]
streamingDomain: cc
Route filters configuration
Filters allow you to control and manage traffic flow for specific routes in Confluent Gateway. You can apply filters at the route level to enforce policies, block or allow requests, and customize error handling for different scenarios.
Fencing filter
The fencing filter in Confluent Gateway is a route-level filter that allows you to control the traffic flow on a specific route. You can configure fencing in two ways:
fence(deprecated): Blocks or allows all requests on a route. Userules.fencinginstead. For more information, see Fence an entire route.rules.fencing: Blocks or allows traffic by traffic type and topic. You can userules.fencingon static and dynamic routes. For more information, see Fencing rules configuration.
A route can use fence or rules.fencing, but not both.
Fence an entire route
The fence configuration supports two fencing scopes:
ALL: Blocks all requests on the specified route. Useful for scenarios such as maintenance windows or when you want to temporarily disable access to a route.NONE: Allows all requests on the specified route.
gateway:
routes:
- name:
fence:
scope: --- [1]
errorCode: --- [2]
errorMessage: --- [3]
[1] Optional. The fencing scope of the filter. The default value is
ALL, which blocks all requests on the route. Set toNONEto allow all requests on the route. If you add afencesection withoutscope, Confluent Gateway blocks all requests on the route.[2] Optional. The error code to return for blocked requests. The default value is
BROKER_NOT_AVAILABLE.For a list of valid error codes, see Kafka protocol error codes.
[3] Optional. The error message to return for blocked requests. The default value is
This route is currently unavailable - all requests are blocked.
The following is an example configuration for a Confluent Gateway route with the fencing filter enabled:
gateway:
routes:
- name: eu-sales
endpoint: eu-gw.sales.example.com:9092
fence:
scope: ALL
errorCode: BROKER_NOT_AVAILABLE
errorMessage: "Maintenance in progress - route temporarily unavailable"
brokerIdentificationStrategy:
type: host
pattern: broker-$(nodeId).eu-gw.sales.example.com:9092
streamingDomain:
name: sales
bootstrapServerId: SASL_SSL-1
This example shows only the settings that the fencing filter requires. A route
that uses type: host also requires an SSL keystore in its security
settings. For more information, see Configure Security for Confluent Gateway.
Fencing rules configuration
Use the rules.fencing setting to block traffic by traffic type and topic,
instead of blocking the entire route. For example, you can block produce
requests to a set of topics while those topics migrate to another cluster, and
let all other traffic continue. To learn how to use fencing to migrate a topic,
see Migrate topics between clusters.
gateway:
routes:
- name:
rules:
fencing: --- [1]
- trafficType: --- [2]
topics: --- [3]
topicPatterns: --- [4]
blocked: --- [5]
[1] The list of fencing rules. Confluent Gateway evaluates the rules in order, and the first rule that matches a request decides whether to block it. Confluent Gateway doesn’t fence requests that match no rule. Each rule must set at least one of
trafficType([2]),topics([3]), ortopicPatterns([4]). A route can’t use bothrules.fencingandfence.[2] Optional. The traffic type that the rule applies to. Set to
PRODUCEorCONSUME. If you omittrafficType, the rule applies to both types.PRODUCE: Requests that write records.CONSUME: Requests that read records or manage consumer groups and offsets. For the requests that each type covers, see the responses table.
A rule that lists
topicsortopicPatternsdoesn’t fence consumer group membership requests (join, sync, heartbeat, and leave), because they don’t name topics. To fence them, use aCONSUMErule that sets neithertopicsnortopicPatterns. Such a rule blocks all consume traffic on the route, for every topic and consumer group, not only for the topics that you migrate.[3] Optional. A list of exact topic names that the rule applies to.
[4] Optional. A list of Java regular expressions that the rule applies to, with the same syntax as
topicPatternsin routing rules. For more information about pattern syntax, see Routing rules configuration (Early Access).A rule matches a topic if the topic is listed in
topics([3]) or matches any pattern intopicPatterns([4]).[5] Required. Set to
trueto block the traffic that matches the rule, orfalseto allow it. To make an exception to a broadertruerule, list afalserule for those topics before it, because the first matching rule wins.
A rule that sets only trafficType applies to all traffic of that type.
The following example blocks produce requests to the orders topic and to all
topics that start with teamA., except for teamA.audit. The false rule
comes first because Confluent Gateway evaluates the rules in order:
gateway:
routes:
- name: migration-route
rules:
fencing:
- trafficType: PRODUCE
topics: ["teamA.audit"]
blocked: false
- trafficType: PRODUCE
topics: ["orders"]
topicPatterns: ["teamA\\..*"]
blocked: true
When a rule blocks a request, the response depends on the request type. Fencing
returns errors that clients can retry, so most clients retry instead of
failing. Clients can retry these errors, which aligns with Kafka behavior, so
client applications don’t need extra error handling. Unlike
fence, which has an errorCode setting, fencing rules don’t let you
configure the error codes. The following table lists the response that each type
of request receives when a fencing rule blocks it:
Traffic type |
Request |
Response for blocked requests |
|---|---|---|
|
Produce |
|
|
Fetch |
An empty response with no error, so the consumer polls again. |
|
ListOffsets |
|
|
OffsetCommit |
|
|
OffsetForLeaderEpoch |
|
|
JoinGroup, SyncGroup, Heartbeat, LeaveGroup |
|
Client timeouts limit how long a fence can last. A producer stops retrying when
its delivery.timeout.ms expires (120,000 ms by default). If a consumer
can’t send heartbeats before its session.timeout.ms expires, the group
coordinator might remove it from its consumer group. Keep fences as short as
possible.
If a request names more than one topic and only some of them are fenced, Confluent Gateway returns the fencing error, or an empty result for fetch requests, for the fenced topics and processes the rest.
For the requests that Confluent Gateway doesn’t fence, such as OffsetFetch, and the
effect of fencing on producers that use acks=0, see
Limitations.
Administration and metrics configuration
The admin section configures the Confluent Gateway administrative service,
including the bind address, TCP port, metrics endpoint, JVM metrics
collection, and custom metric tags.
gateway:
admin:
bindAddress: --- [1]
port: --- [2]
endpoints:
metrics: --- [3]
jvmMetrics: --- [4]
- JvmGcMetrics
- JvmMemoryMetrics
- JvmThreadMetrics
- ProcessorMetrics
- UptimeMetrics
commonTags: --- [5]
host:
region:
[1] The local address to bind admin service and to listen on for incoming connections. The default value is
0.0.0.0.This address determines which network interfaces the Confluent Gateway uses to expose its administrative endpoints, such as metrics and liveness checks.
[2] The TCP port for exposing admin endpoints. The default value is
9190.The Confluent Gateway serves metrics at
http://{bindAddress}:{port}/metrics. It exposes a liveness check athttp://{bindAddress}:{port}/livez.[3] The metrics endpoints to be enabled and exposed. The default value is
true.[4] Standard JVM metrics captured using Micrometer classes. By default,
JvmGcMetrics,JvmMemoryMetrics,JvmThreadMetrics,ProcessorMetrics, andUptimeMetricsare enabled. If you set this list, it replaces the defaults, so include every metric class you want.[5] Optional. The common tags to be applied to all the metrics.
An example configuration for Confluent Gateway administration and metrics:
admin:
bindAddress: 0.0.0.0
port: 9190
endpoints:
metrics: true
jvmMetrics:
- JvmGcMetrics
- JvmMemoryMetrics
- JvmThreadMetrics
- ProcessorMetrics
- UptimeMetrics
commonTags:
host: pod-0
region: us-west-2
For a recommended set of metrics to monitor and example alerting queries, see Monitor Confluent Gateway Metrics.
Optional: Enterprise license configuration
Enterprise mode enables unlimited routes and requires a valid Confluent Platform Confluent Enterprise license that includes the Confluent Gateway add-on. The default Trial mode, which doesn’t require a key, is limited to a maximum of four routes. For a full comparison of modes, see License modes.
If you’re using Enterprise mode, follow these steps to apply your license key:
Contact Confluent to get a Confluent Enterprise license for Confluent Platform that includes the Confluent Gateway add-on for production use. For more information, see Manage Confluent Platform Licenses.
Using the license key, configure the
GATEWAY_LICENSESenvironment variable by exporting it or defining in thedocker-compose.yaml.Set the environment variable before starting the Confluent Gateway.
export GATEWAY_LICENSES="your-license-key"
To add multiple license keys, use Bash ANSI-C quoting (
$'...') so that the shell expands\ninto a newline between keys.export GATEWAY_LICENSES=$'your-first-license-key\nyour-second-license-key'
Edit
docker-compose.yaml. You can add multiple license keys, one per line.gateway: environment: GATEWAY_LICENSES: | your-first-license-key your-second-license-key
To verify the license status, check the Confluent Gateway logs for license information after starting the Confluent Gateway.
docker compose -f docker-compose.yaml logs gateway | grep -i license
After completing your configuration, save the file as docker-compose.yaml.
Deploy Confluent Gateway using Docker
To deploy Confluent Gateway:
Pull the Confluent Gateway Docker image to ensure you have the correct version and avoid using a stale locally cached image. For available version tags, see confluent-gateway on Docker Hub.
docker pull confluentinc/confluent-gateway:<version_tag>
Start Confluent Gateway using the
docker-compose.yamlconfiguration file you set up in Configure Confluent Gateway using Docker Compose.docker compose -f docker-compose.yaml up -d
Verify that Confluent Gateway is running.
docker psConfluent Gateway starts in the background after the
docker composecommand completes. Confirm the Confluent Gateway container appears in the output.
Next steps
After you deploy Confluent Gateway:
Verify the deployment and resolve any startup or connectivity problems. For diagnostic steps and symptom-based resolutions, see Troubleshoot Confluent Gateway Docker Deployments.
Configure security for the Confluent Gateway. Security configuration covers authentication, SSL/TLS, secret stores, and passwords for client-to-Confluent Gateway and Confluent Gateway-to-Kafka cluster connections.
Reconfigure clients to communicate with the Confluent Gateway endpoint by pointing their
bootstrap.serversto the route endpoint defined in the Confluent Gateway configuration. For migration scenarios between Kafka clusters, see Migrate between Kafka Clusters using Confluent Gateway.