Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add testcontainers-oss quickstart guides #22120

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions _vale/config/vocabularies/Docker/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Intune
JFrog
Jamf
JetBrains
JUnit
Kerberos
Kitematic
Kubeadm
Expand All @@ -80,6 +81,7 @@ Paketo
Postgres
PowerShell
Python
Ryuk
S3
SQLite
Slack
Expand Down
4 changes: 4 additions & 0 deletions content/manuals/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ params:
description: Define and run multi-container applications.
icon: /assets/icons/Compose.svg
link: /compose/
- title: Testcontainers OSS
description: Run containers programmatically in your preferred programming language.
icon: /assets/icons/Testcontainers.svg
link: /testcontainers/
products:
- title: Docker Desktop
description: Your command center for container development.
Expand Down
30 changes: 30 additions & 0 deletions content/manuals/testcontainers/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Testcontainers OSS
weight: 30
description: Learn how to use Testcontainers OSS to run containers programmatically in your preferred programming language.
keywords: docker APIs, docker, testcontainers documentation, testcontainers, testcontainers oss, testcontainers oss documentation,
docker compose, docker-compose, java, golang, go
params:
sidebar:
group: Open source
grid:
- title: Why use Testcontainers?
description: Understand Testcontainers' key benefits
icon: feature_search
link: /testcontainers/benefits/
- title: Quickstart
description: Learn the key concepts of Testcontainers OSS
icon: explore
link: /testcontainers/getting-started
aliases:
- /testcontainers/
---

Testcontainers is set libraries that provides easy and lightweight APIs for bootstrapping local development and test dependencies with real services wrapped in Docker containers.
Using Testcontainers, you can write tests that depend on the same services you use in production without mocks or in-memory services.

{{< grid >}}

## Want to know more?

