diff --git a/docs/api/connection_string_provider.md b/docs/api/connection_string_provider.md index fbb30b6d3..785507fde 100644 --- a/docs/api/connection_string_provider.md +++ b/docs/api/connection_string_provider.md @@ -11,7 +11,7 @@ The Connection String Provider API provides a standardized way to access and man Register a custom connection string provider via the container builder: ```csharp -IContainer container = new ContainerBuilder() +IContainer container = new ContainerBuilder("alpine:3.20.0") .WithConnectionStringProvider(new MyProvider1()) .Build(); diff --git a/docs/api/create_docker_container.md b/docs/api/create_docker_container.md index 496547dd4..96a80811a 100644 --- a/docs/api/create_docker_container.md +++ b/docs/api/create_docker_container.md @@ -33,7 +33,7 @@ Both `ENTRYPOINT` and `CMD` allows you to configure an executable and parameters Instead of running the NGINX application, the following container configuration overrides the default start procedure of the image and just tests the NGINX configuration file. ```csharp -_ = new ContainerBuilder() +_ = new ContainerBuilder("nginx:1.26.3-alpine3.20") .WithEntrypoint("nginx") .WithCommand("-t"); ``` @@ -49,7 +49,7 @@ Apps or services running inside a container are usually configured either with e To configure an ASP.NET Core application, either one or both mechanisms can be used. ```csharp -_ = new ContainerBuilder() +_ = new ContainerBuilder("mcr.microsoft.com/dotnet/aspnet:10.0") .WithEnvironment("ASPNETCORE_URLS", "https://+") .WithEnvironment("ASPNETCORE_Kestrel__Certificates__Default__Path", "/app/certificate.pfx") .WithEnvironment("ASPNETCORE_Kestrel__Certificates__Default__Password", "password") @@ -63,12 +63,12 @@ _ = new ContainerBuilder() Sometimes it is necessary to copy files into the container to configure the services running inside the container in advance, like the `appsettings.json` or an SSL certificate. The container builder API provides a member `WithResourceMapping(string, string)`, including several overloads to copy directories or individual files to a container's directory. ```csharp title="Copying a directory" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithResourceMapping(new DirectoryInfo("."), "/app/"); ``` ```csharp title="Copying a file" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") // Copy 'appsettings.json' into the '/app' directory. .WithResourceMapping(new FileInfo("appsettings.json"), "/app/") // Copy 'appsettings.Container.json' to '/app/appsettings.Developer.json'. @@ -78,7 +78,7 @@ _ = new ContainerBuilder() Another overloaded member of the container builder API allows you to copy the contents of a byte array to a specific file path within the container. This can be useful when you already have the file content stored in memory or when you need to dynamically generate the file content before copying it. ```csharp title="Copying a byte array" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithResourceMapping(Encoding.Default.GetBytes("{}"), "/app/appsettings.json"); ``` @@ -87,7 +87,7 @@ _ = new ContainerBuilder() When copying files into a container, you can specify the user ID (UID) and group ID (GID) to set the correct ownership of the copied files. This is particularly useful when the container runs as a non-root user or when specific file permissions are required for security or application functionality. ```csharp title="Copying a file with specific UID and GID" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithResourceMapping(new DirectoryInfo("."), "/app/", uid: 1000, gid: 1000); ``` @@ -96,7 +96,7 @@ _ = new ContainerBuilder() When copying files into a container, you can specify the file mode to set the correct permissions for the copied files. ```csharp title="Copying a script with executable permissions" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithResourceMapping(new DirectoryInfo("."), "/app/", fileMode: Unix.FileMode755); ``` @@ -144,7 +144,7 @@ The `WithOutputConsumer` method is part of the `ContainerBuilder` class and is u ```csharp title="Forwarding all log messages" using IOutputConsumer outputConsumer = Consume.RedirectStdoutAndStderrToConsole(); -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithOutputConsumer(outputConsumer); ``` @@ -170,7 +170,7 @@ If a module applies default commands and you need to override or remove them ent // .WithCommand("-c", "synchronous_commit=off") // ... -var postgreSqlContainer = new PostgreSqlBuilder() +var postgreSqlContainer = new PostgreSqlBuilder("postgres:15.1") .WithCommand(new OverwriteEnumerable(Array.Empty())) .Build(); ``` @@ -188,9 +188,8 @@ An NGINX container that binds the HTTP port to a random host port and hosts stat ```csharp const ushort HttpPort = 80; -var nginxContainer = new ContainerBuilder() +var nginxContainer = new ContainerBuilder("nginx:1.26.3-alpine3.20") .WithName(Guid.NewGuid().ToString("D")) - .WithImage("nginx") .WithPortBinding(HttpPort, true) .Build(); @@ -213,9 +212,8 @@ const string MagicNumber = "42"; const ushort MagicNumberPort = 80; -var deepThoughtContainer = new ContainerBuilder() +var deepThoughtContainer = new ContainerBuilder("alpine:3.20.0") .WithName(Guid.NewGuid().ToString("D")) - .WithImage("alpine") .WithPortBinding(MagicNumberPort, true) .WithEnvironment("MAGIC_NUMBER", MagicNumber) .WithEntrypoint("/bin/sh", "-c") diff --git a/docs/api/create_docker_network.md b/docs/api/create_docker_network.md index 45fc0b0af..0b3d85faf 100644 --- a/docs/api/create_docker_network.md +++ b/docs/api/create_docker_network.md @@ -29,9 +29,8 @@ var network = new NetworkBuilder() .WithName(Guid.NewGuid().ToString("D")) .Build(); -var deepThoughtContainer = new ContainerBuilder() +var deepThoughtContainer = new ContainerBuilder("alpine:3.20.0") .WithName(Guid.NewGuid().ToString("D")) - .WithImage("alpine") .WithEnvironment("MAGIC_NUMBER", MagicNumber) .WithEntrypoint("/bin/sh", "-c") .WithCommand($"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p {MagicNumberPort}; done") @@ -39,9 +38,8 @@ var deepThoughtContainer = new ContainerBuilder() .WithNetworkAliases(MagicNumberHost) .Build(); -var ultimateQuestionContainer = new ContainerBuilder() +var ultimateQuestionContainer = new ContainerBuilder("alpine:3.20.0") .WithName(Guid.NewGuid().ToString("D")) - .WithImage("alpine") .WithEntrypoint("top") .WithNetwork(network) .Build(); diff --git a/docs/api/low_level_api_access.md b/docs/api/low_level_api_access.md index 12f67ff74..3c12f205a 100644 --- a/docs/api/low_level_api_access.md +++ b/docs/api/low_level_api_access.md @@ -4,6 +4,6 @@ Testcontainers does not expose all available [Docker Engine APIs](https://docs.d ```csharp title="Setting the memory limit to 2GB" const long TwoGB = 2L * 1024 * 1024 * 1024; -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithCreateParameterModifier(parameterModifier => parameterModifier.HostConfig.Memory = TwoGB); ``` diff --git a/docs/api/resource_reaper.md b/docs/api/resource_reaper.md index 6c9c232ad..369abf4b6 100644 --- a/docs/api/resource_reaper.md +++ b/docs/api/resource_reaper.md @@ -16,8 +16,7 @@ Creates a scoped Resource Reaper and assigns its session id to a container (Dock var resourceReaper = await ResourceReaper.GetAndStartNewAsync() .ConfigureAwait(false); -await new ContainerBuilder() - .WithImage("alpine") +await new ContainerBuilder("alpine:3.20.0") .WithResourceReaperSessionId(resourceReaper.SessionId) .Build() .StartAsync() diff --git a/docs/api/resource_reuse.md b/docs/api/resource_reuse.md index 2165add78..999f31b5b 100644 --- a/docs/api/resource_reuse.md +++ b/docs/api/resource_reuse.md @@ -3,14 +3,14 @@ Reuse is an experimental feature designed to simplify and enhance the development experience. Instead of disposing resources after the tests are finished, enabling reuse will retain the resources and reuse them in the next test run. Testcontainers assigns a hash value according to the builder configuration. If it identifies a matching resource, it will reuse this resource instead of creating a new one. Enabling reuse will disable the resource reaper, meaning the resource will not be cleaned up. ```csharp title="Enable container reuse" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithReuse(true); ``` The reuse implementation does currently not consider (support) all builder APIs when calculating the hash value. Therefore, collisions may occur. To prevent collisions, simply use a distinct label to identify the resource. ```csharp title="Label container resource to identify it" -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithReuse(true) .WithLabel("reuse-id", "WeatherForecast"); ``` diff --git a/docs/api/wait_strategies.md b/docs/api/wait_strategies.md index 6a4365c12..3c2a8de95 100644 --- a/docs/api/wait_strategies.md +++ b/docs/api/wait_strategies.md @@ -103,7 +103,7 @@ HEALTHCHECK --interval=1s CMD test -e /healthcheck You can leverage the container's health status as your wait strategy to report readiness of your application or service: ```csharp -_ = new ContainerBuilder() +_ = new ContainerBuilder("alpine:3.20.0") .WithWaitStrategy(Wait.ForUnixContainer().UntilContainerIsHealthy()); ``` diff --git a/docs/examples/aspnet.md b/docs/examples/aspnet.md index 95959f485..42019a8ff 100644 --- a/docs/examples/aspnet.md +++ b/docs/examples/aspnet.md @@ -59,7 +59,7 @@ private sealed class RedisConfigurationProvider : ConfigurationProvider public async Task LoadAsync() { - var redisContainer = new RedisBuilder().Build(); + var redisContainer = new RedisBuilder("redis:7.0").Build(); await redisContainer.StartAsync() .ConfigureAwait(false); @@ -93,13 +93,12 @@ const string connectionString = $"server={weatherForecastStorage};user id={MsSql _weatherForecastNetwork = new NetworkBuilder() .Build(); -_msSqlContainer = new MsSqlBuilder() +_msSqlContainer = new MsSqlBuilder("mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04") .WithNetwork(_weatherForecastNetwork) .WithNetworkAliases(weatherForecastStorage) .Build(); -_weatherForecastContainer = new ContainerBuilder() - .WithImage(Image) +_weatherForecastContainer = new ContainerBuilder(Image) .WithNetwork(_weatherForecastNetwork) .WithPortBinding(WeatherForecastImage.HttpsPort, true) .WithEnvironment("ASPNETCORE_URLS", "https://+") diff --git a/docs/index.md b/docs/index.md index 42a860a43..3c65f0b14 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,9 +6,7 @@ dotnet add package Testcontainers ```csharp title="Run the Hello World container" // Create a new instance of a container. -var container = new ContainerBuilder() - // Set the image for the container to "testcontainers/helloworld:1.3.0". - .WithImage("testcontainers/helloworld:1.3.0") +var container = new ContainerBuilder("testcontainers/helloworld:1.3.0") // Bind port 8080 of the container to a random port on the host. .WithPortBinding(8080, true) // Wait until the HTTP endpoint of the container is available. diff --git a/docs/modules/cassandra.md b/docs/modules/cassandra.md index e2a72c55b..81d4a0089 100644 --- a/docs/modules/cassandra.md +++ b/docs/modules/cassandra.md @@ -12,7 +12,7 @@ You can start an Apache Cassandra container instance from any .NET application. === "Start a Cassandra container" ```csharp - var cassandraContainer = new CassandraBuilder().Build(); + var cassandraContainer = new CassandraBuilder("cassandra:5.0").Build(); await cassandraContainer.StartAsync(); ``` diff --git a/docs/modules/db2.md b/docs/modules/db2.md index e5eddb59d..ee2b34c00 100644 --- a/docs/modules/db2.md +++ b/docs/modules/db2.md @@ -16,7 +16,7 @@ You can start a Db2 container instance from any .NET application. To create and === "Start a Db2 container" ```csharp - var db2Container = new Db2Builder().Build(); + var db2Container = new Db2Builder("icr.io/db2_community/db2:12.1.0.0").Build(); await db2Container.StartAsync(); ``` diff --git a/docs/modules/grafana.md b/docs/modules/grafana.md index 89199c1d0..76fb338ba 100644 --- a/docs/modules/grafana.md +++ b/docs/modules/grafana.md @@ -40,5 +40,5 @@ To execute the tests, use the command `dotnet test` from a terminal. Developers can enable anonymous access using the Grafana builder API `WithAnonymousAccessEnabled()`. This will enable anonymous access and no authentication is necessary to access Grafana: ```csharp -GrafanaContainer _grafanaContainer = new GrafanaBuilder().WithAnonymousAccessEnabled().Build(); +GrafanaContainer _grafanaContainer = new GrafanaBuilder("grafana/grafana:12.2").WithAnonymousAccessEnabled().Build(); ``` \ No newline at end of file diff --git a/docs/modules/index.md b/docs/modules/index.md index d3e7dbffe..b20d06f27 100644 --- a/docs/modules/index.md +++ b/docs/modules/index.md @@ -11,7 +11,7 @@ dotnet add package Testcontainers.ModuleName All modules follow the same design and come pre-configured with best practices. Usually, you do not need to worry about configuring them yourself. To create and start a container, all you need is: ```csharp -var moduleNameContainer = new ModuleNameBuilder().Build(); +var moduleNameContainer = new ModuleNameBuilder(":").Build(); await moduleNameContainer.StartAsync(); ``` @@ -115,10 +115,15 @@ To set the PostgreSQL module default configuration, override the read-only `Dock The .NET template already includes this configuration, making it easy for developers to quickly get started by simply commenting out the necessary parts: ```csharp -public PostgreSqlBuilder() +public PostgreSqlBuilder(string image) + : this(new DockerImage(image)) +{ +} + +public PostgreSqlBuilder(IImage image) : this(new PostgreSqlConfiguration()) { - DockerResourceConfiguration = Init().DockerResourceConfiguration; + DockerResourceConfiguration = Init().WithImage(image).DockerResourceConfiguration; } private PostgreSqlBuilder(PostgreSqlConfiguration resourceConfiguration) @@ -130,13 +135,13 @@ private PostgreSqlBuilder(PostgreSqlConfiguration resourceConfiguration) protected override PostgreSqlConfiguration DockerResourceConfiguration { get; } ``` -To append the PostgreSQL configurations to the default Testcontainers configurations override or comment out the `Init()` member and add the necessary configurations such as the Docker image and a wait strategy to the base implementation: +To append the PostgreSQL configurations to the default Testcontainers configurations override or comment out the `Init()` member and add the necessary configurations and a wait strategy to the base implementation: ```csharp protected override PostgreSqlBuilder Init() { var waitStrategy = Wait.ForUnixContainer().UntilCommandIsCompleted("pg_isready"); - return base.Init().WithImage("postgres:15.1").WithPortBinding(5432, true).WithWaitStrategy(waitStrategy); + return base.Init().WithPortBinding(5432, true).WithWaitStrategy(waitStrategy); } ``` diff --git a/docs/modules/mssql.md b/docs/modules/mssql.md index 93e1aa26c..d83260ff2 100644 --- a/docs/modules/mssql.md +++ b/docs/modules/mssql.md @@ -12,7 +12,7 @@ You can start a MSSQL container instance from any .NET application. To create an === "Start a MSSQL container" ```csharp - var msSqlContainer = new MsSqlBuilder().Build(); + var msSqlContainer = new MsSqlBuilder("mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04").Build(); await msSqlContainer.StartAsync(); ``` diff --git a/docs/modules/opensearch.md b/docs/modules/opensearch.md index df050268f..2d4c39edc 100644 --- a/docs/modules/opensearch.md +++ b/docs/modules/opensearch.md @@ -12,7 +12,7 @@ You can start an OpenSearch container instance from any .NET application. To cre === "Start an OpenSearch container" ```csharp - var openSearchContainer = new OpenSearchBuilder().Build(); + var openSearchContainer = new OpenSearchBuilder("opensearchproject/opensearch:2.12.0").Build(); await openSearchContainer.StartAsync(); ``` diff --git a/docs/modules/playwright.md b/docs/modules/playwright.md index 73fc0ab95..f5353fa4d 100644 --- a/docs/modules/playwright.md +++ b/docs/modules/playwright.md @@ -12,7 +12,7 @@ You can start a Playwright container instance from any .NET application. To crea === "Start a Playwright container" ```csharp - var playwrightContainer = new PlaywrightBuilder().Build(); + var playwrightContainer = new PlaywrightBuilder("mcr.microsoft.com/playwright:v1.55.1").Build(); await playwrightContainer.StartAsync(); ``` @@ -41,7 +41,7 @@ To execute the tests, use the command `dotnet test` from a terminal. The Playwright container is configured with a network that can be shared with other containers. This is useful when testing applications that need to communicate with other services. Use the `GetNetwork()` method to access the container's network: ```csharp -IContainer helloWorldContainer = new ContainerBuilder() +IContainer helloWorldContainer = new ContainerBuilder("testcontainers/helloworld:1.3.0") .WithNetwork(_playwrightContainer.GetNetwork()) .Build(); ``` \ No newline at end of file diff --git a/docs/modules/postgres.md b/docs/modules/postgres.md index 376056cf3..cd9c3879c 100644 --- a/docs/modules/postgres.md +++ b/docs/modules/postgres.md @@ -12,7 +12,7 @@ You can start a PostgreSQL container instance from any .NET application. To crea === "Start a PostgreSQL container" ```csharp - var postgreSqlContainer = new PostgreSqlBuilder().Build(); + var postgreSqlContainer = new PostgreSqlBuilder("postgres:15.1").Build(); await postgreSqlContainer.StartAsync(); ``` diff --git a/docs/modules/pulsar.md b/docs/modules/pulsar.md index 04ccca828..dcc88d1f9 100644 --- a/docs/modules/pulsar.md +++ b/docs/modules/pulsar.md @@ -48,7 +48,7 @@ string pulsarServiceUrl = _pulsarContainer.GetHttpServiceUrl(); If you need to use token authentication, use the following builder configuration to enable authentication: ```csharp -PulsarContainer _pulsarContainer = new PulsarBuilder().WithTokenAuthentication().Build(); +PulsarContainer _pulsarContainer = new PulsarBuilder("apachepulsar/pulsar:3.0.9").WithTokenAuthentication().Build(); ``` Start the container and obtain an authentication token with a specified expiration time @@ -70,5 +70,5 @@ var authToken = await container.CreateAuthenticationTokenAsync(Timeout.InfiniteT If you need to use Pulsar Functions, use the following builder configuration to enable it: ```csharp -PulsarContainer _pulsarContainer = new PulsarBuilder().WithFunctions().Build(); +PulsarContainer _pulsarContainer = new PulsarBuilder("apachepulsar/pulsar:3.0.9").WithFunctions().Build(); ``` \ No newline at end of file diff --git a/tests/Testcontainers.Commons/CommonImages.cs b/tests/Testcontainers.Commons/CommonImages.cs index b8cbe4978..c288d86f3 100644 --- a/tests/Testcontainers.Commons/CommonImages.cs +++ b/tests/Testcontainers.Commons/CommonImages.cs @@ -7,13 +7,13 @@ public static class CommonImages public static readonly IImage HelloWorld = new DockerImage("testcontainers/helloworld:1.3.0"); - public static readonly IImage Alpine = new DockerImage("alpine:3.17"); + public static readonly IImage Alpine = new DockerImage("alpine:3.20.0"); public static readonly IImage Socat = new DockerImage("alpine/socat:1.8.0.3"); public static readonly IImage Curl = new DockerImage("curlimages/curl:8.00.1"); - public static readonly IImage Nginx = new DockerImage("nginx:1.22"); + public static readonly IImage Nginx = new DockerImage("nginx:1.26.3-alpine3.20"); public static readonly IImage ServerCore = new DockerImage("mcr.microsoft.com/windows/servercore:ltsc2025"); } \ No newline at end of file