From f0b85c5b76db6e1e7bcec0c645110d6bbd9bc56b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 3 Nov 2022 18:53:02 +0100 Subject: [PATCH 1/3] docs: basic networking --- docker_test.go | 15 +++++++++- docs/features/networking.md | 56 +++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 docs/features/networking.md diff --git a/docker_test.go b/docker_test.go index c8f5e58fe1..f051c36eb5 100644 --- a/docker_test.go +++ b/docker_test.go @@ -5,8 +5,8 @@ import ( "database/sql" "errors" "fmt" + // Import mysql into the scope of this package (required) - _ "github.com/go-sql-driver/mysql" "io" "io/ioutil" "math/rand" @@ -18,6 +18,8 @@ import ( "testing" "time" + _ "github.com/go-sql-driver/mysql" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/strslice" "github.com/docker/go-units" @@ -54,6 +56,7 @@ func init() { } } +// testNetworkAliases { func TestContainerAttachedToNewNetwork(t *testing.T) { aliases := []string{"alias1", "alias2", "alias3"} networkName := "new-network" @@ -131,6 +134,8 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { } } +// } + func TestContainerWithHostNetworkOptions(t *testing.T) { absPath, err := filepath.Abs("./testresources/nginx-highport.conf") if err != nil { @@ -981,6 +986,7 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { } func TestContainerCreationWaitsForLog(t *testing.T) { + // exposePorts { ctx := context.Background() req := ContainerRequest{ Image: "docker.io/mysql:latest", @@ -996,13 +1002,18 @@ func TestContainerCreationWaitsForLog(t *testing.T) { ContainerRequest: req, Started: true, }) + // } require.NoError(t, err) terminateContainerOnEnd(t, ctx, mysqlC) + // containerHost { host, _ := mysqlC.Host(ctx) + // } + // mappedPort { p, _ := mysqlC.MappedPort(ctx, "3306/tcp") port := p.Int() + // } connectionString := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?tls=skip-verify", "root", "password", host, port, "database") @@ -1368,6 +1379,7 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { require.NoError(t, err) terminateContainerOnEnd(t, ctx, mysqlC) + // buildingAddresses { host, _ := mysqlC.Host(ctx) p, _ := mysqlC.MappedPort(ctx, "3306/tcp") port := p.Int() @@ -1378,6 +1390,7 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { if err != nil { t.Fatal(err) } + // } defer db.Close() diff --git a/docs/features/networking.md b/docs/features/networking.md new file mode 100644 index 0000000000..0b7e9cfb63 --- /dev/null +++ b/docs/features/networking.md @@ -0,0 +1,56 @@ +# Networking and communicating with containers + +## Exposing container ports to the host + +It is common to want to connect to a container from your test process, running on the test 'host' machine. +For example, you may be testing some code that needs to connect to a backend or data store container. + +Generally, each required port needs to be explicitly exposed. For example, we can specify one or more ports as follows: + + +[Exposing ports](../../docker_test.go) inside_block:exposePorts + + +Note that this exposed port number is from the *perspective of the container*. + +*From the host's perspective* Testcontainers actually exposes this on a random free port. +This is by design, to avoid port collisions that may arise with locally running software or in between parallel test runs. + +Because there is this layer of indirection, it is necessary to ask Testcontainers for the actual mapped port at runtime. +This can be done using the `getMappedPort` method, which takes the original (container) port as an argument: + + +[Retrieving actual ports at runtime](../../docker_test.go) inside_block:mappedPort + + +!!! warning + Because the randomised port mapping happens during container startup, the container must be running at the time `MappedPort` is called. + You may need to ensure that the startup order of components in your tests caters for this. + +## Getting the container host + +When running with a local Docker daemon, exposed ports will usually be reachable on `localhost`. +However, in some CI environments they may instead be reachable on a different host. + +As such, Testcontainers provides a convenience method to obtain an address on which the container should be reachable from the host machine. + + +[Getting the container host](../../docker_test.go) inside_block:containerHost + + +It is normally advisable to use `Host` and `MappedPort` together when constructing addresses - for example: + + +[Getting the container host and mapped port](../../docker_test.go) inside_block:buildingAddresses + + +## Advanced networking + +Docker provides the ability for you to create custom networks and place containers on one or more networks. Then, communication can occur between networked containers without the need of exposing ports through the host. With Testcontainers, you can do this as well. + +!!! tip + Note that _Testcontainers for Go_ allows a container to be on multiple networks including network aliases. + + +[Creating custom networks](../../docker_test.go) inside_block:testNetworkAliases + diff --git a/mkdocs.yml b/mkdocs.yml index 0c7fa8ef56..4283d8d990 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,6 +30,7 @@ nav: - quickstart/gotest.md - Features: - features/creating_container.md + - features/networking.md - features/garbage_collector.md - features/build_from_dockerfile.md - features/docker_compose.md From f1b5c091c95e3f0be932c2a6bab0591eb56e504c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 4 Nov 2022 10:12:11 +0100 Subject: [PATCH 2/3] fix: use function instead Co-authored-by: Kevin Wittek --- docs/features/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/networking.md b/docs/features/networking.md index 0b7e9cfb63..e4e92f4766 100644 --- a/docs/features/networking.md +++ b/docs/features/networking.md @@ -17,7 +17,7 @@ Note that this exposed port number is from the *perspective of the container*. This is by design, to avoid port collisions that may arise with locally running software or in between parallel test runs. Because there is this layer of indirection, it is necessary to ask Testcontainers for the actual mapped port at runtime. -This can be done using the `getMappedPort` method, which takes the original (container) port as an argument: +This can be done using the `MappedPort` function, which takes the original (container) port as an argument: [Retrieving actual ports at runtime](../../docker_test.go) inside_block:mappedPort From e0971dc96619dd65e17cdc6c1477435cf15c6a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 4 Nov 2022 10:14:07 +0100 Subject: [PATCH 3/3] fix: more function --- docs/features/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/networking.md b/docs/features/networking.md index e4e92f4766..bee2f0f0ad 100644 --- a/docs/features/networking.md +++ b/docs/features/networking.md @@ -32,7 +32,7 @@ This can be done using the `MappedPort` function, which takes the original (cont When running with a local Docker daemon, exposed ports will usually be reachable on `localhost`. However, in some CI environments they may instead be reachable on a different host. -As such, Testcontainers provides a convenience method to obtain an address on which the container should be reachable from the host machine. +As such, Testcontainers provides a convenience function to obtain an address on which the container should be reachable from the host machine. [Getting the container host](../../docker_test.go) inside_block:containerHost