- Visit the [Testcontainers website](https://testcontainers.com/getting-started/)
41 changes: 41 additions & 0 deletions content/manuals/testcontainers/benefits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
description: Key benefits and use cases of Testcontainers OSS
keywords: documentation, docs, docker, testcontainers, containers, uses, benefits
title: Why use Testcontainers?
weight: 10
linkTitle: Why use Testcontainers?
aliases:
- /testcontainers/benefits/
---

### Benefits of using Testcontainers

* **On-demand isolated infrastructure provisioning:**
You don't need to have a pre-provisioned integration testing infrastructure.
Testcontainers will provide the required services before running your tests.
There will be no test data pollution, even when multiple build pipelines run in parallel
because each pipeline runs with an isolated set of services.

* **Consistent experience on both local and CI environments:**
You can run your integration tests right from your IDE, just like you run unit tests.
No need to push your changes and wait for the CI pipeline to complete.

* **Reliable test setup using wait strategies:**
Docker containers need to be started and fully initialized before using them in your tests.
The Testcontainers library offers several out-of-the-box wait strategies implementations to make sure
the containers (and the application within) are fully initialized.
Testcontainers modules already implement the relevant wait strategies for a given technology,
and you can always implement your own or create a composite strategy if needed.

* **Advanced networking capabilities:**
Testcontainers libraries map the container's ports onto random ports available on the host machine
so that your tests connect reliably to those services. You can even create a (Docker) network and
connect multiple containers together so that they talk to each other via static Docker network aliases.

* **Automatic clean up:**
The Testcontainers library takes care of removing any created resources (containers, volumes, networks etc.)
automatically after the test execution is complete by using the Ryuk sidecar container.
While starting the required containers, Testcontainers attaches a set of labels to the
created resources (containers, volumes, networks etc) and Ryuk automatically performs
resource clean up by matching those labels.
This works reliably even when the test process exits abnormally (for example sending a SIGKILL).
35 changes: 35 additions & 0 deletions content/manuals/testcontainers/getting-started/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
description: Learn how to install Testcontainers OSS and run your first container
keywords: testcontainers, testcontainers quickstart, testcontainers oss, testcontainers oss quickstart, testcontainers quickstart,
java, go, golang
title: Testcontainers Quickstart
linkTitle: Testcontainers Quickstart
weight: 20
toc_max: 3
aliases:
- /testcontainers/getting-started/
---

This page contains summary information about Testcontainers OSS.

## Supported languages

Testcontainers provide support for the most popular languages, and Docker sponsors the development of the following Testcontainers implementations:

- [Go](/manuals/testcontainers/getting-started/go.md)
- [Java](/manuals/testcontainers/getting-started/java.md)

The rest are community-driven and maintained by independent contributors.

## Prerequisites

Testcontainers requires a Docker-API compatible container runtime.
During development, Testcontainers is actively tested against recent versions of Docker on Linux, as well as against Docker Desktop on Mac and Windows.
These Docker environments are automatically detected and used by Testcontainers without any additional configuration being necessary.

It is possible to configure Testcontainers to work for other Docker setups, such as a remote Docker host or Docker alternatives.
However, these are not actively tested in the main development workflow, so not all Testcontainers features might be available
and additional manual configuration might be necessary.

If you have further questions about configuration details for your setup or whether it supports running Testcontainers-based tests,
contact the Testcontainers team and other users from the Testcontainers community on [Slack](https://slack.testcontainers.org/).
131 changes: 131 additions & 0 deletions content/manuals/testcontainers/getting-started/go.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
description: How to install Testcontainers for Go and run your first container
keywords: testcontainers, testcontainers go, testcontainers oss, testcontainers oss go, testcontainers go quickstart
toc_max: 3
title: Go quickstart
linkTitle: Go
aliases:
- /testcontainers/getting-started/go/
weight: 10
---

_Testcontainers for Go_ plays well with the native `go test` framework.

The ideal use case is for integration or end to end tests. It helps you to spin
up and manage the dependencies life cycle via Docker.

## System requirements

### Go version

From the [Go Release Policy](https://go.dev/doc/devel/release#policy):

> Each major Go release is supported until there are two newer major releases. For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was supported until the Go 1.8 release. We fix critical problems, including critical security problems, in supported releases as needed by issuing minor revisions (for example, Go 1.6.1, Go 1.6.2, and so on).

Check warning on line 23 in content/manuals/testcontainers/getting-started/go.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Docker.We] Avoid using first-person plural like 'We'. Raw Output: {"message": "[Docker.We] Avoid using first-person plural like 'We'.", "location": {"path": "content/manuals/testcontainers/getting-started/go.md", "range": {"start": {"line": 23, "column": 191}}}, "severity": "WARNING"}

_Testcontainers for Go_ is tested against those two latest Go releases, therefore it's recommended to use any of them.

## Step 1: Install _Testcontainers for Go_

_Testcontainers for Go_ uses [go mod](https://blog.golang.org/using-go-modules) and you can get it installed via:

```bash
go get github.com/testcontainers/testcontainers-go
```

## Step 2: Spin up Redis

```go
import (
"context"
"testing"

"github.com/stretchr/testify/require"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)

func TestWithRedis(t *testing.T) {
ctx := context.Background()
req := testcontainers.ContainerRequest{
Image: "redis:latest",
ExposedPorts: []string{"6379/tcp"},
WaitingFor: wait.ForLog("Ready to accept connections"),
}
redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
testcontainers.CleanupContainer(t, redisC)
require.NoError(t, err)
}
```

The `testcontainers.ContainerRequest` describes how the Docker container will
look.

* `Image` is the Docker image the container starts from.
* `ExposedPorts` lists the ports to be exposed from the container.
* `WaitingFor` is a field you can use to validate when a container is ready.
It is important to get this set because it helps to know when the container is
ready to receive any traffic. In this case, the project checks for the logs that come from Redis, mentioning that it is ready to accept requests.

When you use `ExposedPorts` you have to imagine yourself using `docker run -p
<port>`. When you do so, `dockerd` maps the selected `<port>` from inside the
container to a random one available on your host.

In the previous example, the `6379/tcp` port is exposed to the outside. This

Check warning on line 77 in content/manuals/testcontainers/getting-started/go.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Docker.SentenceLength] Write short, concise sentences. (<=40 words) Raw Output: {"message": "[Docker.SentenceLength] Write short, concise sentences. (\u003c=40 words)", "location": {"path": "content/manuals/testcontainers/getting-started/go.md", "range": {"start": {"line": 77, "column": 73}}}, "severity": "WARNING"}
allows Redis to be reachable from your code that runs outside the container, but
it also makes parallel execution possible: if you add `t.Parallel` to your
tests, and each of them starts a Redis container, then each of them will be
exposed on a different random port.

`testcontainers.GenericContainer` creates the container. This example uses `Started: true`. It means that the container function will wait for the
container to be up and running. If you set the `Start` value to `false` it won't
start, leaving to you the decision about when to start it.

All the containers must be removed at some point, otherwise they will run until
the host is overloaded. You can do the clean up by deferring the
terminated function: `defer testcontainers.TerminateContainer(redisC)` which
automatically handles nil container so is safe to use even in the error case.

> [!TIP]
>
> Look at [features/garbage_collector](https://golang.testcontainers.org/features/garbage_collector/) to know another
> way to clean up resources.

## Step 3: Talking to the container

This is just an example, but usually Go applications that rely on Redis are
using the [redis-go](https://github.com/go-redis/redis) client. This code gets
the endpoint from the container that was started before, and it configures the client.

```go
endpoint, err := redisC.Endpoint(ctx, "")
if err != nil {
t.Error(err)
}

client := redis.NewClient(&redis.Options{
Addr: endpoint,
})

_ = client
```

The container exposed only one port, so the `Endpoint` does not need a second argument set.

> [!TIP]
>
> If you expose more than one port you can specify the one you need as a second
> argument.

In this case it returns: `localhost:<mappedportfor-6379>`.

## Step 4: Run the test

You can run the test via `go test ./...`

## Step 5: Want to go deeper with Redis?

You can find a more elaborated Redis example in the [Redis module docs](https://golang.testcontainers.org/modules/redis/).
Loading
Loading