You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by GitBox <gi...@apache.org> on 2021/06/14 08:08:26 UTC

[GitHub] [skywalking-infra-e2e] mrproliu opened a new pull request #19: Support docker compose

mrproliu opened a new pull request #19:
URL: https://github.com/apache/skywalking-infra-e2e/pull/19


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [skywalking-infra-e2e] mrproliu commented on a change in pull request #19: Support docker compose

Posted by GitBox <gi...@apache.org>.
mrproliu commented on a change in pull request #19:
URL: https://github.com/apache/skywalking-infra-e2e/pull/19#discussion_r657860448



##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       > A new release has been pushed, fixing this. Hope it helps!
   
   Wow, thx a lot. I will continue to work on this. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [skywalking-infra-e2e] mdelapenya commented on a change in pull request #19: Support docker compose

Posted by GitBox <gi...@apache.org>.
mdelapenya commented on a change in pull request #19:
URL: https://github.com/apache/skywalking-infra-e2e/pull/19#discussion_r657854828



##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       A new release has been pushed, fixing this. Hope it helps!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [skywalking-infra-e2e] kezhenxu94 merged pull request #19: Support docker compose

Posted by GitBox <gi...@apache.org>.
kezhenxu94 merged pull request #19:
URL: https://github.com/apache/skywalking-infra-e2e/pull/19


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [skywalking-infra-e2e] kezhenxu94 commented on a change in pull request #19: Support docker compose

Posted by GitBox <gi...@apache.org>.
kezhenxu94 commented on a change in pull request #19:
URL: https://github.com/apache/skywalking-infra-e2e/pull/19#discussion_r650606046



##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export
+				err := waitTCPPortStarted(context.Background(), cli, container, int(containerPort.PublicPort), int(containerPort.PrivatePort), waitTimeout)
+				if err != nil {
+					return fmt.Errorf("could wait port exported: %s:%d, %v", service, portList[inx], err)
+				}
+
+				// expose env config to env
+				envKey := fmt.Sprintf("e2e_host_and_port_%s_%d", service, containerPort.PrivatePort)
+				envValue := fmt.Sprintf("127.0.0.1:%d", containerPort.PublicPort)
+				err = os.Setenv(envKey, envValue)
+				if err != nil {
+					return fmt.Errorf("could not setting env for %s:%d, %v", service, portList[inx], err)

Review comment:
       ```suggestion
   					return fmt.Errorf("could not set env for %s:%d, %v", service, portList[inx], err)
   ```

##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       We don't need to wait and export, just exporting it is OK, the healthiness check should be done by `docker-compose.yml`, because the healthiness check should only make sense by the one who write `docker-compose.yml`, we can cover every possibility of how to check healthiness.

##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export
+				err := waitTCPPortStarted(context.Background(), cli, container, int(containerPort.PublicPort), int(containerPort.PrivatePort), waitTimeout)
+				if err != nil {
+					return fmt.Errorf("could wait port exported: %s:%d, %v", service, portList[inx], err)
+				}
+
+				// expose env config to env
+				envKey := fmt.Sprintf("e2e_host_and_port_%s_%d", service, containerPort.PrivatePort)

Review comment:
       Let's only expose the port as env var `<SERVICE_NAME>_PORT`, because the host is not necessarily always 127.0.0.1, so that user can use something like `localhost:${WEBAPP_PORT}` as the url of trigger

##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       OK, it makes sense to me, can you reuse `compose.WithExposedService(service, port, wait.ForListeningPort("<port>/tcp"))` to replace `waitTCPPortStarted` so that we don't replicate the codes? Others generally look good to me, thanks again ❤️ 

##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       Thanks for the information, can you paste the related issue / PR here?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [skywalking-infra-e2e] mrproliu commented on a change in pull request #19: Support docker compose

Posted by GitBox <gi...@apache.org>.
mrproliu commented on a change in pull request #19:
URL: https://github.com/apache/skywalking-infra-e2e/pull/19#discussion_r650646907



##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       Sure, but the `healthcheck` is only working on the service that has `depends_on`. If we need to use `webapp` service on `trigger` or `query`, it hasn't service dependent on this, so we may not access it. Do I miss anything?

##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       I have tried `compose.WithExposedService(service, port, wait.ForListeningPort("<port>/tcp"))` method, but currently the second parameter only supports the specified port, so we cannot use it. This error has already been reported and a new PR has been created. I will pay attention to the next release version of the `testcontainers-go` project. If this bug is fixed, I will use it.

##########
File path: internal/components/setup/compose.go
##########
@@ -17,3 +17,212 @@
 //
 
 package setup
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"regexp"
+	"syscall"
+	"time"
+
+	"github.com/apache/skywalking-infra-e2e/internal/config"
+	"github.com/apache/skywalking-infra-e2e/internal/constant"
+	"github.com/apache/skywalking-infra-e2e/internal/logger"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+// ComposeSetup sets up environment according to e2e.yaml.
+func ComposeSetup(e2eConfig *config.E2EConfig) error {
+	composeConfigPath := e2eConfig.Setup.GetFile()
+	if composeConfigPath == "" {
+		return fmt.Errorf("no compose config file was provided")
+	}
+
+	// build docker client
+	cli, err := client.NewClientWithOpts(client.FromEnv)
+	if err != nil {
+		return err
+	}
+
+	// setup docker compose
+	composeFilePaths := []string{
+		composeConfigPath,
+	}
+	identifier := GetIdentity()
+	compose := testcontainers.NewLocalDockerCompose(composeFilePaths, identifier)
+	execError := compose.WithCommand([]string{"up", "-d"}).Invoke()
+	if execError.Error != nil {
+		return execError.Error
+	}
+
+	// record time now
+	timeNow := time.Now()
+	timeout := e2eConfig.Setup.Timeout
+	var waitTimeout time.Duration
+	if timeout <= 0 {
+		waitTimeout = constant.DefaultWaitTimeout
+	} else {
+		waitTimeout = time.Duration(timeout) * time.Second
+	}
+	logger.Log.Debugf("wait timeout is %d seconds", int(waitTimeout.Seconds()))
+
+	// find exported port and build env
+	for service, content := range compose.Services {
+		serviceConfig := content.(map[interface{}]interface{})
+		ports := serviceConfig["ports"]
+		if ports == nil {
+			continue
+		}
+		portList := ports.([]interface{})
+		container, err := findContainer(cli, fmt.Sprintf("%s_%s", identifier, getInstanceName(service)))
+		if err != nil {
+			return err
+		}
+		containerPorts := container.Ports
+
+		for inx := range portList {
+			for _, containerPort := range containerPorts {
+				if int(containerPort.PrivatePort) != portList[inx].(int) {
+					continue
+				}
+
+				// calculate max wait time
+				waitTimeout = NewTimeout(timeNow, waitTimeout)
+				timeNow = time.Now()
+
+				// wait port and export

Review comment:
       Sorry I forget. here: https://github.com/testcontainers/testcontainers-go/pull/330 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org