使用testcontainers-go构建容器失败:镜像不存在及空指针异常
问题
初次使用testcontainers-go库时,构建容器时报错Error response from daemon: No such image,随后触发空指针解引用panic。代码与官方文档示例基本一致,且通过docker build命令行能正常构建镜像,具体信息如下:
报错信息
testcontainers_test.go:25: Error response from daemon: No such image: d79b11e4-647c-4064-9e6f-94a626c9287d:964a49e9-0b99-42f5-acba-851d95792857: failed to create container --- FAIL: TestWithRedis (23.00s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0xe0 pc=0x8d6731]
相关代码
package xx import ( "context" "testing" "github.com/testcontainers/testcontainers-go" ) var token = "xxx" var customVersion = "v1.11" var http_proxy = "xxx" var https_proxy = "xxx" var no_proxy = "xxx" func TestWithRedis(t *testing.T) { ctx := context.Background() req := testcontainers.ContainerRequest{FromDockerfile: testcontainers.FromDockerfile{ Context: "/home/usr/project", // this is where I have my Dockerfile Dockerfile: "Dockerfile", BuildArgs: map[string]*string{ "TOKEN": &token, "CUSTOM_VERSION": &customVersion, "http_proxy": &http_proxy, "https_proxy": &https_proxy, "no_proxy": &no_proxy, }, }, } redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, ProviderType: 0, Logger: nil, Reuse: false, }) if err != nil { t.Error(err) // this is line 25 where the error from above refers to } defer func() { if err := redisC.Terminate(ctx); err != nil { t.Fatalf("failed to terminate container: %s", err.Error()) } }() }
命令行构建命令
docker build --pull --build-arg TOKEN="xxx" --build-arg CUSTOM_VERSION="v1.11" --build-arg http_proxy --build-arg https_proxy --build-arg no_proxy .
问题原因与解决办法
1. 空指针panic的直接修复
当GenericContainer调用失败返回错误时,redisC会是nil,但后续defer函数仍尝试调用redisC.Terminate(ctx),对空指针调用方法直接触发panic。
修复代码:将defer移到错误判断之后,确保只有容器创建成功时才执行终止操作:
redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, ProviderType: 0, Logger: nil, Reuse: false, }) if err != nil { t.Error(err) return // 提前返回,避免后续空指针操作 } // 仅在容器创建成功后注册终止逻辑 defer func() { if err := redisC.Terminate(ctx); err != nil { t.Fatalf("failed to terminate container: %s", err.Error()) } }()
2. 镜像构建失败的核心原因
报错中的随机ID镜像名说明testcontainers-go构建镜像未成功,结合命令行能正常构建的情况,问题出在构建参数传递差异:
- 命令行中
--build-arg http_proxy是直接传递系统环境变量的值,但代码中你硬编码了http_proxy变量为"xxx",可能和实际需要的代理值不符 - 检查
Context路径是否为绝对路径且正确,确保Dockerfile存在于该目录下 - 确认
BuildArgs的键名与Dockerfile中的ARG指令完全一致(大小写敏感)
优化构建参数传递:如果需要使用系统环境变量中的代理值,直接从环境变量读取:
import "os" // ... token := os.Getenv("TOKEN") customVersion := "v1.11" http_proxy := os.Getenv("http_proxy") https_proxy := os.Getenv("https_proxy") no_proxy := os.Getenv("no_proxy")
3. 排查构建细节的额外建议
开启testcontainers-go的日志输出,查看镜像构建过程中的具体错误:
redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, ProviderType: 0, Logger: testcontainers.DefaultLogger, // 开启默认日志 Reuse: false, })
内容的提问来源于stack exchange,提问作者Robert Kwiatkowski
相关产品推荐
相关产品推荐

