You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:13:19