-
-
Notifications
You must be signed in to change notification settings - Fork 492
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added getting started, gc and container creation
- Loading branch information
Gianluca Arbezzano
committed
May 12, 2020
1 parent
7046559
commit 48a6b03
Showing
8 changed files
with
211 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
# Contributing | ||
|
||
Hello | ||
|
||
We follow the same one used by [testcontainers-java check it out](https://www.testcontainers.org/contributing/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Lato|Merriweather+Sans|Open+Sans|Source+Sans+Pro'); | ||
|
||
body { | ||
font-family: 'Lato', sans-serif; | ||
|
||
} | ||
|
||
.md-typeset pre { | ||
font-family: 'Inconsolata', monospace; | ||
font-size: 100%; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# How to create a container | ||
|
||
When I have to describe TestContainer I say: "it is a wrapper around the docker | ||
daemon designed for tests." | ||
|
||
This libraries demands all the complexity of creating and managing container to | ||
Docker to stay focused on usability in a testing environment. | ||
|
||
You can use this library to run everything you can run with docker: | ||
|
||
* NoSQL databases or other data stores (e.g. redis, elasticsearch, mongo) | ||
* Web servers/proxies (e.g. nginx, apache) | ||
* Log services (e.g. logstash, kibana) | ||
* Other services developed by your team/organization which are already dockerized | ||
|
||
## GenericContainer | ||
|
||
`testcontainers.GenericContainer` identifies the ability to spin up a single | ||
container, you can look at it as a different way to create a `docker run` | ||
command. | ||
|
||
```go | ||
func TestNginxLatestReturn(t *testing.T) { | ||
ctx := context.Background() | ||
req := testcontainers.ContainerRequest{ | ||
Image: "nginx", | ||
ExposedPorts: []string{"80/tcp"}, | ||
WaitingFor: wait.ForHTTP("/"), | ||
} | ||
nginxC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
ContainerRequest: req, | ||
Started: true, | ||
}) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
defer nginxC.Terminate(ctx) | ||
ip, err := nginxC.Host(ctx) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
port, err := nginxC.MappedPort(ctx, "80") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
resp, err := http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) | ||
if resp.StatusCode != http.StatusOK { | ||
t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) | ||
} | ||
} | ||
``` | ||
|
||
This test creates an Nginx container and it validates that it returns a 200 as | ||
StatusCode. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Garbage Collector | ||
|
||
Usually one test creates at least one container. At the end it means a lot of | ||
containers running. We need to have a way to keep the CI servers reliable | ||
removing unused containers. | ||
|
||
Containers can be unused because: | ||
|
||
1. Test is over and the container is not needed anymore. | ||
2. Test failed, we do not need that container anymore because next build will | ||
create new containers. | ||
|
||
## Terminate function | ||
|
||
As we saw previously there are at least two way to remove unused containers. | ||
First one is to use the `Terminate(context.Conext)` function available when a | ||
container is created. You can call it in your test or you use `defer` . | ||
|
||
!!!tip | ||
Remember to `defer` as soon as possible so you won't forget. The best time | ||
is as soon as you call `testcontainers.GenericContainer` but remember to | ||
check for the `err` first. | ||
|
||
## Ryuk | ||
|
||
[https:/testcontainers/moby-ryuk](ryuk) helps you to remove | ||
containers/networks/volumes by given filter after specified delay. | ||
|
||
It is a project developer by TestContainer and it is used across the board for | ||
Java, Go and any more. | ||
|
||
When you run one tests you will see that there is not only the containers your | ||
tests requires running, there is another one called `ryuk`, we refers to it as | ||
`Reaper` as well in this library. | ||
|
||
Based on container labels it removes resources created from testcontainers that | ||
are running from more than 10 minutes. | ||
|
||
!!!tip | ||
This feature can be disabled when creating a container | ||
|
||
In this way even if you do not call Terminate, something will keep your | ||
environment clean. It will also clean itself when there is nothing left to do. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
TestContainers 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. | ||
|
||
This is way Docker has to be available for this library to work. | ||
|
||
## 1. Install | ||
|
||
We use [gomod](https://blog.golang.org/using-go-modules) and you can get it installed via: | ||
|
||
``` | ||
go get github.com/testcontainers/testcontainers-go | ||
``` | ||
|
||
## 2. Spin up Redis | ||
|
||
```go | ||
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, | ||
}) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
defer redisC.Terminate(ctx) | ||
} | ||
``` | ||
|
||
The `testcontainers.ContainerRequest` describes how the Docker container will | ||
look like. As you ca see it recalls to a lot of concepts related to it. | ||
|
||
* `Image` is the docker image the container starts from. | ||
* `ExposedPorts` lists the port that has 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 reach any traffic. In this case we checks for the logs we know coming | ||
from Redis, telling us that it is ready to accept requests. | ||
|
||
When you use `ExposedPorts` you have to image 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 | ||
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 you | ||
test and each of them starts a Redis container all of them will be exposed on a | ||
different random port. | ||
|
||
`testcontainers.GenericContainer` creates the container. In this example we are | ||
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' | ||
start. Leaving to you the decision about when to start it. | ||
|
||
All the container has to be removed at some point, otherwise they will run until | ||
the host will overloaded. One of the way we have to clean after ourself is | ||
defering the terminated function: `defer redisC.Terminate(ctx)`. | ||
|
||
!!!tip | ||
Lock at [features/garbage_collector.md] to know the other way we have to | ||
clean after ourself. | ||
|
||
## 3. Make your code to talk with the container | ||
|
||
This is just an example but usually Go applications that relay on redis are | ||
using the [redis-go](https:/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 an specify the one you need as second | ||
argument | ||
|
||
In this case it returns: `localhost:<mappedportfor-6379>`. | ||
|
||
## 3. Run the test | ||
|
||
You can run the test via `go test ./...` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters