testcontainers-go
testcontainers-go copied to clipboard
container.Exec exit code is 1, but the cmd execute well using docker exec directly
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
}
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.
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
? 🤔
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.
@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/
@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 https://github.com/testcontainers/testcontainers-go/issues/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
}
@lsongseven @mozarik did you have time to check the above code snippet?
Closing due to inactivity. Please reopen if needed, thanks!