我有一個 docker 應用程式,它有兩個容器。一個是 MySql,另一個是我使用 Dockerfile 創建的自定義映像的一些邏輯代碼。對于端到端測驗,我希望在資料庫中存盤一些值,然后運行邏輯代碼影像(golang 中的邏輯)。這是我目前擁有的 docker-compose 檔案:
version: '3'
networks:
docker-network:
driver: bridge
services:
database:
image: mysql
env_file:
- ./src/logic/environment-variables.env
ports:
- 3306:3306
healthcheck:
test: "mysql -uroot -p$$MYSQL_ROOT_PASSWORD $$MYSQL_DATABASE -e 'select 1'"
timeout: 20s
retries: 10
network:
docker-network
logic:
container_name: main-logic
build: ./src/logic/.
depends_on:
database:
condition: service_healthy
network:
docker-network
我不能作為一個整體運行這個應用程式,因為它會在資料庫運行時立即運行主程式。相反,我想啟動資料庫,在其中存盤一些值,然后運行邏輯映像。我怎樣才能在測驗方法中做到這一點?
考慮的方法: 與測驗方法分開啟動mysql映像,然后在其中存盤值。然后啟動邏輯映像并檢查資料庫的結果。有沒有更好的方法或框架來使用?
uj5u.com熱心網友回復:
您在這里需要的是資料庫遷移。這應該如下作業:
- 在啟動服務之前啟動資料庫實體。
- 將服務連接到資料庫。
- 在 DB 上運行遷移。
- 繼續執行服務。
考慮一下:https : //github.com/golang-migrate/migrate
uj5u.com熱心網友回復:
您可以完全按照您在問題中所說的去做:啟動資料庫,手動加載種子資料,然后啟動應用程式的其余部分。由于您的資料庫已經發布,ports:您可以直接從主機連接到它,而無需做任何特殊的事情。
docker-compose up -d database
mysql -h 127.0.0.1 < seed_data.sql
docker-compose up -d
@advayrajhansa 的回答建議使用資料庫遷移系統。如果這是內置在您的影像中,您可以docker-compose run logic migrate ...作為中間步驟。這會在您在docker-compose.yml檔案中定義的容器上運行備用命令。
uj5u.com熱心網友回復:
對于您的方法:
- 啟動 MySQL 映像。
- 將資料上傳到資料庫。
- 啟動邏輯映像。
- 檢查資料庫以獲取結果。
你可以:
使用 Makefile
里面有一個 sh 腳本,它將一步一步地執行所有步驟。
生成檔案:
start_test:
docker-compose run -d database
# put here your data uploading script
docker-compose run -d logic
# put here your data database checking script
然后執行
$make start_test # execute all steps
使用Testcontainers-Go
測驗容器 GitHub
Testcontainers-Go 是一個 Go 包,它使得為自動化集成/冒煙測驗創建和清理基于容器的依賴項變得簡單。
它允許您在 go 測驗方法中執行所有步驟。對于你的情況,你會有這樣的事情:
只是一個草稿代碼來趕上這個想法:
package main
import (
"context"
"database/sql"
"fmt"
"github.com/pkg/errors"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
"log"
"testing"
)
var db *sql.DB
func TestIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
err := setupMySql()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
err = setupData()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
err = setupLogic()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
err = checkResult()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
}
func setupMySql() error {
ctx := context.Background()
req := testcontainers.ContainerRequest{
Image: "mysql:latest",
ExposedPorts: []string{"3306/tcp", "33060/tcp"},
Env: map[string]string{
"MYSQL_ROOT_PASSWORD": "secret",
},
WaitingFor: wait.ForLog("port: 3306 MySQL Community Server - GPL"),
}
mysqlC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
defer func() {
err := mysqlC.Terminate(ctx)
if err != nil {
log.Fatal(err)
}
}()
if err != nil {
return errors.Wrap(err, "Failed to run test container")
}
host, err := mysqlC.Host(ctx)
p, err := mysqlC.MappedPort(ctx, "3306/tcp")
port := p.Int()
connectionString := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?tls=skip-verify",
"root", "secret", host, port, "database")
db, err = sql.Open("mysql", connectionString)
defer func(db *sql.DB) {
err := db.Close()
if err != nil {
log.Fatal(err)
}
}(db)
if err != nil {
return errors.Wrap(err, "Failed to connect to db")
}
return nil
}
func setupData() error {
// db.Query(), your code with uploading data
return nil
}
func setupLogic() error {
// run your logic container
return nil
}
func checkResult() error {
// db.Query(), your code with checking result
return nil
}
使用Dockertest
Dockertest 可幫助您以最少的作業為 Go 測驗啟動臨時 docker 鏡像。
與 Testcontainers-Go 相同,
只是一個草稿代碼來趕上這個想法:
package main
import (
"database/sql"
"fmt"
"github.com/ory/dockertest/v3"
"github.com/pkg/errors"
"testing"
)
var db *sql.DB
func TestIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
err := setupMySql()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
err = setupData()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
err = setupLogic()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
err = checkResult()
if err != nil {
t.Errorf("Test failed with error: %s", err)
}
}
func setupMySql() error {
// uses a sensible default on windows (tcp/http) and linux/osx (socket)
pool, err := dockertest.NewPool("")
if err != nil {
return errors.Wrap(err, "Could not connect to docker")
}
// pulls an image, creates a container based on it and runs it
resource, err := pool.Run("mysql", "5.7", []string{"MYSQL_ROOT_PASSWORD=secret"})
if err != nil {
return errors.Wrap(err, "Could not start resource")
}
// exponential backoff-retry, because the application in the container might not be ready to accept connections yet
if err := pool.Retry(func() error {
var err error
db, err = sql.Open("mysql", fmt.Sprintf("root:secret@(localhost:%s)/mysql", resource.GetPort("3306/tcp")))
if err != nil {
return err
}
return db.Ping()
}); err != nil {
return errors.Wrap(err, "Could not connect to database")
}
if err := pool.Purge(resource); err != nil {
return errors.Wrap(err, "Could not purge resource")
}
return nil
}
func setupData() error {
// db.Query(), your code with uploading data
return nil
}
func setupLogic() error {
// run your logic container
return nil
}
func checkResult() error {
// db.Query(), your code with checking result
return nil
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/390042.html
上一篇:當我在docker中運行時嘗試使用postgres在laravel中遷移時,我收到了一個錯誤,例如找不到驅動程式
