Maison > développement back-end > Golang > le corps du texte

Conteneurs de test Golang, impossible de faire fonctionner le réseau

WBOY
Libérer: 2024-02-14 13:30:09
avant
1065 Les gens l'ont consulté

Golang testcontainers,无法使网络工作

l'éditeur php Strawberry a rencontré un problème lors de l'utilisation des conteneurs de test Golang, c'est-à-dire qu'il n'a pas pu faire fonctionner le réseau correctement. Golang testcontainers est un outil permettant d'exécuter des conteneurs dans des tests, qui aide les développeurs à démarrer et à détruire rapidement des conteneurs dans un environnement de test. Cependant, en utilisation réelle, l'éditeur PHP Strawberry a constaté que la fonction réseau ne pouvait pas être utilisée normalement dans le conteneur, ce qui a provoqué certains problèmes lors du test. Ensuite, nous explorerons ensemble la solution à ce problème.

Contenu de la question

J'essaie de créer des tests dans mon microservice et je souhaite créer un réseau auquel j'attacherai mon conteneur de test de base de données (postgres) et mon conteneur de test de microservice. Peu importe ce que j'essaie, je n'arrive pas à connecter mon microservice à la base de données. Mon microservice est Golang utilisant Fiber et Gorm. J'essaie de me connecter à la base de données dans le fichier de configuration db.go comme ceci :

func SetupDB(port string, host string) *gorm.DB {

    dsn := "host=" + host + " user=postgres password=password dbname=prescription port=" + port + " sslmode=disable"

    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})

    if err != nil {
        panic("error connecting to database")
    }

    db.AutoMigrate(&model.Prescription{})

    return db
}
Copier après la connexion

Voici à quoi ressemble mon conteneur de test :

prescriptionDBContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
        ContainerRequest: testcontainers.ContainerRequest{
            Image:        "postgres",
            ExposedPorts: []string{postgresPort.Port()},
            Env: map[string]string{
                "POSTGRES_USER":     "postgres",
                "POSTGRES_PASSWORD": "password",
                "POSTGRES_DB":       "prescription",
            },
            Networks: []string{network.Name},
            NetworkAliases: map[string][]string{
                network.Name: {"db-network"},
            },
            WaitingFor: wait.ForAll(
                wait.ForLog("database system is ready to accept connections"),
                wait.ForListeningPort(postgresPort),
            ),
        },
        Started: true,
    })
Copier après la connexion
prescriptionContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
        ContainerRequest: testcontainers.ContainerRequest{
            FromDockerfile: testcontainers.FromDockerfile{Context: "../../../../prescription"},
            Networks:       []string{network.Name},
            NetworkAliases: map[string][]string{
                network.Name: {"db-network"},
            },
            Env: map[string]string{
                "POSTGRES_USER":     "postgres",
                "POSTGRES_PASSWORD": "password",
                "POSTGRES_DB":       "prescription",
                "HOST":              prescriptionDBHost,
                "DB_PORT":           prescriptionDBPort.Port(),
            },
            ExposedPorts: []string{pMicroPort.Port()},
            WaitingFor:   wait.ForListeningPort("8080"),
        },
        Started: true,
    })
Copier après la connexion

C'est peut-être parce que je ne comprends tout simplement pas ce qui se passe pendant le processus de connexion réseau dans Docker, mais je suis vraiment perdu et lorsque j'ai configuré l'environnement pour HOST et DB_PORT (j'ai essayé toutes les combinaisons sous le soleil), il refuse les microservices connectés à la base de données

Dans le conteneur de test du microservice j'ai essayé :

"HOST":              prescriptionDBHost,
"DB_PORT":           prescriptionDBPort.Port(),
Copier après la connexion
La méthode d'extraction de

prescriptionDBHost est :

prescriptionDBHost, err := prescriptionDBContainer.Name(context.Background())
Copier après la connexion

entraîne le message d'erreur : 

