README ¶
TestContainers dotnet
Testcontainers is a dotnet standard 2.0 library that supports NUnit and XUnit tests, providing lightweight, throwaway instances of common databases or anything else that can run in a Docker container.
Uses common Microsoft dependency injection patterns, app and host settings, and Microsoft Extensions Logging (MEL).
This is a port of testcontainers-java for dotnet.
Feature parity
Linux environment
- Container management
- Docker providers
- Unix socket
- Environment
- Image management
- Pulling from public repo
- Building from docker file
- Network management
- User defined networks
- Network aliases
- Ryuk resource reaper
Windows environment
- Container management
- Docker providers
- Npipe
- Environment
- Image management
- Pulling from public repo
- Building from docker file
- Network management
- User defined networks
- Network aliases
- Todo: Windows version of Ryuk [Help wanted]
Built-in containers
Container | Readme | Version |
---|---|---|
Generic Container | -- | |
MsSql Container | README | |
PostgreSql Container | README | |
ArangoDb Container | README |
Example code
For more examples, see integration tests
Start a container by pulling the image from a remote repository
var container = new ContainerBuilder<GenericContainer>()
.ConfigureHostConfiguration(builder => builder.AddInMemoryCollection()) // host settings
.ConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection()) // app settings
.ConfigureDockerImageName(PlatformSpecific.TinyDockerImage)
.ConfigureLogging(builder => builder.AddConsole()) // Microsoft extensions logging
.ConfigureContainer((context, container) =>
{
// add labels
container.Labels.Add(CustomLabel.Key, CustomLabel.Value);
// add environment labels
container.Env[InjectedEnvVar.Key] = InjectedEnvVar.Value;
// add exposed ports (automatically mapped to higher port
container.ExposedPorts.Add(ExposedPort);
/*
to do something like `docker run -p 2345:34567 alpine:latest`,
both expose port and port binding must be set
*/
container.ExposedPorts.Add(PortBinding.Key);
container.PortBindings.Add(PortBinding.Key, PortBinding.Value);
// add bind mounts
container.BindMounts.Add(new Bind
{
HostPath = HostPathBinding.Key,
ContainerPath = HostPathBinding.Value,
AccessMode = AccessMode.ReadOnly
});
// set working directory
container.WorkingDirectory = WorkingDirectory;
// set command to run
container.Command = PlatformSpecific.ShellCommand(
$"{PlatformSpecific.Touch} {FileTouchedByCommand}; {PlatformSpecific.Shell}")
.ToList();
})
.Build();
Start a container by building the image from a Dockerfile
var image = new ImageBuilder<DockerfileImage>()
.ConfigureHostConfiguration(builder => builder.AddInMemoryCollection()) // host settings
.ConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection()) // app settings
.ConfigureLogging(builder => builder.AddConsole()) // Microsoft extensions logging
.ConfigureImage((context, image) =>
{
image.DockerfilePath = "Dockerfile";
image.DeleteOnExit = false;
// add the Dockerfile into the build context
image.Transferables.Add("Dockerfile", new MountableFile(PlatformSpecific.DockerfileImagePath));
// add other files required by the Dockerfile into the build context
image.Transferables.Add(".", new MountableFile(PlatformSpecific.DockerfileImageContext));
})
.Build();
var container = new ContainerBuilder<GenericContainer>()
.ConfigureDockerImage(image)
.ConfigureHostConfiguration(builder => builder.AddInMemoryCollection()) // host settings
.ConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection()) // app settings
.ConfigureLogging(builder => builder.AddConsole()) // Microsoft extensions logging
.ConfigureContainer((h, c) =>
{
c.ExposedPorts.Add(80);
})
.Build();
or
var container = new ContainerBuilder<GenericContainer>()
.ConfigureDockerImage((hostContext, builderContext) =>
{
return new ImageBuilder<DockerfileImage>()
// share the app/host config and service collection from the parent builder context
.WithContextFrom(builderContext)
.ConfigureImage((context, image) =>
{
image.DeleteOnExit = false;
image.BasePath = PlatformSpecific.DockerfileImageContext;
// add the Dockerfile as like the command line `-f <path to dockerfile`
image.DockerfilePath = "Dockerfile";
image.Transferables.Add("Dockerfile", new MountableFile(PlatformSpecific.DockerfileImagePath));
// add other files required by the Dockerfile into the build context
image.Transferables.Add("folder1", new MountableFile(DockerfileImageTransferableFolder));
})
.Build();
})
.ConfigureHostConfiguration(builder => builder.AddInMemoryCollection()) // host settings
.ConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection()) // app settings
.ConfigureLogging(builder => builder.AddConsole()) // Microsoft extensions logging
.ConfigureContainer((h, c) =>
{
c.ExposedPorts.Add(80);
})
.Build();
Start a container with a new network
var container = new ContainerBuilder<GenericContainer>()
.ConfigureNetwork((hostContext, builderContext) =>
{
return new NetworkBuilder<UserDefinedNetwork>()
// share the app/host config and service collection from the parent builder context
.WithContextFrom(builderContext)
.ConfigureNetwork((context, network) =>
{
// be careful when setting static network names
// if they already exists, the existing network will be used
// otherwise, the default NetworkName is a random string
network.NetworkName = "my_network"
})
.Build();
})
.ConfigureHostConfiguration(builder => builder.AddInMemoryCollection()) // host settings
.ConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection()) // app settings
.ConfigureLogging(builder => builder.AddConsole()) // Microsoft extensions logging
.ConfigureContainer((h, c) =>
{
c.ExposedPorts.Add(80);
})
.Build();
Configuring TestContainers-dotnet
There are some configurations to testcontainers-dotnet that cannot be performed in code or injected. These configuration can be set in environment variables before the first instance of your container is built.
Variable | Default | Description |
---|---|---|
REAPER_DISABLED |
(not-set) | When set to 1 or true , disables starting of the reaper container |
REAPER_IMAGE |
quay.io/testcontainers/ryuk:0.2.3 |
Change which container image to use for reaper |
Click to show internal directories.
Click to hide internal directories.