Repository: testcontainers/testcontainers-go
Pull request #3062: fix: handle stopped containers more gracefully when reuse is enabled
Author: login: georgespalding
Labels: name: bug
description: An issue with the library
Created: 2025-03-26T22:43:33Z | Merged: 2025-04-25T11:40:12Z

<!-- Type of change
Please label this PR with one of the existing labels, depending on the scope of your change
-->

## What does this PR do?

Fixes a bug that causes testcontainers to hang for a really long time waiting on a stopped container when reuse is enabled.

The fix in short is:

When a container is being created with reuse enabled:
- Look among all containers, even the ones not running.
  - If a container with the expected name is found:
    - If it is not running:
      - Attempt to start it.
        - If the start fails, return an error

The alternative cases above should work same as before 

<!-- Mandatory
Explain here the changes you made on the PR. Please explain the WHAT: patterns used, algorithms implemented, design architecture, etc.
-->

## Why is it important?

The way the library works today, if a reused container exists, but is not running, it freezes for a long time, which is a really bad developer experience.

This fix is not watertight (ses the `docker pause` scenario below), but instantly tells you that something is wrong, giving fast feedback.

## Related issues


<!-- Recommended
Link related issues below. Insert the issue link or reference after the word "Closes" if merging this should automatically close it.

- Closes #123
- Relates #123
- Requires #123
- Supersedes #123
-->
- Relates https://github.com/testcontainers/testcontainers-go/issues/2470

## How to test this PR

Create a little program that runs a testcontainer:
```golang
package main

import (
	"context"
	"fmt"
	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/postgres"
)

func main() {
	true := true
	containerName := "my-postgres"
	container, err := postgres.Run(context.Background(),
		"postgres:14-bookworm",
		postgres.BasicWaitStrategies(),
		testcontainers.CustomizeRequestOption(func(req *testcontainers.GenericContainerRequest) error {
			req.Name = containerName
			req.Reuse = true
			return nil
		}),
	)
	if err != nil {
		fmt.Println(fmt.Sprintf("run postgres testcontainer: %s", err.Error()))
	} else {
		fmt.Println(fmt.Sprintf("postgres testcontainer is running: %t", container.Container.IsRunning()))
	}
}
```

1. `docker ps` -> container is not there
2. `go run ./` -> prints `postgres testcontainer is running: true`
3. `docker ps` -> container _is_ running
4. `docker stop my-postgres`
5. `go run ./` -> prints `postgres testcontainer is running: true`
6. `docker pause my-postgres`
7. `go run ./` -> prints `run postgres testcontainer: generic container: create container: start container my-postgres in state paused: container start: Error response from daemon: cannot start a paused container, try unpause instead` 