failed to initialize database, got error failed to connect to `host=/stoic_heyrovsky user=postgres database=prescription`: dial error (dial unix /stoic_heyrovsky/.s.PGSQL.53802: connect: no such file or directory)
panic: error connecting to database
Copier après la connexion

Ensuite, j'ai essayé de supprimer le "/" du nom d'hôte, par exemple :

"HOST":              strings.Trim(prescriptionDBHost,"/"),
"DB_PORT":           prescriptionDBPort.Port(),
Copier après la connexion

J'ai aussi essayé :

"HOST":              "localhost",
"DB_PORT":           prescriptionDBPort.Port(),
Copier après la connexion
"HOST":              "127.0.0.1",
"DB_PORT":           prescriptionDBPort.Port(),
Copier après la connexion
prescriptionDBHost, err := prescriptionDBContainer.ContainerIP(context.Background())

"HOST":              prescriptionDBHost,
"DB_PORT":           prescriptionDBPort.Port(),
Copier après la connexion

Les 4 derniers exemples ici entraînent tous une sorte d'erreur TCP de connexion, par exemple :

failed to initialize database, got error failed to connect to `host=localhost user=postgres database=prescription`: dial error (dial tcp [::1]:53921: connect: cannot assign requested address)
Copier après la connexion

J'ai également débogué et arrêté le testcontainer après avoir créé le conteneur de base de données, puis je suis allé sur mon microservice et j'ai codé en dur une connexion au conteneur avec DB_HOST=localhost et port= et cela a fonctionné, donc je suis vraiment perdu sur ce qui se passe. Quelque chose ne va pas . La seule chose à laquelle je peux penser est que le conteneur de microservices n'est pas connecté au réseau avant d'essayer de se connecter à la base de données ? J'ai effectué une vérification du réseau Docker et je peux voir que le conteneur de base de données est attaché, mais le microservice ne s'attache jamais (mais peut-être est-ce juste pour d'autres raisons ?).

Solution

Vous pouvez faire ceci :

prescriptionDBContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
    ContainerRequest: testcontainers.ContainerRequest{
        Image:        "postgres",
        ExposedPorts: []string{"5432/tcp"},
        Env: map[string]string{
            "POSTGRES_USER":     "postgres",
            "POSTGRES_PASSWORD": "password",
            "POSTGRES_DB":       "prescription",
        },
        Networks:       []string{networkName},
        NetworkAliases: map[string][]string{networkName: []string{"postgres"}},
        WaitingFor: wait.ForAll(
            wait.ForLog("database system is ready to accept connections"),
            wait.ForListeningPort("5432/tcp"),
        ),
    },
    Started: true,
})
if err != nil {
    t.Fatal(err)
}

prescriptionContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
    ContainerRequest: testcontainers.ContainerRequest{
        FromDockerfile: testcontainers.FromDockerfile{Context: "./testapp"},
        ExposedPorts:   []string{"8080/tcp"},
        Networks:       []string{networkName},
        NetworkAliases: map[string][]string{networkName: []string{"blah"}},
        Env: map[string]string{
            "DATABASE_URL": "postgres://postgres:password@postgres:5432/prescription",
        },
        WaitingFor: wait.ForListeningPort("8080/tcp"),
    },
    Started: true,
})
Copier après la connexion

AttentionNetworkAliases的配置方式;在您的代码中,您将两者都设置为 db-network 但是,我想,这是由于误解。该设置配置了一个可以引用容器的别名(在本例中,我使用 postgres 作为 postgres 容器;这意味着当连接 HOST 时,根据上面示例中使用的 URL,postgres 将是 postgres).

Comme alternative, vous pouvez utiliser le port, err :=处方DBContainer.MappedPort(context.Background(), "5432/tcp") 获取主机上公开的端口,然后连接到端口上的 host.docker.internal port.Port().当被测试的应用程序在主机上而不是在容器中运行时,经常使用此方法(但在这种情况下,您将连接到 localhost 并使用从 MappedPort()rapport renvoyé).

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal