twerpiebird
twerpiebird

Reputation: 21

Why can't I push an image to a local Docker registry started with Testcontainers?

I'm trying to create a local Docker registry using Testcontainers and push an image programatically to it. However, I'm getting a connection refused error when attempting to push the image. The first test which checks if the registry is running works, so i know the registry is running.

Here’s my test class:

class DockerRegistryTest {

    @Rule
    public static GenericContainer registry;
    private static String registryAddress;
    private static DockerClient dockerClient;

    @BeforeAll
    static void startRegistry() {
        registry = new GenericContainer(DockerImageName.parse("registry:2"))
                .withExposedPorts(5000)
                .waitingFor(Wait.forHttp("/v2/").forStatusCode(200));

        registry.start();
        assertTrue(registry.isRunning(), "Registry is running");

        registryAddress = registry.getHost() + ":" + registry.getMappedPort(5000);
        System.out.println("Registry available at: " + registryAddress);

        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder().build();
        dockerClient = DockerClientImpl.getInstance(config, new ApacheDockerHttpClient.Builder()
                .dockerHost(config.getDockerHost())
                .sslConfig(config.getSSLConfig())
                .build());
    }

    @AfterAll
    static void tearDown() {
        if (registry != null) {
            registry.stop();
        }
    }

    @Test
    void testPushImageToRegistry() throws InterruptedException {
        String localImage = "busybox:latest";
        dockerClient.pullImageCmd(localImage).start().awaitCompletion();

        String registryImageTag = registryAddress + "/busybox:latest";
        dockerClient.tagImageCmd(localImage, registryAddress + "/busybox", "latest").exec();

        dockerClient.pushImageCmd(registryImageTag)
                .withAuthConfig(new AuthConfig()) // No authentication needed
                .start()
                .awaitCompletion();

        System.out.println("Successfully pushed image to registry: " + registryImageTag);
        assertTrue(true);
    }
}

However, when I run the test, I get this error:

com.github.dockerjava.api.exception.DockerClientException: Could not push image: failed to do request: 
Head "https://localhost:57244/v2/busybox/blobs/sha256:31311c5853a22c04d692f6581b4faa25771d915c1ba056c74e5ec82606eefdfa": 
dial tcp [::1]:57244: connect: connection refused

Things I tried

  1. manually tag and push an image into the registry, result still connection refused error.
  2. I ran
C:\Users\codex>curl http://localhost:<mappedPortIgotFromLogs>/v2/_catalog
{"repositories":[]}

so I know the repository is up and running

I also added this in testcontainers.properties ryuk.container.image=testcontainersofficial/ryuk

to get my test container to work in the first place.

And here is a screenshot from my docker desktop

docker desktop

Update 1:

i changed

`registryAddress = registry.getHost() + ":" + registry.getMappedPort(5000);`

to registryAddress = "0.0.0.0" + ":" + registry.getMappedPort(5000); but now i get

`com.github.dockerjava.api.exception.DockerClientException: Could not push image: failed to do request: Head "https://0.0.0.0:60075/v2/busybox/blobs/sha256:9c0abc9c5bd3a7854141800ba1f4a227baa88b11b49d8207eadc483c3f2496de": http: server gave HTTP response to HTTPS client`

Upvotes: 0

Views: 49

Answers (1)

David Spulock
David Spulock

Reputation: 11

  1. Force Docker to Use HTTP Instead of HTTPS

By default, Docker assumes that private registries use HTTPS. Since Testcontainers is running an HTTP registry, you need to configure Docker to allow HTTP.

Modify your Docker daemon configuration (for Windows, macOS, or Linux): Open the Docker Daemon settings (found in Docker Desktop under Settings → Docker Engine). Add the following entry under "insecure-registries":

{
  "insecure-registries": ["localhost:57244"]
}
(Replace 57244 with the mapped port from Testcontainers).

Restart Docker Desktop after saving the changes.

Alternatively, use the environment variable for Docker:

System.setProperty("com.github.dockerjava.insecure", "true");

Before running your test, try the following manual push in the terminal:

docker tag busybox:latest localhost:<your_testcontainer_mapped_port>/busybox:latest
docker push localhost:<your_testcontainer_mapped_port>/busybox:latest

Upvotes: 1

Related Questions