Skip to content

Commit 00a7e17

Browse files
authored
deps(compose): bump compose to v2.34.0 and compose-go to v2.4.9 (#3041)
* chore: mod tidy * docs: use embedded code snippets
1 parent 25437ec commit 00a7e17

File tree

6 files changed

+340
-275
lines changed

6 files changed

+340
-275
lines changed

docs/features/docker_compose.md

Lines changed: 24 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,20 @@ Please refer to [the Ryuk configuration](../configuration/#customizing-ryuk-the-
2626

2727
### Usage
2828

29-
Use the convenience `NewDockerCompose(...)` constructor which creates a random identifier and takes a variable number
30-
of stack files:
31-
32-
```go
33-
package example_test
34-
35-
import (
36-
"context"
37-
"testing"
38-
39-
"github.com/stretchr/testify/require"
40-
tc "github.com/testcontainers/testcontainers-go/modules/compose"
41-
)
42-
43-
func TestSomething(t *testing.T) {
44-
compose, err := tc.NewDockerCompose("testdata/docker-compose.yml")
45-
require.NoError(t, err, "NewDockerComposeAPI()")
46-
47-
t.Cleanup(func() {
48-
require.NoError(t, compose.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveImagesLocal), "compose.Down()")
49-
})
50-
51-
ctx, cancel := context.WithCancel(context.Background())
52-
t.Cleanup(cancel)
53-
54-
require.NoError(t, compose.Up(ctx, tc.Wait(true)), "compose.Up()")
55-
56-
// do some testing here
57-
}
58-
```
59-
6029
Use the advanced `NewDockerComposeWith(...)` constructor allowing you to customise the compose execution with options:
6130

6231
- `StackIdentifier`: the identifier for the stack, which is used to name the network and containers. If not passed, a random identifier is generated.
6332
- `WithStackFiles`: specify the Docker Compose stack files to use, as a variadic argument of string paths where the stack files are located.
6433
- `WithStackReaders`: specify the Docker Compose stack files to use, as a variadic argument of `io.Reader` instances. It will create a temporary file in the temp dir of the given O.S., that will be removed after the `Down` method is called. You can use both `WithComposeStackFiles` and `WithComposeStackReaders` at the same time.
6534

35+
<!--codeinclude-->
36+
[Define Compose File](../../modules/compose/compose_examples_test.go) inside_block:defineComposeFile
37+
[Define Options](../../modules/compose/compose_examples_test.go) inside_block:defineStackWithOptions
38+
[Start Compose Stack](../../modules/compose/compose_examples_test.go) inside_block:upComposeStack
39+
[Get Service Names](../../modules/compose/compose_examples_test.go) inside_block:getServiceNames
40+
[Get Service Container](../../modules/compose/compose_examples_test.go) inside_block:getServiceContainer
41+
<!--/codeinclude-->
42+
6643
#### Compose Up options
6744

6845
- `Recreate`: recreate the containers. If any other value than `api.RecreateNever`, `api.RecreateForce` or `api.RecreateDiverged` is provided, the default value `api.RecreateForce` will be used.
@@ -76,91 +53,26 @@ Use the advanced `NewDockerComposeWith(...)` constructor allowing you to customi
7653
- `RemoveOrphans`: remove orphaned containers after the stack is stopped.
7754
- `RemoveVolumes`: remove volumes after the stack is stopped.
7855

79-
#### Example
80-
81-
```go
82-
package example_test
83-
84-
import (
85-
"context"
86-
"testing"
87-
88-
"github.com/stretchr/testify/require"
89-
90-
"github.com/docker/compose/v2/pkg/api"
91-
tc "github.com/testcontainers/testcontainers-go/modules/compose"
92-
)
93-
94-
func TestSomethingElse(t *testing.T) {
95-
identifier := tc.StackIdentifier("some_ident")
96-
compose, err := tc.NewDockerComposeWith(tc.WithStackFiles("./testdata/docker-compose-simple.yml"), identifier)
97-
require.NoError(t, err, "NewDockerComposeAPIWith()")
98-
99-
t.Cleanup(func() {
100-
require.NoError(t, compose.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveImagesLocal), "compose.Down()")
101-
})
102-
103-
ctx, cancel := context.WithCancel(context.Background())
104-
t.Cleanup(cancel)
105-
106-
require.NoError(t, compose.Up(ctx, tc.WithRecreate(api.RecreateNever), tc.Wait(true)), "compose.Up()")
107-
108-
// do some testing here
109-
}
110-
```
111-
11256
### Interacting with compose services
11357

114-
To interact with service containers after a stack was started it is possible to get an `*tc.DockerContainer` instance via the `ServiceContainer(...)` function.
115-
The function takes a **service name** (and a `context.Context`) and returns either a `*tc.DockerContainer` or an `error`.
116-
This is different to the previous `LocalDockerCompose` API where service containers were accessed via their **container name** e.g. `mysql_1` or `mysql-1` (depending on the version of `docker compose`).
58+
To interact with service containers after a stack was started it is possible to get a `*testcontainers.DockerContainer` instance via the `ServiceContainer(...)` function.
59+
The function takes a **service name** (and a `context.Context`) and returns either a `*testcontainers.DockerContainer` or an `error`.
11760

11861
Furthermore, there's the convenience function `Services()` to get a list of all services **defined** by the current project.
11962
Note that not all of them need necessarily be correctly started as the information is based on the given compose files.
12063

12164
### Wait strategies
12265

123-
Just like with regular test containers you can also apply wait strategies to `docker compose` services.
66+
Just like with the containers created by _Testcontainers for Go_, you can also apply wait strategies to `docker compose` services.
12467
The `ComposeStack.WaitForService(...)` function allows you to apply a wait strategy to **a service by name**.
12568
All wait strategies are executed in parallel to both improve startup performance by not blocking too long and to fail
12669
early if something's wrong.
12770

12871
#### Example
12972

130-
```go
131-
package example_test
132-
133-
import (
134-
"context"
135-
"testing"
136-
"time"
137-
138-
"github.com/stretchr/testify/require"
139-
tc "github.com/testcontainers/testcontainers-go/modules/compose"
140-
"github.com/testcontainers/testcontainers-go/wait"
141-
)
142-
143-
func TestSomethingWithWaiting(t *testing.T) {
144-
identifier := tc.StackIdentifier("some_ident")
145-
compose, err := tc.NewDockerComposeWith(tc.WithStackFiles("./testdata/docker-compose-simple.yml"), identifier)
146-
require.NoError(t, err, "NewDockerComposeAPIWith()")
147-
148-
t.Cleanup(func() {
149-
require.NoError(t, compose.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveImagesLocal), "compose.Down()")
150-
})
151-
152-
ctx, cancel := context.WithCancel(context.Background())
153-
t.Cleanup(cancel)
154-
155-
err = compose.
156-
WaitForService("nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)).
157-
Up(ctx, tc.Wait(true))
158-
159-
require.NoError(t, err, "compose.Up()")
160-
161-
// do some testing here
162-
}
163-
```
73+
<!--codeinclude-->
74+
[Compose Example](../../modules/compose/compose_examples_test.go) inside_block:ExampleNewDockerComposeWith_waitForService
75+
<!--/codeinclude-->
16476

16577
### Compose environment
16678

@@ -175,10 +87,11 @@ The `ComposeStack` supports this as well in two different variants:
17587
Also have a look at [ComposeStack](https://pkg.go.dev/github.com/testcontainers/testcontainers-go#ComposeStack) docs for
17688
further information.
17789

178-
## Usage of the `docker compose` binary
90+
## Usage of the deprecated Local `docker compose` binary
17991

180-
_Note:_ this API is deprecated and superseded by `ComposeStack` which takes advantage of `compose` v2 being
181-
implemented in Go as well by directly using the upstream project.
92+
!!! warning
93+
This API is deprecated and superseded by `ComposeStack` which takes advantage of `compose` v2 being
94+
implemented in Go as well by directly using the upstream project.
18295

18396
You can override Testcontainers' default behaviour and make it use a
18497
docker compose binary installed on the local machine. This will generally yield
@@ -187,41 +100,16 @@ that Docker Compose needs to be present on dev and CI machines.
187100

188101
### Examples
189102

190-
```go
191-
composeFilePaths := []string {"testdata/docker-compose.yml"}
192-
identifier := strings.ToLower(uuid.New().String())
193-
194-
compose := tc.NewLocalDockerCompose(composeFilePaths, identifier)
195-
execError := compose.
196-
WithCommand([]string{"up", "-d"}).
197-
WithEnv(map[string]string {
198-
"key1": "value1",
199-
"key2": "value2",
200-
}).
201-
Invoke()
202-
203-
err := execError.Error
204-
if err != nil {
205-
return fmt.Errorf("Could not run compose file: %v - %v", composeFilePaths, err)
206-
}
207-
return nil
208-
```
103+
<!--codeinclude-->
104+
[Invoke Example](../../modules/compose/compose_local_examples_test.go) inside_block:ExampleLocalDockerCompose_Invoke
105+
<!--/codeinclude-->
209106

210107
Note that the environment variables in the `env` map will be applied, if
211108
possible, to the existing variables declared in the Docker Compose file.
212109

213110
In the following example, we demonstrate how to stop a Docker Compose created project using the
214111
convenient `Down` method.
215112

216-
```go
217-
composeFilePaths := []string{"testdata/docker-compose.yml"}
218-
219-
compose := tc.NewLocalDockerCompose(composeFilePaths, identifierFromExistingRunningCompose)
220-
execError := compose.Down()
221-
err := execError.Error
222-
if err != nil {
223-
return fmt.Errorf("Could not run compose file: %v - %v", composeFilePaths, err)
224-
}
225-
return nil
226-
```
227-
113+
<!--codeinclude-->
114+
[Down Example](../../modules/compose/compose_local_examples_test.go) inside_block:ExampleLocalDockerCompose_Down
115+
<!--/codeinclude-->
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package compose_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"slices"
8+
"strings"
9+
"time"
10+
11+
"github.com/testcontainers/testcontainers-go/modules/compose"
12+
"github.com/testcontainers/testcontainers-go/wait"
13+
)
14+
15+
func ExampleNewDockerComposeWith() {
16+
// defineComposeFile {
17+
composeContent := `services:
18+
nginx:
19+
image: nginx:stable-alpine
20+
environment:
21+
bar: ${bar}
22+
foo: ${foo}
23+
ports:
24+
- "8081:80"
25+
mysql:
26+
image: mysql:8.0.36
27+
environment:
28+
- MYSQL_DATABASE=db
29+
- MYSQL_ROOT_PASSWORD=my-secret-pw
30+
ports:
31+
- "3307:3306"
32+
`
33+
// }
34+
35+
// defineStackWithOptions {
36+
stack, err := compose.NewDockerComposeWith(
37+
compose.StackIdentifier("test"),
38+
compose.WithStackReaders(strings.NewReader(composeContent)),
39+
)
40+
if err != nil {
41+
log.Printf("Failed to create stack: %v", err)
42+
return
43+
}
44+
// }
45+
46+
ctx, cancel := context.WithCancel(context.Background())
47+
defer cancel()
48+
49+
// upComposeStack {
50+
err = stack.
51+
WithEnv(map[string]string{
52+
"bar": "BAR",
53+
"foo": "FOO",
54+
}).
55+
WaitForService("nginx", wait.ForListeningPort("80/tcp")).
56+
Up(ctx, compose.Wait(true))
57+
if err != nil {
58+
log.Printf("Failed to start stack: %v", err)
59+
return
60+
}
61+
defer func() {
62+
err = stack.Down(
63+
context.Background(),
64+
compose.RemoveOrphans(true),
65+
compose.RemoveVolumes(true),
66+
compose.RemoveImagesLocal,
67+
)
68+
if err != nil {
69+
log.Printf("Failed to stop stack: %v", err)
70+
}
71+
}()
72+
// }
73+
74+
// getServiceNames {
75+
serviceNames := stack.Services()
76+
// }
77+
78+
// both services are started
79+
fmt.Println(len(serviceNames))
80+
fmt.Println(slices.Contains(serviceNames, "nginx"))
81+
fmt.Println(slices.Contains(serviceNames, "mysql"))
82+
83+
// nginx container is started
84+
// getServiceContainer {
85+
nginxContainer, err := stack.ServiceContainer(context.Background(), "nginx")
86+
if err != nil {
87+
log.Printf("Failed to get container: %v", err)
88+
return
89+
}
90+
// }
91+
92+
inspect, err := nginxContainer.Inspect(context.Background())
93+
if err != nil {
94+
log.Printf("Failed to inspect container: %v", err)
95+
return
96+
}
97+
98+
// the nginx container has the correct environment variables
99+
present := map[string]string{
100+
"bar": "BAR",
101+
"foo": "FOO",
102+
}
103+
for k, v := range present {
104+
keyVal := k + "=" + v
105+
fmt.Println(slices.Contains(inspect.Config.Env, keyVal))
106+
}
107+
108+
// Output:
109+
// 2
110+
// true
111+
// true
112+
// true
113+
// true
114+
}
115+
116+
func ExampleNewDockerComposeWith_waitForService() {
117+
composeContent := `services:
118+
nginx:
119+
image: nginx:stable-alpine
120+
environment:
121+
bar: ${bar}
122+
foo: ${foo}
123+
ports:
124+
- "8081:80"
125+
`
126+
127+
ctx, cancel := context.WithCancel(context.Background())
128+
defer cancel()
129+
130+
stack, err := compose.NewDockerComposeWith(compose.WithStackReaders(strings.NewReader(composeContent)))
131+
if err != nil {
132+
log.Printf("Failed to create stack: %v", err)
133+
return
134+
}
135+
136+
err = stack.
137+
WithEnv(map[string]string{
138+
"bar": "BAR",
139+
}).
140+
WaitForService("nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)).
141+
Up(ctx, compose.Wait(true))
142+
if err != nil {
143+
log.Printf("Failed to start stack: %v", err)
144+
return
145+
}
146+
defer func() {
147+
err = stack.Down(
148+
context.Background(),
149+
compose.RemoveOrphans(true),
150+
compose.RemoveVolumes(true),
151+
compose.RemoveImagesLocal,
152+
)
153+
if err != nil {
154+
log.Printf("Failed to stop stack: %v", err)
155+
}
156+
}()
157+
158+
serviceNames := stack.Services()
159+
160+
fmt.Println(serviceNames)
161+
162+
// Output:
163+
// [nginx]
164+
}

0 commit comments

Comments
 (0)