Repository navigation
Expand file tree
/
Copy pathDockerfile.connect
More file actions
204 lines (185 loc) · 12.4 KB
/
Copy pathDockerfile.connect
File metadata and controls
204 lines (185 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
FROM quay.io/strimzi/kafka:1.2.0-kafka-4.3.1 AS base
# ─── Stage 1: Download connector plugins ─────────────────────────────────────
#
# This stage downloads all enterprise connector plugins from Maven Central
# and GitHub. Each plugin is placed in its own directory under /plugins.
#
# Plugin versions are pinned as build args for easy upgrades.
#
FROM eclipse-temurin:21-jre-alpine AS download
ARG DEBEZIUM_VERSION=3.6.2.Final
ARG APICURIO_VERSION=3.3.0
ARG GROOVY_VERSION=5.0.7
ARG AIVEN_JDBC_VERSION=6.10.0
ARG AIVEN_S3_VERSION=3.4.3
RUN apk add --no-cache curl tar
WORKDIR /plugins
# ── Debezium CDC Connectors ──────────────────────────────────────────────────
# Debezium captures row-level changes from database transaction logs (WAL/binlog)
# and streams them as Kafka events. Essential for Change Data Capture pipelines.
# PostgreSQL — primary relational database CDC via logical replication
RUN mkdir -p debezium-postgres && \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/debezium-connector-postgres/${DEBEZIUM_VERSION}/debezium-connector-postgres-${DEBEZIUM_VERSION}-plugin.tar.gz" \
| tar -xz -C debezium-postgres --strip-components=1
# MySQL / MariaDB — binlog-based CDC for legacy OLTP systems
RUN mkdir -p debezium-mysql && \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/debezium-connector-mysql/${DEBEZIUM_VERSION}/debezium-connector-mysql-${DEBEZIUM_VERSION}-plugin.tar.gz" \
| tar -xz -C debezium-mysql --strip-components=1
# MongoDB — oplog/change-stream CDC for document stores
RUN mkdir -p debezium-mongodb && \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/debezium-connector-mongodb/${DEBEZIUM_VERSION}/debezium-connector-mongodb-${DEBEZIUM_VERSION}-plugin.tar.gz" \
| tar -xz -C debezium-mongodb --strip-components=1
# SQL Server — CDC via SQL Server Change Tracking
RUN mkdir -p debezium-sqlserver && \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/debezium-connector-sqlserver/${DEBEZIUM_VERSION}/debezium-connector-sqlserver-${DEBEZIUM_VERSION}-plugin.tar.gz" \
| tar -xz -C debezium-sqlserver --strip-components=1
# JDBC Sink Connector — Write events to relational databases
#
# The plugin archive bundles ojdbc11 (Oracle's driver, binary-only under Oracle's
# free-use terms — free to redistribute, but not open source). It is deleted so
# this image stays entirely open source; see the matching note on aiven-jdbc.
# Drivers for PostgreSQL, MySQL, MariaDB and SQL Server stay.
RUN mkdir -p debezium-jdbc && \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/debezium-connector-jdbc/${DEBEZIUM_VERSION}/debezium-connector-jdbc-${DEBEZIUM_VERSION}-plugin.tar.gz" \
| tar -xz -C debezium-jdbc --strip-components=1 && \
rm -f debezium-jdbc/ojdbc*.jar
# ── Aiven JDBC Source/Sink Connector ─────────────────────────────────────────
# Generic JDBC source (io.aiven.connect.jdbc.JdbcSourceConnector) that polls
# relational tables into Kafka topics, plus a matching sink. Not published to
# Maven Central — Aiven attaches release archives to GitHub releases only
# (plain .tar, not gzipped).
#
# The archive bundles ojdbc8 alongside the open-source drivers. Oracle's JDBC
# driver ships as a binary under the Oracle Free Use Terms — free of charge and
# free to redistribute, but with no source and no OSI licence, so it is the one
# thing that would make this image not open source. It is removed here; Oracle
# is not a supported target for this image. Anyone who needs it can layer the
# driver back in:
#
# FROM ghcr.io/bmscomp/connect:3.6.2
# ARG OJDBC=https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc11/23.26.1.0.0/ojdbc11-23.26.1.0.0.jar
# ADD --chown=1001:1001 ${OJDBC} /opt/kafka/plugins/aiven-jdbc/
#
# The connectors' own Oracle dialect classes are harmless without a driver: they
# are selected from the JDBC URL, so an Oracle URL now fails at connection time
# with "No suitable driver" instead of half-working.
RUN mkdir -p aiven-jdbc && \
curl -sfL "https://github.com/Aiven-Open/jdbc-connector-for-apache-kafka/releases/download/v${AIVEN_JDBC_VERSION}/jdbc-connector-for-apache-kafka-${AIVEN_JDBC_VERSION}.tar" \
| tar -x -C aiven-jdbc --strip-components=1 && \
rm -f aiven-jdbc/ojdbc*.jar
# ── Aiven S3 Sink / Source Connectors ────────────────────────────────────────
# Archive Kafka topics to Amazon S3 and replay S3 objects back into Kafka.
# Apache-2.0 throughout — the connectors themselves, the AWS SDK for Java v2
# they bundle, and the rest of the archive. Confluent's kafka-connect-s3 is
# source-available under the Confluent Community Licence instead: redistribution
# is allowed, but it carries a competing-hosted-service restriction that this
# image would pass on to everyone who pulls it. Same release-archive shape as
# the JDBC connector above: plain .tar, one top-level directory.
#
# Sink and source ship as separate archives that each bundle their own copy of
# the shared commons jars, so they get separate plugin directories. Putting
# them in one directory would leave duplicate classes on the same plugin path.
RUN mkdir -p aiven-s3-sink && \
curl -sfL "https://github.com/Aiven-Open/cloud-storage-connectors-for-apache-kafka/releases/download/v${AIVEN_S3_VERSION}/s3-sink-connector-for-apache-kafka-${AIVEN_S3_VERSION}.tar" \
| tar -x -C aiven-s3-sink --strip-components=1
# The source release archive also ships its dependencies *exploded*: about 34k
# loose .class files and resources sitting next to the jars. Every one of them
# already exists inside a bundled jar — verified entry by entry against the
# 3.4.3 archive, zero unique paths — so they are pure duplication. Dropping them
# takes the plugin directory from ~300 MB to ~65 MB and keeps a second,
# unversioned copy of Avro, Hadoop and the AWS SDK off the plugin classpath.
# Licence and notice texts are kept.
RUN mkdir -p aiven-s3-source && \
curl -sfL "https://github.com/Aiven-Open/cloud-storage-connectors-for-apache-kafka/releases/download/v${AIVEN_S3_VERSION}/s3-source-connector-for-apache-kafka-${AIVEN_S3_VERSION}.tar" \
| tar -x -C aiven-s3-source --strip-components=1 && \
cd aiven-s3-source && \
for entry in *; do \
case "$entry" in \
*.jar|LICENSE*|NOTICE*|licenses|notices) ;; \
*) rm -rf "$entry" ;; \
esac; \
done
# Avro and Parquet in both S3 archives carry CRITICAL CVEs fixed in patch
# releases: CVE-2024-47561 (Avro schema parsing, RCE; sink bundles 1.11.0,
# source 1.11.3) and CVE-2025-30065 (parquet-avro 1.15.0, arbitrary code
# execution). 3.4.3 is Aiven's latest, so each plugin's copies are swapped for
# the newest patch of the same line: Avro 1.11.5, and every parquet-* jar at
# 1.15.2 so the Parquet modules stay in step (1.11.5 and 1.15.2 also fix
# CVE-2025-33042 and CVE-2025-46762). The build fails if an archive stops
# bundling the jar it replaces; that is the cue to drop the override.
ARG AVRO_VERSION=1.11.5
ARG PARQUET_VERSION=1.15.2
RUN for dir in aiven-s3-sink aiven-s3-source; do \
old=$(ls "$dir"/avro-1.11.[0-4].jar) && rm "$old" && \
curl -sfL "https://repo1.maven.org/maven2/org/apache/avro/avro/${AVRO_VERSION}/avro-${AVRO_VERSION}.jar" \
-o "$dir/avro-${AVRO_VERSION}.jar" || exit 1; \
for m in parquet-avro parquet-column parquet-common parquet-encoding \
parquet-format-structures parquet-hadoop parquet-jackson; do \
rm "$dir/$m-1.15.0.jar" && \
curl -sfL "https://repo1.maven.org/maven2/org/apache/parquet/$m/${PARQUET_VERSION}/$m-${PARQUET_VERSION}.jar" \
-o "$dir/$m-${PARQUET_VERSION}.jar" || exit 1; \
done; \
done
# ── Apicurio Schema Registry Integration ─────────────────────────────────────
# Apicurio converters enable schema governance with Avro, JSON Schema, and
# Protobuf serialization. Required when connecting to Apicurio Registry.
#
# Use Apicurio's Connect-converter distribution, not the bare serde jars: it
# ships the converters together with every dependency they import (the Apicurio
# Java SDK, Avro, Protobuf, Jackson, netty). Downloading the four serde jars on
# their own left every import unresolved, so Connect logged a LinkageError per
# converter during the plugin scan and started without any of them — a failure
# invisible to the build. The archive is flat, so no --strip-components.
RUN mkdir -p apicurio-converter && \
curl -sfL "https://repo1.maven.org/maven2/io/apicurio/apicurio-registry-distro-connect-converter/${APICURIO_VERSION}/apicurio-registry-distro-connect-converter-${APICURIO_VERSION}.tar.gz" \
| tar -xz -C apicurio-converter
# Debezium Scripting SMT and Groovy JSR-223 Engine
#
# The scripting archive holds the SMT and nothing else. Alone on its own plugin
# path it cannot resolve the Debezium runtime classes it compiles against
# (io.debezium.config.EnumeratedValue, io.debezium.metadata.ConfigDescriptor,
# ...), so Connect dropped both transformations during the plugin scan and
# started without them. Debezium 3.6 splits that runtime across small modules —
# there is no debezium-core artifact any more — so pull the same four a
# connector plugin directory carries.
RUN mkdir -p debezium-scripting && \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/debezium-scripting/${DEBEZIUM_VERSION}/debezium-scripting-${DEBEZIUM_VERSION}.tar.gz" \
| tar -xz -C debezium-scripting --strip-components=1 && \
for jar in groovy groovy-jsr223 groovy-json; do \
curl -sfL "https://repo1.maven.org/maven2/org/apache/groovy/${jar}/${GROOVY_VERSION}/${jar}-${GROOVY_VERSION}.jar" \
-o "debezium-scripting/${jar}-${GROOVY_VERSION}.jar"; \
done && \
for jar in debezium-api debezium-config debezium-util debezium-connector-common; do \
curl -sfL "https://repo1.maven.org/maven2/io/debezium/${jar}/${DEBEZIUM_VERSION}/${jar}-${DEBEZIUM_VERSION}.jar" \
-o "debezium-scripting/${jar}-${DEBEZIUM_VERSION}.jar"; \
done
# ─── Stage 2: Final production image ─────────────────────────────────────────
FROM base
ARG DEBEZIUM_VERSION=3.6.2.Final
ARG AIVEN_JDBC_VERSION=6.10.0
ARG AIVEN_S3_VERSION=3.4.3
USER root:root
COPY --from=download /plugins/ /opt/kafka/plugins/
# The base image is Strimzi's Kafka image, which also carries the Kafka
# Exporter for the operator's exporter Deployment. That Deployment runs
# Strimzi's own image, never this one, and a Connect worker never starts the
# exporter; its binary is built with Go 1.24.0 (CVE-2025-68121, CRITICAL,
# crypto/tls). Removing it takes the CVE out of the image.
RUN rm -rf /opt/kafka-exporter
USER 1001
# ─── OCI Image Labels (https://github.com/opencontainers/image-spec) ─────────
LABEL org.opencontainers.image.title="connect"
LABEL org.opencontainers.image.description="Kafka Connect image with fully open-source Debezium CDC (PostgreSQL, MySQL, MongoDB, SQL Server), Apicurio Schema Registry (Avro, JSON Schema, Protobuf), Debezium JDBC Sink, Aiven JDBC source/sink, and Aiven S3 sink/source. Built on Strimzi Kafka 4.3.1."
LABEL org.opencontainers.image.source="https://github.com/bmscomp/kates"
LABEL org.opencontainers.image.url="https://github.com/bmscomp/kates/pkgs/container/connect"
LABEL org.opencontainers.image.documentation="https://github.com/bmscomp/kates/blob/main/docs/kafka-connect.md"
LABEL org.opencontainers.image.vendor="bmscomp"
# Every bundled jar is open source, but not all of it is Apache-2.0: the JDBC
# drivers and a few transitive dependencies bring MIT, BSD, LGPL, CDDL/EPL and
# (for MySQL Connector/J) GPLv2-with-FOSS-exception terms. The OCI spec wants the
# licences of the software actually contained in the image, so list them all.
LABEL org.opencontainers.image.licenses="Apache-2.0 AND MIT AND BSD-2-Clause AND BSD-3-Clause AND LGPL-2.1-or-later AND CDDL-1.0 AND CDDL-1.1 AND EPL-2.0 AND (GPL-2.0-only WITH Universal-FOSS-exception-1.0)"
LABEL org.opencontainers.image.base.name="quay.io/strimzi/kafka:1.2.0-kafka-4.3.1"
LABEL io.debezium.version="${DEBEZIUM_VERSION}"
LABEL io.aiven.jdbc.version="${AIVEN_JDBC_VERSION}"
LABEL io.aiven.s3.version="${AIVEN_S3_VERSION}"