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

Merged
merged 6 commits into from
Mar 3, 2025
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
chore: adds quickstarts for tc-go and tc-java
  • Loading branch information
mdelapenya committed Feb 27, 2025
commit 56151458503a7955e96d12edbc224f34dcc821fd
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.

Check failure on line 37 in content/manuals/testcontainers/benefits.md

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'Ryuk'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'Ryuk'?", "location": {"path": "content/manuals/testcontainers/benefits.md", "range": {"start": {"line": 37, "column": 65}}}, "severity": "ERROR"}
While starting the required containers, Testcontainers attaches a set of labels to the
created resources (containers, volumes, networks etc) and Ryuk automatically performs

Check failure on line 39 in content/manuals/testcontainers/benefits.md

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'Ryuk'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'Ryuk'?", "location": {"path": "content/manuals/testcontainers/benefits.md", "range": {"start": {"line": 39, "column": 59}}}, "severity": "ERROR"}
resource clean up by matching those labels.
This works reliably even when the test process exits abnormally (e.g. sending a SIGKILL).

Check warning on line 41 in content/manuals/testcontainers/benefits.md

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Docker.RecommendedWords] Consider using 'for example' instead of 'e.g.' Raw Output: {"message": "[Docker.RecommendedWords] Consider using 'for example' instead of 'e.g.'", "location": {"path": "content/manuals/testcontainers/benefits.md", "range": {"start": {"line": 41, "column": 66}}}, "severity": "INFO"}
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,
please contact the Testcontainers team and other users from the Testcontainers community on [Slack](https://slack.testcontainers.org/).

Check warning on line 35 in content/manuals/testcontainers/getting-started/_index.md

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Docker.Avoid] Consider removing 'please'. Raw Output: {"message": "[Docker.Avoid] Consider removing 'please'.", "location": {"path": "content/manuals/testcontainers/getting-started/_index.md", "range": {"start": {"line": 35, "column": 1}}}, "severity": "WARNING"}
133 changes: 133 additions & 0 deletions content/manuals/testcontainers/getting-started/go.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
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

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 we recommend using any of them.

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

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": 25, "column": 83}}}, "severity": "WARNING"}

## 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:

```
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

Check failure on line 70 in content/manuals/testcontainers/getting-started/go.md

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Docker.Spacing] ' ' should have one space. Raw Output: {"message": "[Docker.Spacing] ' ' should have one space.", "location": {"path": "content/manuals/testcontainers/getting-started/go.md", "range": {"start": {"line": 70, "column": 1}}}, "severity": "ERROR"}
ready to receive any traffic. In this case, we check for the logs we know come

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

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": 71, "column": 47}}}, "severity": "WARNING"}

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

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": 71, "column": 69}}}, "severity": "WARNING"}
from Redis, telling us that it is ready to accept requests.

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

GitHub Actions / vale

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

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, we expose `6379` for `tcp` traffic to the outside. This

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

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": 78, "column": 26}}}, "severity": "WARNING"}

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

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": 78, "column": 77}}}, "severity": "WARNING"}
allows Redis to be reachable from your code that runs outside the container, but
it also makes parallelization possible because if you add `t.Parallel` to your

Check failure on line 80 in content/manuals/testcontainers/getting-started/go.md

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'parallelization'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'parallelization'?", "location": {"path": "content/manuals/testcontainers/getting-started/go.md", "range": {"start": {"line": 80, "column": 15}}}, "severity": "ERROR"}
tests, and each of them starts a Redis container each of them will be exposed on a
different random port.

`testcontainers.GenericContainer` creates the container. In this example we are

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

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": 84, "column": 74}}}, "severity": "WARNING"}
using `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. One of the ways we have to clean up is 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](/features/garbage_collector/) to know another
> way to clean up resources.

## Step 3: Make your code talk 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 we just started, 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
```

We expose 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 our examples section. Please check it out [here](https://golang.testcontainers.org/modules/redis/).
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.