|
| 1 | +--- |
| 2 | +description: How to install Testcontainers for Go and run your first container |
| 3 | +keywords: testcontainers, testcontainers go, testcontainers oss, testcontainers oss go, testcontainers go quickstart |
| 4 | +toc_max: 3 |
| 5 | +title: Go quickstart |
| 6 | +linkTitle: Go |
| 7 | +aliases: |
| 8 | +- /testcontainers/getting-started/go/ |
| 9 | +weight: 10 |
| 10 | +--- |
| 11 | + |
| 12 | +_Testcontainers for Go_ plays well with the native `go test` framework. |
| 13 | + |
| 14 | +The ideal use case is for integration or end to end tests. It helps you to spin |
| 15 | +up and manage the dependencies life cycle via Docker. |
| 16 | + |
| 17 | +## System requirements |
| 18 | + |
| 19 | +### Go version |
| 20 | + |
| 21 | +From the [Go Release Policy](https://go.dev/doc/devel/release#policy): |
| 22 | + |
| 23 | +> 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). |
| 24 | +
|
| 25 | +_Testcontainers for Go_ is tested against those two latest Go releases, therefore we recommend using any of them. |
| 26 | + |
| 27 | +## Step 1:Install _Testcontainers for Go_ |
| 28 | + |
| 29 | +_Testcontainers for Go_ uses [go mod](https://blog.golang.org/using-go-modules) and you can get it installed via: |
| 30 | + |
| 31 | +``` |
| 32 | +go get github.com/testcontainers/testcontainers-go |
| 33 | +``` |
| 34 | + |
| 35 | +## Step 2: Spin up Redis |
| 36 | + |
| 37 | +```go |
| 38 | +import ( |
| 39 | + "context" |
| 40 | + "testing" |
| 41 | + |
| 42 | + "github.com/stretchr/testify/require" |
| 43 | + |
| 44 | + "github.com/testcontainers/testcontainers-go" |
| 45 | + "github.com/testcontainers/testcontainers-go/wait" |
| 46 | +) |
| 47 | + |
| 48 | +func TestWithRedis(t *testing.T) { |
| 49 | + ctx := context.Background() |
| 50 | + req := testcontainers.ContainerRequest{ |
| 51 | + Image: "redis:latest", |
| 52 | + ExposedPorts: []string{"6379/tcp"}, |
| 53 | + WaitingFor: wait.ForLog("Ready to accept connections"), |
| 54 | + } |
| 55 | + redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ |
| 56 | + ContainerRequest: req, |
| 57 | + Started: true, |
| 58 | + }) |
| 59 | + testcontainers.CleanupContainer(t, redisC) |
| 60 | + require.NoError(t, err) |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +The `testcontainers.ContainerRequest` describes how the Docker container will |
| 65 | +look. |
| 66 | + |
| 67 | +* `Image` is the Docker image the container starts from. |
| 68 | +* `ExposedPorts` lists the ports to be exposed from the container. |
| 69 | +* `WaitingFor` is a field you can use to validate when a container is ready. It |
| 70 | + is important to get this set because it helps to know when the container is |
| 71 | + ready to receive any traffic. In this case, we check for the logs we know come |
| 72 | + from Redis, telling us that it is ready to accept requests. |
| 73 | + |
| 74 | +When you use `ExposedPorts` you have to imagine yourself using `docker run -p |
| 75 | +<port>`. When you do so, `dockerd` maps the selected `<port>` from inside the |
| 76 | +container to a random one available on your host. |
| 77 | + |
| 78 | +In the previous example, we expose `6379` for `tcp` traffic to the outside. This |
| 79 | +allows Redis to be reachable from your code that runs outside the container, but |
| 80 | +it also makes parallelization possible because if you add `t.Parallel` to your |
| 81 | +tests, and each of them starts a Redis container each of them will be exposed on a |
| 82 | +different random port. |
| 83 | + |
| 84 | +`testcontainers.GenericContainer` creates the container. In this example we are |
| 85 | +using `Started: true`. It means that the container function will wait for the |
| 86 | +container to be up and running. If you set the `Start` value to `false` it won't |
| 87 | +start, leaving to you the decision about when to start it. |
| 88 | + |
| 89 | +All the containers must be removed at some point, otherwise they will run until |
| 90 | +the host is overloaded. One of the ways we have to clean up is by deferring the |
| 91 | +terminated function: `defer testcontainers.TerminateContainer(redisC)` which |
| 92 | +automatically handles nil container so is safe to use even in the error case. |
| 93 | + |
| 94 | +> [!TIP] |
| 95 | +> |
| 96 | +> Look at [features/garbage_collector](/features/garbage_collector/) to know another |
| 97 | +> way to clean up resources. |
| 98 | +
|
| 99 | +## Step 3: Make your code talk to the container |
| 100 | + |
| 101 | +This is just an example, but usually Go applications that rely on Redis are |
| 102 | +using the [redis-go](https://github.com/go-redis/redis) client. This code gets |
| 103 | +the endpoint from the container we just started, and it configures the client. |
| 104 | + |
| 105 | +```go |
| 106 | +endpoint, err := redisC.Endpoint(ctx, "") |
| 107 | +if err != nil { |
| 108 | + t.Error(err) |
| 109 | +} |
| 110 | + |
| 111 | +client := redis.NewClient(&redis.Options{ |
| 112 | + Addr: endpoint, |
| 113 | +}) |
| 114 | + |
| 115 | +_ = client |
| 116 | +``` |
| 117 | + |
| 118 | +We expose only one port, so the `Endpoint` does not need a second argument set. |
| 119 | + |
| 120 | +> [!TIP] |
| 121 | +> |
| 122 | +> If you expose more than one port you can specify the one you need as a second |
| 123 | +> argument. |
| 124 | +
|
| 125 | +In this case it returns: `localhost:<mappedportfor-6379>`. |
| 126 | + |
| 127 | +## Step 4: Run the test |
| 128 | + |
| 129 | +You can run the test via `go test ./...` |
| 130 | + |
| 131 | +## Step 5: Want to go deeper with Redis? |
| 132 | + |
| 133 | +You can find a more elaborated Redis example in our examples section. Please check it out [here](https://golang.testcontainers.org/modules/redis/). |
0 commit comments