Diff:
diff --git a/docker.go b/docker.go
index 1493cd9682..c578796d75 100644
--- a/docker.go
+++ b/docker.go
@@ -1266,7 +1266,7 @@ func (p *DockerProvider) findContainerByName(ctx context.Context, name string) (
 
 	// Note that, 'name' filter will use regex to find the containers
 	filter := filters.NewArgs(filters.Arg("name", fmt.Sprintf("^%s$", name)))
-	containers, err := p.client.ContainerList(ctx, container.ListOptions{Filters: filter})
+	containers, err := p.client.ContainerList(ctx, container.ListOptions{All: true, Filters: filter})
 	if err != nil {
 		return nil, fmt.Errorf("container list: %w", err)
 	}
@@ -1364,6 +1364,23 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
+	// If a container was stopped programmatically, we want to ensure the container
+	// is running again, but only if it is not paused, as it's not possible to start
+	// a paused container. The Docker Engine returns the "cannot start a paused container,
+	// try unpause instead" error.
+	switch c.State {
+	case "running":
+		// cannot re-start a running container, but we still need
+		// to call the startup hooks.
+	case "paused":
+		// TODO: we should unpause the container here.
+		return nil, fmt.Errorf("cannot start a paused container: %w", errors.ErrUnsupported)
+	default:
+		if err := dc.Start(ctx); err != nil {
+			return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
+		}
+	}
+
 	err = dc.startedHook(ctx)
 	if err != nil {
 		return nil, err
diff --git a/reuse_test.go b/reuse_test.go
new file mode 100644
index 0000000000..bb4ccddc7f
--- /dev/null
+++ b/reuse_test.go
@@ -0,0 +1,73 @@
+package testcontainers_test
+
+import (
+	"context"
+	"errors"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/internal/core"
+)
+
+func TestGenericContainer_stop_start_withReuse(t *testing.T) {
+	containerName := "my-nginx"
+
+	req := testcontainers.GenericContainerRequest{
+		ContainerRequest: testcontainers.ContainerRequest{
+			Image:        nginxAlpineImage,
+			ExposedPorts: []string{"8080/tcp"},
+			Name:         containerName,
+		},
+		Reuse:   true,
+		Started: true,
+	}
+
+	ctr, err := testcontainers.GenericContainer(context.Background(), req)
+	testcontainers.CleanupContainer(t, ctr)
+	require.NoError(t, err)
+	require.NotNil(t, ctr)
+
+	err = ctr.Stop(context.Background(), nil)
+	require.NoError(t, err)
+
+	// Run another container with same container name:
+	// The checks for the exposed ports must not fail when restarting the container.
+	ctr1, err := testcontainers.GenericContainer(context.Background(), req)
+	testcontainers.CleanupContainer(t, ctr1)
+	require.NoError(t, err)
+	require.NotNil(t, ctr1)
+}
+
+func TestGenericContainer_pause_start_withReuse(t *testing.T) {
+	containerName := "my-nginx"
+
+	req := testcontainers.GenericContainerRequest{
+		ContainerRequest: testcontainers.ContainerRequest{
+			Image:        nginxAlpineImage,
+			ExposedPorts: []string{"8080/tcp"},
+			Name:         containerName,
+		},
+		Reuse:   true,
+		Started: true,
+	}
+
+	ctr, err := testcontainers.GenericContainer(context.Background(), req)
+	testcontainers.CleanupContainer(t, ctr)
+	require.NoError(t, err)
+	require.NotNil(t, ctr)
+
+	// Pause the container is not supported by our API, but we can do it manually
+	// by using the Docker client.
+	cli, err := core.NewClient(context.Background())
+	require.NoError(t, err)
+
+	err = cli.ContainerPause(context.Background(), ctr.GetContainerID())
+	require.NoError(t, err)
+
+	// Because the container is paused, it should not be possible to start it again.
+	ctr1, err := testcontainers.GenericContainer(context.Background(), req)
+	testcontainers.CleanupContainer(t, ctr1)
+	require.ErrorIs(t, err, errors.ErrUnsupported)
+}


Reviews:
user: login: georgespalding
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T07:35:31Z
user: login: stevenh
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T10:58:17Z
user: login: georgespalding
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T13:17:25Z
user: login: georgespalding
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T08:49:40Z
user: login: stevenh
body: A few clarifying questions
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T08:47:58Z
user: login: mdelapenya
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T08:55:49Z
user: login: mdelapenya
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T08:58:47Z
user: login: mdelapenya
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T09:00:00Z
user: login: mdelapenya
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T09:13:14Z
user: login: stevenh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T10:05:47Z
user: login: mdelapenya
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T10:08:35Z
user: login: mdelapenya
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T10:14:54Z

Review comments:
diff_hunk: @@ -1369,6 +1369,16 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
+	if p.config.RyukDisabled {
+		// ryuk disabled, ensure the container we are about to reuse is started
+		if !dc.IsRunning() {
path: docker.go
user: login: georgespalding
body: Bug: `dc.IsRunning` always returns false, that struct was initialized right above... :facepalm: 
```suggestion
		if c.State == "running" {
```
created_at: 2025-03-28T07:35:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1369,6 +1369,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
+	if p.config.RyukDisabled {
+		// ryuk disabled, ensure the container we are about to reuse is running
+		if c.State != "running" {
+			// found container to reuse, but it is not in state running
+			fmt.Println("Attempting to start: " + req.Name + " in state: " + c.State)
path: docker.go
user: login: stevenh
body: suggestion: removing this debugging.
created_at: 2025-03-28T10:58:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1369,6 +1369,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
+	if p.config.RyukDisabled {
+		// ryuk disabled, ensure the container we are about to reuse is running
+		if c.State != "running" {
+			// found container to reuse, but it is not in state running
+			fmt.Println("Attempting to start: " + req.Name + " in state: " + c.State)
path: docker.go
user: login: georgespalding
body: Committed by mistake when checking that the `c.State` check was doing what I expected...
Removed now.
created_at: 2025-03-28T13:17:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1369,6 +1369,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
+	if p.config.RyukDisabled {
+		// ryuk disabled, ensure the container we are about to reuse is running
+		if c.State != "running" {
+			// found container to reuse, but it is not in state running
+			fmt.Println("Attempting to start: " + req.Name + " in state: " + c.State)
path: docker.go
user: login: georgespalding
body: @stevenh I've removed the debugging as you suggested. Would you be up for doing a second pass?
created_at: 2025-04-02T08:49:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
path: docker.go
user: login: stevenh
body: question: the comment details Ryuk state but there's no check for this, should there be?
created_at: 2025-04-25T08:44:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
+	// ensure the container is running again, but only if it is not paused, as it's
+	// not possible to start a paused container. The Docker Engine returns the
+	// "cannot start a paused container, try unpause instead" error.
+	switch c.State {
+	case "running", "paused":
path: docker.go
user: login: stevenh
body: question: should we unpause it or error?
created_at: 2025-04-25T08:45:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,39 @@
+package testcontainers_test
+
+import (
+	"context"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+func TestGenericContainer_stop_start_withReuse(t *testing.T) {
+	containerName := "my-postgres"
path: reuse_test.go
user: login: stevenh
body: nit: change to my-nginx to avoid confusion given the image used.
created_at: 2025-04-25T08:47:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,39 @@
+package testcontainers_test
+
+import (
+	"context"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/testcontainers/testcontainers-go"
+)
+
+func TestGenericContainer_stop_start_withReuse(t *testing.T) {
+	containerName := "my-postgres"
path: reuse_test.go
user: login: mdelapenya
body: Oh yes, I started with postgres, but reduced the test size. Changing it asap
created_at: 2025-04-25T08:55:49Z
author_association: MEMBER
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
path: docker.go
user: login: mdelapenya
body: Mmm I added it because the original message included it 🤔 But you're right, and readers don't care about Ryuk's state in this case. Removing that asap
created_at: 2025-04-25T08:58:46Z
author_association: MEMBER
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
+	// ensure the container is running again, but only if it is not paused, as it's
+	// not possible to start a paused container. The Docker Engine returns the
+	// "cannot start a paused container, try unpause instead" error.
+	switch c.State {
+	case "running", "paused":
path: docker.go
user: login: mdelapenya
body: I intentionally added like that because we do not support Pause/Unpause at the moment, which could be of desire I guess. Probably adding a //TODO comment mentioning it will be addressed once Pause is supported?
created_at: 2025-04-25T09:00:00Z
author_association: MEMBER
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
+	// ensure the container is running again, but only if it is not paused, as it's
+	// not possible to start a paused container. The Docker Engine returns the
+	// "cannot start a paused container, try unpause instead" error.
+	switch c.State {
+	case "running", "paused":
path: docker.go
user: login: mdelapenya
body: I added the //TODO message
created_at: 2025-04-25T09:13:14Z
author_association: MEMBER
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
+	// ensure the container is running again, but only if it is not paused, as it's
+	// not possible to start a paused container. The Docker Engine returns the
+	// "cannot start a paused container, try unpause instead" error.
+	switch c.State {
+	case "running", "paused":
path: docker.go
user: login: stevenh
body: Would it be better to just error for paused, indicating it's not supported, that way it will fail fast?
created_at: 2025-04-25T10:05:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
+	// ensure the container is running again, but only if it is not paused, as it's
+	// not possible to start a paused container. The Docker Engine returns the
+	// "cannot start a paused container, try unpause instead" error.
+	switch c.State {
+	case "running", "paused":
path: docker.go
user: login: mdelapenya
body: Yeah, I like the idea, thanks!
created_at: 2025-04-25T10:08:35Z
author_association: MEMBER
diff_hunk: @@ -1364,13 +1364,17 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
 		lifecycleHooks:    []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
 	}
 
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
+	// If a container was stopped programmatically, and Ryuk is enabled, we want to
+	// ensure the container is running again, but only if it is not paused, as it's
+	// not possible to start a paused container. The Docker Engine returns the
+	// "cannot start a paused container, try unpause instead" error.
+	switch c.State {
+	case "running", "paused":
path: docker.go
user: login: mdelapenya
body: ✅  Done in [77bfbc2](https://github.com/testcontainers/testcontainers-go/pull/3062/commits/77bfbc23d9f92fafbb570f505dca01bc31d17b6a)
created_at: 2025-04-25T10:14:54Z
author_association: MEMBER

PR comments:
user: login: netlify[bot]
created_at: 2025-03-26T22:43:54Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *testcontainers-go* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 77bfbc23d9f92fafbb570f505dca01bc31d17b6a |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/testcontainers-go/deploys/680b609406923c000871a107 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-3062--testcontainers-go.netlify.app](https://deploy-preview-3062--testcontainers-go.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTMwNjItLXRlc3Rjb250YWluZXJzLWdvLm5ldGxpZnkuYXBwIn0.n-rP5qT8UHlFgC0nlB5IoCbmuYpdkuGuXevUfzIU82E)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [testcontainers-go Preview](https://deploy-preview-3062--testcontainers-go.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/testcontainers-go/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: mdelapenya
created_at: 2025-04-24T16:21:45Z
body: @georgespalding thanks for submitting this PR.  I'm trying to reproduce it locally with this test:

```go
func TestWithReuse(t *testing.T) {
	containerName := "my-postgres"

	opts := []testcontainers.ContainerCustomizer{
		postgres.BasicWaitStrategies(),
		testcontainers.CustomizeRequestOption(func(req *testcontainers.GenericContainerRequest) error {
			req.Name = containerName
			req.Reuse = true
			return nil
		}),
	}

	ctr, err := postgres.Run(context.Background(), "postgres:14-bookworm", opts...)
	if err != nil {
		t.Logf("run postgres testcontainer: %s", err.Error())
	} else {
		t.Logf("postgres testcontainer is running: %t", ctr.IsRunning())
	}

	require.NoError(t, err)
	require.NotNil(t, ctr)

	err = ctr.Stop(context.Background(), nil)
	require.NoError(t, err)

	ctr1, err := postgres.Run(context.Background(), "postgres:14-bookworm", opts...)
	if err != nil {
		t.Logf("run postgres testcontainer: %s", err.Error())
	} else {
		t.Logf("postgres testcontainer is running: %t", ctr1.IsRunning())
	}

	require.NoError(t, err)
	require.NotNil(t, ctr1)

	cli, err := testcontainers.NewDockerClientWithOpts(context.Background())
	require.NoError(t, err)
	require.NotNil(t, cli)

	err = cli.ContainerPause(context.Background(), ctr1.GetContainerID())
	require.NoError(t, err)

	ctr2, err := postgres.Run(context.Background(), "postgres:14-bookworm", opts...)
	if err != nil {
		t.Logf("run postgres testcontainer: %s", err.Error())
	} else {
		t.Logf("postgres testcontainer is running: %t", ctr2.IsRunning())
	}

	require.NoError(t, err)
	require.NotNil(t, ctr2)
}
```

This test fails for `ctr2` to be run, and this is because it needs to be `unpaused` first, which is the error message I see in the description of the PR.

I tested it against `main` and your code with the same results, although I spotted a different bug for reused containers: the code to skip starting a container if Ryuk was disabled I think is incorrect, and should apply always, checking if the container is in the unpaused state too (cc/ @stevenh)

docker.go:L1367
```diff
-	if p.config.RyukDisabled {
-		// ryuk disabled, ensure the container we are about to reuse is running
-		if c.State != "running" {
-			// found container to reuse, but it is not in state running
-			if err := dc.Start(ctx); err != nil {
-				return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
-			}
-		}
-	}
+	// Ensure the container we are about to reuse is running,
+	// but not if it is paused.
+	if c.State != "running" && c.State != "paused" {
+		// found container to reuse, but it is not in state running
+		if err := dc.Start(ctx); err != nil {
+			return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
+		}
+	}
```

OTOH, testcontainers-go does not provide native support for Pausing/Unpausing containers, unless using the underlying Docker client we expose (see my test).

Said that, I'm not sure how to proceed with this PR
author_association: MEMBER
user: login: mdelapenya
created_at: 2025-04-25T05:43:37Z
body: @georgespalding I added a commit with the related fix that I found
author_association: MEMBER