Skip to content

Commit 97b02f2

Browse files
committed
Merge branch 'main' into wait-for-available-ports
* main: chore(deps): bump github.com/docker/docker from v26.1.4 to v27.0.2 (#2593) fix: Rename TC_HOST environment variable to TESTCONTAINERS_HOST_OVERRIDE (#2536) chore: test cleanups (#2608) chore(ci): pass docker install type to the nightly build payload (#2612) chore: run rootless mode in nighlty builds (#2611) chore(deps): bump github.com/hashicorp/go-retryablehttp (#2605) chore: improve log handling when container is stopping (#2601)
2 parents b0c17a8 + 989b422 commit 97b02f2

File tree

103 files changed

+500
-550
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+500
-550
lines changed

.github/workflows/docker-moby-latest.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,25 @@ on:
77

88
jobs:
99
test_latest_moby:
10+
strategy:
11+
matrix:
12+
rootless-docker: [true, false]
1013
name: "Core tests using latest moby/moby"
1114
runs-on: 'ubuntu-latest'
15+
continue-on-error: true
1216
steps:
17+
- name: Set the Docker Install type
18+
run: |
19+
echo "docker_install_type=${{ matrix.rootless-docker == true && 'Rootless' || 'Rootful' }}" >> "$GITHUB_ENV"
20+
21+
- name: Setup rootless Docker
22+
if: ${{ matrix.rootless-docker }}
23+
uses: ScribeMD/rootless-docker@6bd157a512c2fafa4e0243a8aa87d964eb890886 # v0.2.2
24+
25+
- name: Remove Docker root socket
26+
if: ${{ matrix.rootless-docker }}
27+
run: sudo rm -rf /var/run/docker.sock
28+
1329
- name: Check out code into the Go module directory
1430
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
1531

@@ -39,6 +55,7 @@ jobs:
3955
cat <<EOF > ./payload-slack-content.json
4056
{
4157
"tc_project": "testcontainers-go",
58+
"tc_docker_install_type": "${docker_install_type}",
4259
"tc_github_action_url": "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/attempts/${GITHUB_RUN_ATTEMPT}",
4360
"tc_github_action_status": "FAILED",
4461
"tc_slack_channel_id": "${{ secrets.SLACK_DOCKER_LATEST_CHANNEL_ID }}"

docker.go

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package testcontainers
33
import (
44
"archive/tar"
55
"bufio"
6-
"bytes"
76
"context"
87
"encoding/base64"
98
"encoding/binary"
@@ -12,6 +11,7 @@ import (
1211
"fmt"
1312
"io"
1413
"io/fs"
14+
"net"
1515
"net/url"
1616
"os"
1717
"path/filepath"
@@ -156,7 +156,7 @@ func (c *DockerContainer) PortEndpoint(ctx context.Context, port nat.Port, proto
156156

157157
// Host gets host (ip or name) of the docker daemon where the container port is exposed
158158
// Warning: this is based on your Docker host setting. Will fail if using an SSH tunnel
159-
// You can use the "TC_HOST" env variable to set this yourself
159+
// You can use the "TESTCONTAINERS_HOST_OVERRIDE" env variable to set this yourself
160160
func (c *DockerContainer) Host(ctx context.Context) (string, error) {
161161
host, err := c.provider.DaemonHost(ctx)
162162
if err != nil {
@@ -507,7 +507,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string, options ...tce
507507
return 0, nil, err
508508
}
509509

510-
hijack, err := cli.ContainerExecAttach(ctx, response.ID, types.ExecStartCheck{})
510+
hijack, err := cli.ContainerExecAttach(ctx, response.ID, container.ExecAttachOptions{})
511511
if err != nil {
512512
return 0, nil, err
513513
}
@@ -596,7 +596,7 @@ func (c *DockerContainer) CopyDirToContainer(ctx context.Context, hostDirPath st
596596
// create the directory under its parent
597597
parent := filepath.Dir(containerParentPath)
598598

599-
err = c.provider.client.CopyToContainer(ctx, c.ID, parent, buff, types.CopyToContainerOptions{})
599+
err = c.provider.client.CopyToContainer(ctx, c.ID, parent, buff, container.CopyToContainerOptions{})
600600
if err != nil {
601601
return err
602602
}
@@ -654,7 +654,7 @@ func (c *DockerContainer) copyToContainer(ctx context.Context, fileContent func(
654654
return err
655655
}
656656

657-
err = c.provider.client.CopyToContainer(ctx, c.ID, "/", buffer, types.CopyToContainerOptions{})
657+
err = c.provider.client.CopyToContainer(ctx, c.ID, "/", buffer, container.CopyToContainerOptions{})
658658
if err != nil {
659659
return err
660660
}
@@ -742,57 +742,59 @@ func (c *DockerContainer) startLogProduction(ctx context.Context, opts ...LogPro
742742
c.logProductionError <- r.Close()
743743
return
744744
default:
745-
h := make([]byte, 8)
746-
_, err := io.ReadFull(r, h)
747-
if err != nil {
748-
// proper type matching requires https://go-review.googlesource.com/c/go/+/250357/ (go 1.16)
749-
if strings.Contains(err.Error(), "use of closed network connection") {
750-
now := time.Now()
751-
since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond()))
752-
goto BEGIN
753-
}
754-
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
755-
// Probably safe to continue here
756-
continue
757-
}
745+
}
746+
h := make([]byte, 8)
747+
_, err := io.ReadFull(r, h)
748+
if err != nil {
749+
switch {
750+
case err == io.EOF:
751+
// No more logs coming
752+
case errors.Is(err, net.ErrClosed):
753+
now := time.Now()
754+
since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond()))
755+
goto BEGIN
756+
case errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled):
757+
// Probably safe to continue here
758+
continue
759+
default:
758760
_, _ = fmt.Fprintf(os.Stderr, "container log error: %+v. %s", err, logStoppedForOutOfSyncMessage)
759761
// if we would continue here, the next header-read will result into random data...
760-
return
761762
}
763+
return
764+
}
762765

763-
count := binary.BigEndian.Uint32(h[4:])
764-
if count == 0 {
765-
continue
766-
}
767-
logType := h[0]
768-
if logType > 2 {
769-
_, _ = fmt.Fprintf(os.Stderr, "received invalid log type: %d", logType)
770-
// sometimes docker returns logType = 3 which is an undocumented log type, so treat it as stdout
771-
logType = 1
772-
}
766+
count := binary.BigEndian.Uint32(h[4:])
767+
if count == 0 {
768+
continue
769+
}
770+
logType := h[0]
771+
if logType > 2 {
772+
_, _ = fmt.Fprintf(os.Stderr, "received invalid log type: %d", logType)
773+
// sometimes docker returns logType = 3 which is an undocumented log type, so treat it as stdout
774+
logType = 1
775+
}
773776

774-
// a map of the log type --> int representation in the header, notice the first is blank, this is stdin, but the go docker client doesn't allow following that in logs
775-
logTypes := []string{"", StdoutLog, StderrLog}
777+
// a map of the log type --> int representation in the header, notice the first is blank, this is stdin, but the go docker client doesn't allow following that in logs
778+
logTypes := []string{"", StdoutLog, StderrLog}
776779

777-
b := make([]byte, count)
778-
_, err = io.ReadFull(r, b)
779-
if err != nil {
780-
// TODO: add-logger: use logger to log out this error
781-
_, _ = fmt.Fprintf(os.Stderr, "error occurred reading log with known length %s", err.Error())
782-
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
783-
// Probably safe to continue here
784-
continue
785-
}
786-
// we can not continue here as the next read most likely will not be the next header
787-
_, _ = fmt.Fprintln(os.Stderr, logStoppedForOutOfSyncMessage)
788-
return
789-
}
790-
for _, c := range c.consumers {
791-
c.Accept(Log{
792-
LogType: logTypes[logType],
793-
Content: b,
794-
})
780+
b := make([]byte, count)
781+
_, err = io.ReadFull(r, b)
782+
if err != nil {
783+
// TODO: add-logger: use logger to log out this error
784+
_, _ = fmt.Fprintf(os.Stderr, "error occurred reading log with known length %s", err.Error())
785+
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
786+
// Probably safe to continue here
787+
continue
795788
}
789+
// we can not continue here as the next read most likely will not be the next header
790+
_, _ = fmt.Fprintln(os.Stderr, logStoppedForOutOfSyncMessage)
791+
return
792+
}
793+
for _, c := range c.consumers {
794+
c.Accept(Log{
795+
LogType: logTypes[logType],
796+
Content: b,
797+
})
796798
}
797799
}
798800
}()
@@ -881,6 +883,9 @@ var _ ContainerProvider = (*DockerProvider)(nil)
881883
// BuildImage will build and image from context and Dockerfile, then return the tag
882884
func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (string, error) {
883885
buildOptions, err := img.BuildOptions()
886+
if err != nil {
887+
return "", err
888+
}
884889

885890
var buildError error
886891
var resp types.ImageBuildResponse
@@ -912,8 +917,7 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st
912917

913918
// need to read the response from Docker, I think otherwise the image
914919
// might not finish building before continuing to execute here
915-
buf := new(bytes.Buffer)
916-
_, err = buf.ReadFrom(resp.Body)
920+
_, err = io.Copy(io.Discard, resp.Body)
917921
if err != nil {
918922
return "", err
919923
}
@@ -1337,7 +1341,7 @@ func (p *DockerProvider) Config() TestcontainersConfig {
13371341

13381342
// DaemonHost gets the host or ip of the Docker daemon where ports are exposed on
13391343
// Warning: this is based on your Docker host setting. Will fail if using an SSH tunnel
1340-
// You can use the "TC_HOST" env variable to set this yourself
1344+
// You can use the "TESTCONTAINERS_HOST_OVERRIDE" env variable to set this yourself
13411345
func (p *DockerProvider) DaemonHost(ctx context.Context) (string, error) {
13421346
return daemonHost(ctx, p)
13431347
}
@@ -1347,7 +1351,7 @@ func daemonHost(ctx context.Context, p *DockerProvider) (string, error) {
13471351
return p.hostCache, nil
13481352
}
13491353

1350-
host, exists := os.LookupEnv("TC_HOST")
1354+
host, exists := os.LookupEnv("TESTCONTAINERS_HOST_OVERRIDE")
13511355
if exists {
13521356
p.hostCache = host
13531357
return p.hostCache, nil
@@ -1405,7 +1409,7 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest)
14051409

14061410
tcConfig := p.Config().Config
14071411

1408-
nc := types.NetworkCreate{
1412+
nc := network.CreateOptions{
14091413
Driver: req.Driver,
14101414
Internal: req.Internal,
14111415
EnableIPv6: req.EnableIPv6,
@@ -1460,12 +1464,12 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest)
14601464
}
14611465

14621466
// GetNetwork returns the object representing the network identified by its name
1463-
func (p *DockerProvider) GetNetwork(ctx context.Context, req NetworkRequest) (types.NetworkResource, error) {
1464-
networkResource, err := p.client.NetworkInspect(ctx, req.Name, types.NetworkInspectOptions{
1467+
func (p *DockerProvider) GetNetwork(ctx context.Context, req NetworkRequest) (network.Inspect, error) {
1468+
networkResource, err := p.client.NetworkInspect(ctx, req.Name, network.InspectOptions{
14651469
Verbose: true,
14661470
})
14671471
if err != nil {
1468-
return types.NetworkResource{}, err
1472+
return network.Inspect{}, err
14691473
}
14701474

14711475
return networkResource, err
@@ -1501,7 +1505,7 @@ func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) {
15011505

15021506
func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APIClient) (string, error) {
15031507
// Get list of available networks
1504-
networkResources, err := cli.NetworkList(ctx, types.NetworkListOptions{})
1508+
networkResources, err := cli.NetworkList(ctx, network.ListOptions{})
15051509
if err != nil {
15061510
return "", err
15071511
}
@@ -1522,7 +1526,7 @@ func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APICl
15221526

15231527
// Create a bridge network for the container communications
15241528
if !reaperNetworkExists {
1525-
_, err = cli.NetworkCreate(ctx, reaperNetwork, types.NetworkCreate{
1529+
_, err = cli.NetworkCreate(ctx, reaperNetwork, network.CreateOptions{
15261530
Driver: Bridge,
15271531
Attachable: true,
15281532
Labels: core.DefaultLabels(core.SessionID()),

docker_client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var (
3131
var _ client.SystemAPIClient = &DockerClient{}
3232

3333
// Events returns a channel to listen to events that happen to the docker daemon.
34-
func (c *DockerClient) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) {
34+
func (c *DockerClient) Events(ctx context.Context, options events.ListOptions) (<-chan events.Message, <-chan error) {
3535
return c.Client.Events(ctx, options)
3636
}
3737

docker_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"github.com/docker/docker/api/types/strslice"
2323
"github.com/docker/docker/client"
2424
"github.com/docker/docker/errdefs"
25-
"github.com/docker/go-units"
2625
"github.com/stretchr/testify/assert"
2726
"github.com/stretchr/testify/require"
2827

@@ -1713,7 +1712,7 @@ func TestDockerContainerResources(t *testing.T) {
17131712

17141713
ctx := context.Background()
17151714

1716-
expected := []*units.Ulimit{
1715+
expected := []*container.Ulimit{
17171716
{
17181717
Name: "memlock",
17191718
Hard: -1,

docs/features/networking.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ It is normally advisable to use `Host` and `MappedPort` together when constructi
4545
<!--/codeinclude-->
4646

4747
!!! info
48-
Setting the `TC_HOST` environment variable overrides the host of the docker daemon where the container port is exposed. For example, `TC_HOST=172.17.0.1`.
48+
Setting the `TESTCONTAINERS_HOST_OVERRIDE` environment variable overrides the host of the docker daemon where the container port is exposed. For example, `TESTCONTAINERS_HOST_OVERRIDE=172.17.0.1`.
4949

5050
## Exposing host ports to the container
5151

docs/system_requirements/using_podman.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
_Testcontainers for Go_ supports the use of Podman (rootless or rootful) instead of Docker.
44

55
In most scenarios no special setup is required in _Testcontainers for Go_.
6-
_Testcontainers for Go_ will automatically discover the socket based on the `DOCKER_HOST` or the `TC_HOST` environment variables.
6+
_Testcontainers for Go_ will automatically discover the socket based on the `DOCKER_HOST` environment variables.
77
Alternatively you can configure the host with a `.testcontainers.properties` file.
88
The discovered Docker host is taken into account when starting a reaper container.
99
The discovered socket is used to detect the use of Podman.

examples/nginx/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ require (
1616
github.com/containerd/errdefs v0.1.0 // indirect
1717
github.com/containerd/log v0.1.0 // indirect
1818
github.com/cpuguy83/dockercfg v0.3.1 // indirect
19-
github.com/distribution/reference v0.5.0 // indirect
20-
github.com/docker/docker v26.1.4+incompatible // indirect
19+
github.com/distribution/reference v0.6.0 // indirect
20+
github.com/docker/docker v27.0.2+incompatible // indirect
2121
github.com/docker/go-connections v0.5.0 // indirect
2222
github.com/docker/go-units v0.5.0 // indirect
2323
github.com/felixge/httpsnoop v1.0.4 // indirect

examples/nginx/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
2323
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2424
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2525
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
26-
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
27-
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
28-
github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU=
29-
github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
26+
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
27+
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
28+
github.com/docker/docker v27.0.2+incompatible h1:mNhCtgXNV1fIRns102grG7rdzIsGGCq1OlOD0KunZos=
29+
github.com/docker/docker v27.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
3030
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
3131
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
3232
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=

examples/toxiproxy/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ require (
2121
github.com/containerd/log v0.1.0 // indirect
2222
github.com/cpuguy83/dockercfg v0.3.1 // indirect
2323
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
24-
github.com/distribution/reference v0.5.0 // indirect
25-
github.com/docker/docker v26.1.4+incompatible // indirect
24+
github.com/distribution/reference v0.6.0 // indirect
25+
github.com/docker/docker v27.0.2+incompatible // indirect
2626
github.com/docker/go-connections v0.5.0 // indirect
2727
github.com/docker/go-units v0.5.0 // indirect
2828
github.com/felixge/httpsnoop v1.0.4 // indirect

examples/toxiproxy/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
2929
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3030
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
3131
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
32-
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
33-
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
34-
github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU=
35-
github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
32+
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
33+
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
34+
github.com/docker/docker v27.0.2+incompatible h1:mNhCtgXNV1fIRns102grG7rdzIsGGCq1OlOD0KunZos=
35+
github.com/docker/docker v27.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
3636
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
3737
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
3838
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=

0 commit comments

Comments
 (0)