Heim  >  Artikel  >  Backend-Entwicklung  >  Golang-Testcontainer, das Netzwerk funktioniert nicht

Golang-Testcontainer, das Netzwerk funktioniert nicht

WBOY
WBOYnach vorne
2024-02-14 13:30:091060Durchsuche

Golang testcontainers,无法使网络工作

Der PHP-Editor Strawberry hat bei der Verwendung von Golang-Testcontainern ein Problem festgestellt, das heißt, das Netzwerk konnte nicht ordnungsgemäß funktionieren. Golang testcontainers ist ein Tool zum Ausführen von Containern in Tests, das Entwicklern hilft, Container in einer Testumgebung schnell zu starten und zu zerstören. Bei der tatsächlichen Verwendung stellte der PHP-Editor Strawberry jedoch fest, dass die Netzwerkfunktion im Container nicht normal verwendet werden konnte, was im Test zu bestimmten Problemen führte. Als nächstes werden wir gemeinsam die Lösung für dieses Problem erforschen.

Frageninhalt

Ich versuche, einige Tests in meinem Microservice zu erstellen und möchte ein Netzwerk erstellen, an das ich meinen Datenbank-Testcontainer (Postgres) und meinen Microservice-Testcontainer anhängen werde. Egal was ich versuche, ich kann meinen Microservice nicht dazu bringen, eine Verbindung zur Datenbank herzustellen. Mein Mikroservice ist Golang und verwendet Fibre und Gorm. Ich versuche, eine Verbindung zur Datenbank in der db.go-Konfigurationsdatei wie folgt herzustellen:

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
}

So sieht mein Testcontainer aus:

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,
    })
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,
    })

Vielleicht liegt es daran, dass ich einfach nicht verstehe, was während des Netzwerkverbindungsprozesses in Docker vor sich geht, aber ich bin wirklich verloren und als ich die Umgebung für HOST und DB_PORT einrichte (ich habe jede Kombination unter der Sonne ausprobiert), Es lehnt Microservices ab, die mit der Datenbank verbunden sind

Im Testcontainer des Microservices habe ich versucht:

"HOST":              prescriptionDBHost,
"DB_PORT":           prescriptionDBPort.Port(),
Die Extraktionsmethode von

prescriptionDBHost ist:

prescriptionDBHost, err := prescriptionDBContainer.Name(context.Background())

führt zur Fehlermeldung:

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

Dann habe ich versucht, das „/“ aus dem Hostnamen zu entfernen, zum Beispiel:

"HOST":              strings.Trim(prescriptionDBHost,"/"),
"DB_PORT":           prescriptionDBPort.Port(),

Ich habe es auch versucht:

"HOST":              "localhost",
"DB_PORT":           prescriptionDBPort.Port(),
"HOST":              "127.0.0.1",
"DB_PORT":           prescriptionDBPort.Port(),
prescriptionDBHost, err := prescriptionDBContainer.ContainerIP(context.Background())

"HOST":              prescriptionDBHost,
"DB_PORT":           prescriptionDBPort.Port(),

Die letzten 4 Beispiele hier führen alle zu einer Art TCP-Einwahlfehler, zum Beispiel:

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)

Ich habe auch den Testcontainer debuggt und gestoppt, nachdem ich den Datenbankcontainer erstellt hatte, bin dann zu meinem Microservice gegangen und habe eine Verbindung zum Container mit DB_HOST=localhost und port= fest codiert und es hat funktioniert, sodass ich wirklich nicht weiß, was los ist. Etwas stimmt nicht . Das Einzige, was mir einfällt, ist, dass der Microservice-Container nicht mit dem Netzwerk verbunden ist, bevor versucht wird, eine Verbindung zur Datenbank herzustellen? Ich habe eine Docker-Netzwerkprüfung durchgeführt und kann sehen, dass der Datenbankcontainer angehängt ist, der Microservice jedoch nie angehängt wird (aber vielleicht hat das nur andere Gründe?).

Lösung

Sie können dies tun:

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,
})

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

Alternativ können Sie auch den port, err :=处方DBContainer.MappedPort(context.Background(), "5432/tcp") 获取主机上公开的端口,然后连接到端口上的 host.docker.internal port.Port().当被测试的应用程序在主机上而不是在容器中运行时,经常使用此方法(但在这种情况下,您将连接到 localhost 并使用从 MappedPort()Retourenbericht nutzen.

Das obige ist der detaillierte Inhalt vonGolang-Testcontainer, das Netzwerk funktioniert nicht. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen