Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

container.Exec exit code is 1, but the cmd execute well using docker exec directly #427

Closed
lsongseven opened this issue Apr 13, 2022 · 7 comments

Comments

@lsongseven
Copy link

Start a mysql container, and then to execute some inits, the container.Exec exit code is 1, and the log shows

mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost:3306' (99)

The cmd like ["/bin/bash", "/prepare_data.sh"] , and what in prepare_data.sh is

#!/bin/bash
mysql -hlocalhost -P3306 --protocol=tcp -uroot -pTest1234 < ddl.sql 2>> m.log

here the ddl.sql is very simple

create database xxx;

However, when I type the command in terminal directly like

# assume the containerId is b32cdb7845b3
docker exec b32cdb7845b3 /bin/bash /prepare_data.sh 2>>m.log

it works fine.

I don't know what's wrong, so can anyone help me?

  • code to reproduce
func SetupMysql(ctx context.Context) (*mysqlContainer, error) {
	req := testcontainers.ContainerRequest{
		Image:        "mysql:8.0",
		ExposedPorts: []string{"3306/tcp"},
		WaitingFor:   wait.ForLog("MySQL init process done. Ready for start up."),
		Env: map[string]string{
			"MYSQL_ROOT_PASSWORD": "Test1234",
		},
	}

	container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
		ContainerRequest: req,
		Started:          true,
	})

	if err != nil {
		return nil, err
	}

	err = containerInit(ctx, container)

	if err != nil {
		return nil, err
	}

	mappedPort, err := container.MappedPort(ctx, "3306")
	if err != nil {
		return nil, err
	}

	hostIP, err := container.Host(ctx)
	if err != nil {
		return nil, err
	}

	serverIpPort := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port())

	dsn := fmt.Sprintf("root:Test1234@tcp(%s)/life_goods_frontend?charset=utf8mb4&parseTime=True&loc=Local", serverIpPort)

	return &mysqlContainer{
		Container: container,
		DSN:       dsn,
	}, nil
}


func containerInit(ctx context.Context, container testcontainers.Container) error {
	pwd, _ := os.Getwd()

	hostFilePath := pwd + "/../data/prepare_data.sh"
	containerFilePath := "/prepare_data.sh"

	err := container.CopyFileToContainer(ctx, hostFilePath, containerFilePath, 0777)
	if err != nil {
		return err
	}

	hostFilePath = pwd + "/../data/ddl.sql"
	containerFilePath = "/ddl.sql"

	err = container.CopyFileToContainer(ctx, hostFilePath, containerFilePath, 0777)
	if err != nil {
		return err
	}

	cmds := []string{"/bin/bash", "/prepare_data.sh"}
	fmt.Println(cmds)
	exitCode, err := container.Exec(ctx, cmds)
	if err != nil {
		return err
	}
	fmt.Printf("exitCode=%+v\n", exitCode)
	return nil
}
@lsongseven lsongseven changed the title container.Exec exit code is 1, but the cmd exect well using docker exec directly container.Exec exit code is 1, but the cmd execute well using docker exec directly Apr 13, 2022
@mdelapenya
Copy link
Collaborator

Hi @lsongseven thanks for opening this issue, although I think this kind of questions fits more in the Slack channel :)

Have you tried to mount the preparation script into the docker container before it's run? https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/docker-mysql-more-topics.html#docker-additional-init. The official MySQL image should run your .SH/.SQL files for you first.

@lsongseven
Copy link
Author

lsongseven commented Apr 13, 2022

Hi @lsongseven thanks for opening this issue, although I think this kind of questions fits more in the Slack channel :)

Have you tried to mount the preparation script into the docker container before it's run? https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/docker-mysql-more-topics.html#docker-additional-init. The official MySQL image should run your .SH/.SQL files for you first.

Sorry about not-int-slack-channel @mdelapenya .

Mount preparation scripts works, but can you explain the difference between container.Exec and docker exec ? 🤔

@mozarik
Copy link

mozarik commented Jul 8, 2022

Yep same as me using docker exec and exec directly when in '-it' mode work. But testcontainers dont.

The thing that i want to run is pubsub emulator.

So the last thing that i do to satisfy my need is to used custom docker image.

@mdelapenya
Copy link
Collaborator

@mozarik

The thing that i want to run is pubsub emulator.

Have you checked out the pubsub example code? https://golang.testcontainers.org/examples/pubsub/

@mdelapenya
Copy link
Collaborator

@lsongseven sorry for the radio silence, at that time I was changing jobs and did not notice this issue to be stacked into our issues 🤦

I'm not able to reproduce your scenario, using latest version of the Exec method, which is able to receive a Multiplexed options to remove the garbage suffix prepended by Docker (see #624)

package mysql

import (
	"context"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/testcontainers/testcontainers-go"
	tcexec "github.com/testcontainers/testcontainers-go/exec"
	"github.com/testcontainers/testcontainers-go/wait"
)

func SetupMysql(ctx context.Context) (*mysqlContainer, error) {
	req := testcontainers.ContainerRequest{
		Image:        "mysql:8.0",
		ExposedPorts: []string{"3306/tcp"},
		WaitingFor:   wait.ForLog("MySQL init process done. Ready for start up."),
		Env: map[string]string{
			"MYSQL_ROOT_PASSWORD": "Test1234",
		},
	}

	container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
		ContainerRequest: req,
		Started:          true,
	})

	if err != nil {
		return nil, err
	}

	err = containerInit(ctx, container)

	if err != nil {
		return nil, err
	}

	mappedPort, err := container.MappedPort(ctx, "3306")
	if err != nil {
		return nil, err
	}

	hostIP, err := container.Host(ctx)
	if err != nil {
		return nil, err
	}

	serverIpPort := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port())

	dsn := fmt.Sprintf("root:Test1234@tcp(%s)/life_goods_frontend?charset=utf8mb4&parseTime=True&loc=Local", serverIpPort)

	return &mysqlContainer{
		Container: container,
		DSN:       dsn,
	}, nil
}

func containerInit(ctx context.Context, container testcontainers.Container) error {
	pwd, _ := os.Getwd()

	hostFilePath := filepath.Join(pwd, "testresources", "prepare_data.sh")
	containerFilePath := "/prepare_data.sh"

	err := container.CopyFileToContainer(ctx, hostFilePath, containerFilePath, 0777)
	if err != nil {
		return err
	}

	hostFilePath = filepath.Join(pwd, "testresources", "ddl.sql")
	containerFilePath = "/ddl.sql"

	err = container.CopyFileToContainer(ctx, hostFilePath, containerFilePath, 0777)
	if err != nil {
		return err
	}

	cmds := []string{"/bin/bash", "/prepare_data.sh"}
	fmt.Println(cmds)
	exitCode, reader, err := container.Exec(ctx, cmds, tcexec.Multiplexed())
	if err != nil {
		return err
	}
	fmt.Printf("exitCode=%+v\n", exitCode)

	b, err := io.ReadAll(reader)
	str := string(b)
	fmt.Printf("str=%+v\n", str)
	return nil
}

@mdelapenya
Copy link
Collaborator

@lsongseven @mozarik did you have time to check the above code snippet?

@mdelapenya
Copy link
Collaborator

Closing due to inactivity. Please reopen if needed, thanks!

@mdelapenya mdelapenya closed this as not planned Won't fix, can't repro, duplicate, stale Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants