diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index ab1de00f6f8..033fd19c49d 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -20,6 +20,7 @@ body:
- CockroachDB
- Consul
- Couchbase
+ - CrateDB
- DB2
- Dynalite
- Elasticsearch
diff --git a/.github/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/enhancement.yaml
index b80fa9387da..b9d67bc7d52 100644
--- a/.github/ISSUE_TEMPLATE/enhancement.yaml
+++ b/.github/ISSUE_TEMPLATE/enhancement.yaml
@@ -20,6 +20,7 @@ body:
- CockroachDB
- Consul
- Couchbase
+ - CrateDB
- DB2
- Dynalite
- Elasticsearch
diff --git a/.github/ISSUE_TEMPLATE/feature.yaml b/.github/ISSUE_TEMPLATE/feature.yaml
index 024d0414d2f..ffc1b19a6cb 100644
--- a/.github/ISSUE_TEMPLATE/feature.yaml
+++ b/.github/ISSUE_TEMPLATE/feature.yaml
@@ -18,6 +18,7 @@ body:
- Cassandra
- Clickhouse
- CockroachDB
+ - CrateDB
- Consul
- Couchbase
- DB2
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index ecf473b2d65..e78603d163f 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -62,6 +62,11 @@ updates:
schedule:
interval: "monthly"
open-pull-requests-limit: 10
+ - package-ecosystem: "gradle"
+ directory: "/modules/cratedb"
+ schedule:
+ interval: "monthly"
+ open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/database-commons"
schedule:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 55163e0d7c7..48238471563 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -19,6 +19,8 @@
- modules/consul/**/*
"modules/couchbase":
- modules/couchbase/**/*
+"modules/cratedb":
+ - modules/cratedb/**/*
"modules/db2":
- modules/db2/**/*
"modules/dynalite":
diff --git a/.github/settings.yml b/.github/settings.yml
index 7844182893b..7cc83a69524 100644
--- a/.github/settings.yml
+++ b/.github/settings.yml
@@ -124,6 +124,9 @@ labels:
- name: modules/couchbase
color: '#006b75'
+ - name: modules/cratedb
+ color: '#006b75'
+
- name: modules/db2
color: '#006b75'
diff --git a/docs/modules/databases/cratedb.md b/docs/modules/databases/cratedb.md
new file mode 100644
index 00000000000..74ec23dda00
--- /dev/null
+++ b/docs/modules/databases/cratedb.md
@@ -0,0 +1,25 @@
+# CrateDB Module
+
+See [Database containers](./index.md) for documentation and usage that is common to all relational database container types.
+
+## Adding this module to your project dependencies
+
+Add the following dependency to your `pom.xml`/`build.gradle` file:
+
+=== "Gradle"
+ ```groovy
+ testImplementation "org.testcontainers:cratedb:{{latest_version}}"
+ ```
+=== "Maven"
+ ```xml
+
+ org.testcontainers
+ cratedb
+ {{latest_version}}
+ test
+
+ ```
+
+!!! hint
+ Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency.
+
diff --git a/docs/modules/databases/jdbc.md b/docs/modules/databases/jdbc.md
index 6cf4977ad96..020a96ff941 100644
--- a/docs/modules/databases/jdbc.md
+++ b/docs/modules/databases/jdbc.md
@@ -51,6 +51,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database
`jdbc:tc:cockroach:v21.2.3:///databasename`
+#### Using CrateDB
+
+`jdbc:tc:cratedb:5.2.3//localhost:5432/crate`
+
#### Using TiDB
`jdbc:tc:tidb:v6.1.0:///databasename`
diff --git a/mkdocs.yml b/mkdocs.yml
index 8da6fa584ac..72c457b9d5f 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -53,6 +53,7 @@ nav:
- modules/databases/cockroachdb.md
- modules/databases/couchbase.md
- modules/databases/clickhouse.md
+ - modules/databases/cratedb.md
- modules/databases/db2.md
- modules/databases/dynalite.md
- modules/databases/influxdb.md
diff --git a/modules/cratedb/build.gradle b/modules/cratedb/build.gradle
new file mode 100644
index 00000000000..d53031542f5
--- /dev/null
+++ b/modules/cratedb/build.gradle
@@ -0,0 +1,13 @@
+description = "Testcontainers :: JDBC :: CrateDB"
+
+dependencies {
+ annotationProcessor 'com.google.auto.service:auto-service:1.0.1'
+ compileOnly 'com.google.auto.service:auto-service:1.0.1'
+
+ api project(':jdbc')
+
+ testImplementation project(':jdbc-test')
+ testImplementation 'org.postgresql:postgresql:42.5.4'
+
+ compileOnly 'org.jetbrains:annotations:24.0.0'
+}
diff --git a/modules/cratedb/src/main/java/org/testcontainers/cratedb/CrateDBContainer.java b/modules/cratedb/src/main/java/org/testcontainers/cratedb/CrateDBContainer.java
new file mode 100644
index 00000000000..45cd03f460a
--- /dev/null
+++ b/modules/cratedb/src/main/java/org/testcontainers/cratedb/CrateDBContainer.java
@@ -0,0 +1,116 @@
+package org.testcontainers.cratedb;
+
+import org.jetbrains.annotations.NotNull;
+import org.testcontainers.containers.JdbcDatabaseContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+
+import java.util.Set;
+
+public class CrateDBContainer extends JdbcDatabaseContainer {
+
+ static final String NAME = "cratedb";
+
+ static final String IMAGE = "crate";
+
+ static final String DEFAULT_TAG = "5.2.5";
+
+ private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("crate");
+
+ static final Integer CRATEDB_PG_PORT = 5432;
+
+ static final Integer CRATEDB_HTTP_PORT = 4200;
+
+ private String databaseName = "crate";
+
+ private String username = "crate";
+
+ private String password = "crate";
+
+ public CrateDBContainer(final String dockerImageName) {
+ this(DockerImageName.parse(dockerImageName));
+ }
+
+ public CrateDBContainer(final DockerImageName dockerImageName) {
+ super(dockerImageName);
+ dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
+
+ this.waitStrategy = Wait.forHttp("/").forPort(CRATEDB_HTTP_PORT).forStatusCode(200);
+
+ addExposedPort(CRATEDB_PG_PORT);
+ addExposedPort(CRATEDB_HTTP_PORT);
+ }
+
+ /**
+ * @return the ports on which to check if the container is ready
+ * @deprecated use {@link #getLivenessCheckPortNumbers()} instead
+ */
+ @NotNull
+ @Override
+ @Deprecated
+ protected Set getLivenessCheckPorts() {
+ return super.getLivenessCheckPorts();
+ }
+
+ @Override
+ public String getDriverClassName() {
+ return "org.postgresql.Driver";
+ }
+
+ @Override
+ public String getJdbcUrl() {
+ String additionalUrlParams = constructUrlParameters("?", "&");
+ return (
+ "jdbc:postgresql://" +
+ getHost() +
+ ":" +
+ getMappedPort(CRATEDB_PG_PORT) +
+ "/" +
+ databaseName +
+ additionalUrlParams
+ );
+ }
+
+ @Override
+ public String getDatabaseName() {
+ return databaseName;
+ }
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public String getTestQueryString() {
+ return "SELECT 1";
+ }
+
+ @Override
+ public CrateDBContainer withDatabaseName(final String databaseName) {
+ this.databaseName = databaseName;
+ return self();
+ }
+
+ @Override
+ public CrateDBContainer withUsername(final String username) {
+ this.username = username;
+ return self();
+ }
+
+ @Override
+ public CrateDBContainer withPassword(final String password) {
+ this.password = password;
+ return self();
+ }
+
+ @Override
+ protected void waitUntilContainerStarted() {
+ getWaitStrategy().waitUntilReady(this);
+ }
+}
diff --git a/modules/cratedb/src/main/java/org/testcontainers/cratedb/CrateDBContainerProvider.java b/modules/cratedb/src/main/java/org/testcontainers/cratedb/CrateDBContainerProvider.java
new file mode 100644
index 00000000000..0bf80f051ec
--- /dev/null
+++ b/modules/cratedb/src/main/java/org/testcontainers/cratedb/CrateDBContainerProvider.java
@@ -0,0 +1,36 @@
+package org.testcontainers.cratedb;
+
+import org.testcontainers.containers.JdbcDatabaseContainer;
+import org.testcontainers.containers.JdbcDatabaseContainerProvider;
+import org.testcontainers.jdbc.ConnectionUrl;
+import org.testcontainers.utility.DockerImageName;
+
+/**
+ * Factory for CrateDB containers using PostgreSQL JDBC driver.
+ */
+public class CrateDBContainerProvider extends JdbcDatabaseContainerProvider {
+
+ public static final String USER_PARAM = "user";
+
+ public static final String PASSWORD_PARAM = "password";
+
+ @Override
+ public boolean supports(String databaseType) {
+ return databaseType.equals(CrateDBContainer.NAME);
+ }
+
+ @Override
+ public JdbcDatabaseContainer newInstance() {
+ return newInstance(CrateDBContainer.DEFAULT_TAG);
+ }
+
+ @Override
+ public JdbcDatabaseContainer newInstance(String tag) {
+ return new CrateDBContainer(DockerImageName.parse(CrateDBContainer.IMAGE).withTag(tag));
+ }
+
+ @Override
+ public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) {
+ return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM);
+ }
+}
diff --git a/modules/cratedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider b/modules/cratedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider
new file mode 100644
index 00000000000..ddd58ec8794
--- /dev/null
+++ b/modules/cratedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider
@@ -0,0 +1 @@
+org.testcontainers.cratedb.CrateDBContainerProvider
diff --git a/modules/cratedb/src/test/java/org/testcontainers/CrateDBTestImages.java b/modules/cratedb/src/test/java/org/testcontainers/CrateDBTestImages.java
new file mode 100644
index 00000000000..5025d409839
--- /dev/null
+++ b/modules/cratedb/src/test/java/org/testcontainers/CrateDBTestImages.java
@@ -0,0 +1,7 @@
+package org.testcontainers;
+
+import org.testcontainers.utility.DockerImageName;
+
+public interface CrateDBTestImages {
+ DockerImageName CRATEDB_TEST_IMAGE = DockerImageName.parse("crate:5.2.5");
+}
diff --git a/modules/cratedb/src/test/java/org/testcontainers/jdbc/cratedb/CrateDBJDBCDriverTest.java b/modules/cratedb/src/test/java/org/testcontainers/jdbc/cratedb/CrateDBJDBCDriverTest.java
new file mode 100644
index 00000000000..54ef9704ac5
--- /dev/null
+++ b/modules/cratedb/src/test/java/org/testcontainers/jdbc/cratedb/CrateDBJDBCDriverTest.java
@@ -0,0 +1,21 @@
+package org.testcontainers.jdbc.cratedb;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.testcontainers.jdbc.AbstractJDBCDriverTest;
+
+import java.util.Arrays;
+import java.util.EnumSet;
+
+@RunWith(Parameterized.class)
+public class CrateDBJDBCDriverTest extends AbstractJDBCDriverTest {
+
+ @Parameterized.Parameters(name = "{index} - {0}")
+ public static Iterable