diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml
index f2e1e531b..642ce1a33 100644
--- a/.github/workflows/cicd.yml
+++ b/.github/workflows/cicd.yml
@@ -79,6 +79,7 @@ jobs:
{ name: "Testcontainers.Redis", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.Redpanda", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.ServiceBus", runs-on: "ubuntu-22.04" },
+ { name: "Testcontainers.Weaviate", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.WebDriver", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.Xunit", runs-on: "ubuntu-22.04" }
]
diff --git a/Testcontainers.dic b/Testcontainers.dic
index 041996980..df1f16915 100644
--- a/Testcontainers.dic
+++ b/Testcontainers.dic
@@ -34,4 +34,5 @@ testcontainer
testcontainers
tlsverify
toml
-vstest
\ No newline at end of file
+vstest
+weaviate
\ No newline at end of file
diff --git a/Testcontainers.sln b/Testcontainers.sln
index 58609127f..444bdb1c3 100644
--- a/Testcontainers.sln
+++ b/Testcontainers.sln
@@ -97,6 +97,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Redpanda", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ServiceBus", "src\Testcontainers.ServiceBus\Testcontainers.ServiceBus.csproj", "{2E39E532-B81E-4B48-A004-FAE18EDF9E79}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Weaviate", "src\Testcontainers.Weaviate\Testcontainers.Weaviate.csproj", "{68F8600D-24E9-4E03-9E25-5F6EB338EAC1}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver", "src\Testcontainers.WebDriver\Testcontainers.WebDriver.csproj", "{64A87DE5-29B0-4A54-9E74-560484D8C7C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Xunit", "src\Testcontainers.Xunit\Testcontainers.Xunit.csproj", "{380BB29B-F556-404D-B13B-CA250599C565}"
@@ -201,6 +203,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ServiceBus.T
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Tests", "tests\Testcontainers.Tests\Testcontainers.Tests.csproj", "{27CDB869-A150-4593-958F-6F26E5391E7C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Weaviate.Tests", "tests\Testcontainers.Weaviate.Tests\Testcontainers.Weaviate.Tests.csproj", "{DDB41BC8-5826-4D97-9C5F-001151E3FFD6}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Tests", "tests\Testcontainers.WebDriver.Tests\Testcontainers.WebDriver.Tests.csproj", "{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Xunit.Tests", "tests\Testcontainers.Xunit.Tests\Testcontainers.Xunit.Tests.csproj", "{E901DF14-6F05-4FC2-825A-3055FAD33561}"
@@ -382,6 +386,10 @@ Global
{2E39E532-B81E-4B48-A004-FAE18EDF9E79}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E39E532-B81E-4B48-A004-FAE18EDF9E79}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E39E532-B81E-4B48-A004-FAE18EDF9E79}.Release|Any CPU.Build.0 = Release|Any CPU
+ {68F8600D-24E9-4E03-9E25-5F6EB338EAC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {68F8600D-24E9-4E03-9E25-5F6EB338EAC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {68F8600D-24E9-4E03-9E25-5F6EB338EAC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {68F8600D-24E9-4E03-9E25-5F6EB338EAC1}.Release|Any CPU.Build.0 = Release|Any CPU
{64A87DE5-29B0-4A54-9E74-560484D8C7C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64A87DE5-29B0-4A54-9E74-560484D8C7C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64A87DE5-29B0-4A54-9E74-560484D8C7C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -590,6 +598,10 @@ Global
{27CDB869-A150-4593-958F-6F26E5391E7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27CDB869-A150-4593-958F-6F26E5391E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27CDB869-A150-4593-958F-6F26E5391E7C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DDB41BC8-5826-4D97-9C5F-001151E3FFD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DDB41BC8-5826-4D97-9C5F-001151E3FFD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DDB41BC8-5826-4D97-9C5F-001151E3FFD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DDB41BC8-5826-4D97-9C5F-001151E3FFD6}.Release|Any CPU.Build.0 = Release|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -642,6 +654,7 @@ Global
{BFDA179A-40EB-4CEB-B8E9-0DF32C65E2C5} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{45D6F69C-4D87-4130-AA90-0DB2F7460DAE} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{2E39E532-B81E-4B48-A004-FAE18EDF9E79} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
+ {68F8600D-24E9-4E03-9E25-5F6EB338EAC1} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{64A87DE5-29B0-4A54-9E74-560484D8C7C0} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{380BB29B-F556-404D-B13B-CA250599C565} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{84911C93-C2A9-46E9-AE5E-D567306589E5} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
@@ -694,6 +707,7 @@ Global
{9E8E6AA5-65D1-498F-BEAB-BA34723A0050} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{232DD918-46ED-4BA8-B383-1A9146D83064} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {DDB41BC8-5826-4D97-9C5F-001151E3FFD6} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{E901DF14-6F05-4FC2-825A-3055FAD33561} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
EndGlobalSection
diff --git a/Testcontainers.sln.DotSettings b/Testcontainers.sln.DotSettings
index c9af9ff53..ff93162f2 100644
--- a/Testcontainers.sln.DotSettings
+++ b/Testcontainers.sln.DotSettings
@@ -6,9 +6,9 @@
BlockScoped
True
True
- True
True
True
+ True
True
True
True
@@ -42,10 +42,11 @@
True
True
True
- True
+ True
True
- DO_NOT_SHOW
- DO_NOT_SHOW
- DO_NOT_SHOW
+ True
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
DO_NOT_SHOW
diff --git a/src/Testcontainers.Weaviate/.editorconfig b/src/Testcontainers.Weaviate/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/src/Testcontainers.Weaviate/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/src/Testcontainers.Weaviate/Testcontainers.Weaviate.csproj b/src/Testcontainers.Weaviate/Testcontainers.Weaviate.csproj
new file mode 100644
index 000000000..9a25b9c4d
--- /dev/null
+++ b/src/Testcontainers.Weaviate/Testcontainers.Weaviate.csproj
@@ -0,0 +1,12 @@
+
+
+ net8.0;net9.0;netstandard2.0;netstandard2.1
+ latest
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Testcontainers.Weaviate/Usings.cs b/src/Testcontainers.Weaviate/Usings.cs
new file mode 100644
index 000000000..79fd3af9b
--- /dev/null
+++ b/src/Testcontainers.Weaviate/Usings.cs
@@ -0,0 +1,6 @@
+global using System;
+global using Docker.DotNet.Models;
+global using DotNet.Testcontainers.Builders;
+global using DotNet.Testcontainers.Configurations;
+global using DotNet.Testcontainers.Containers;
+global using JetBrains.Annotations;
\ No newline at end of file
diff --git a/src/Testcontainers.Weaviate/WeaviateBuilder.cs b/src/Testcontainers.Weaviate/WeaviateBuilder.cs
new file mode 100644
index 000000000..92d56dcaa
--- /dev/null
+++ b/src/Testcontainers.Weaviate/WeaviateBuilder.cs
@@ -0,0 +1,61 @@
+namespace Testcontainers.Weaviate;
+
+///
+[PublicAPI]
+public sealed class WeaviateBuilder : ContainerBuilder
+{
+ public const string WeaviateImage = "semitechnologies/weaviate:1.26.14";
+
+ public const ushort WeaviateHttpPort = 8080;
+
+ public const ushort WeaviateGrpcPort = 50051;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public WeaviateBuilder() : this(new WeaviateConfiguration())
+ => DockerResourceConfiguration = Init().DockerResourceConfiguration;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ private WeaviateBuilder(WeaviateConfiguration resourceConfiguration) : base(resourceConfiguration)
+ => DockerResourceConfiguration = resourceConfiguration;
+
+ ///
+ protected override WeaviateConfiguration DockerResourceConfiguration { get; }
+
+ ///
+ public override WeaviateContainer Build()
+ {
+ Validate();
+ return new WeaviateContainer(DockerResourceConfiguration);
+ }
+
+ ///
+ protected override WeaviateBuilder Init()
+ => base.Init()
+ .WithImage(WeaviateImage)
+ .WithPortBinding(WeaviateHttpPort, true)
+ .WithPortBinding(WeaviateGrpcPort, true)
+ .WithEnvironment("AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED", "true")
+ .WithEnvironment("PERSISTENCE_DATA_PATH", "/var/lib/weaviate")
+ .WithWaitStrategy(Wait.ForUnixContainer()
+ .UntilPortIsAvailable(WeaviateHttpPort)
+ .UntilPortIsAvailable(WeaviateGrpcPort)
+ .UntilHttpRequestIsSucceeded(request =>
+ request.ForPath("/v1/.well-known/ready").ForPort(WeaviateHttpPort)));
+
+ ///
+ protected override WeaviateBuilder Clone(IResourceConfiguration resourceConfiguration)
+ => Merge(DockerResourceConfiguration, new WeaviateConfiguration(resourceConfiguration));
+
+ ///
+ protected override WeaviateBuilder Clone(IContainerConfiguration resourceConfiguration)
+ => Merge(DockerResourceConfiguration, new WeaviateConfiguration(resourceConfiguration));
+
+ ///
+ protected override WeaviateBuilder Merge(WeaviateConfiguration oldValue, WeaviateConfiguration newValue)
+ => new(new WeaviateConfiguration(oldValue, newValue));
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Weaviate/WeaviateConfiguration.cs b/src/Testcontainers.Weaviate/WeaviateConfiguration.cs
new file mode 100644
index 000000000..87d42c016
--- /dev/null
+++ b/src/Testcontainers.Weaviate/WeaviateConfiguration.cs
@@ -0,0 +1,53 @@
+namespace Testcontainers.Weaviate;
+
+///
+[PublicAPI]
+public sealed class WeaviateConfiguration : ContainerConfiguration
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public WeaviateConfiguration()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public WeaviateConfiguration(IResourceConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public WeaviateConfiguration(IContainerConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public WeaviateConfiguration(WeaviateConfiguration resourceConfiguration)
+ : this(new WeaviateConfiguration(), resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old Docker resource configuration.
+ /// The new Docker resource configuration.
+ public WeaviateConfiguration(WeaviateConfiguration oldValue, WeaviateConfiguration newValue)
+ : base(oldValue, newValue)
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Weaviate/WeaviateContainer.cs b/src/Testcontainers.Weaviate/WeaviateContainer.cs
new file mode 100644
index 000000000..6eba03c0d
--- /dev/null
+++ b/src/Testcontainers.Weaviate/WeaviateContainer.cs
@@ -0,0 +1,15 @@
+namespace Testcontainers.Weaviate;
+
+///
+[PublicAPI]
+public sealed class WeaviateContainer(WeaviateConfiguration configuration) : DockerContainer(configuration)
+{
+ ///
+ /// Gets the Weaviate base address.
+ ///
+ /// The Weaviate base address.
+ public string GetBaseAddress()
+ {
+ return new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(WeaviateBuilder.WeaviateHttpPort)).ToString();
+ }
+}
\ No newline at end of file
diff --git a/tests/Testcontainers.Weaviate.Tests/.editorconfig b/tests/Testcontainers.Weaviate.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Weaviate.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Weaviate.Tests/Testcontainers.Weaviate.Tests.csproj b/tests/Testcontainers.Weaviate.Tests/Testcontainers.Weaviate.Tests.csproj
new file mode 100644
index 000000000..3d19526bb
--- /dev/null
+++ b/tests/Testcontainers.Weaviate.Tests/Testcontainers.Weaviate.Tests.csproj
@@ -0,0 +1,17 @@
+
+
+ net9.0
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Weaviate.Tests/Usings.cs b/tests/Testcontainers.Weaviate.Tests/Usings.cs
new file mode 100644
index 000000000..dc15b5753
--- /dev/null
+++ b/tests/Testcontainers.Weaviate.Tests/Usings.cs
@@ -0,0 +1,6 @@
+global using System;
+global using System.Net;
+global using System.Net.Http;
+global using System.Threading.Tasks;
+global using DotNet.Testcontainers.Commons;
+global using Xunit;
\ No newline at end of file
diff --git a/tests/Testcontainers.Weaviate.Tests/WeaviateContainerTest.cs b/tests/Testcontainers.Weaviate.Tests/WeaviateContainerTest.cs
new file mode 100644
index 000000000..76b96a50f
--- /dev/null
+++ b/tests/Testcontainers.Weaviate.Tests/WeaviateContainerTest.cs
@@ -0,0 +1,26 @@
+namespace Testcontainers.Weaviate;
+
+public sealed class WeaviateContainerTest : IAsyncLifetime
+{
+ private readonly WeaviateContainer _weaviateContainer = new WeaviateBuilder().Build();
+
+ public Task InitializeAsync() => _weaviateContainer.StartAsync();
+
+ public Task DisposeAsync() => _weaviateContainer.DisposeAsync().AsTask();
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task GetSchemaReturnsHttpStatusCodeOk()
+ {
+ // Given
+ using var httpClient = new HttpClient();
+ httpClient.BaseAddress = new Uri(_weaviateContainer.GetBaseAddress());
+
+ // When
+ using var httpResponse = await httpClient.GetAsync("v1/schema")
+ .ConfigureAwait(true);
+
+ // Then
+ Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode);
+ }
+}
\ No newline at end of file