From 4ccbcc8d2624aacb5be938ffa93266a939e62fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarl=20Andr=C3=A9=20H=C3=BCbenthal?= Date: Wed, 22 Apr 2026 08:24:17 +0200 Subject: [PATCH] feat(container): add Container.with_name/2 Adds a `name` field (default nil) to the `Testcontainers.Container` struct and a `with_name/2` builder that assigns a custom name to the container at creation time, wired through to Docker's `/containers/create` `name` query parameter. This lets users give a container a stable, well-known name (like `docker run --name foo`) so other containers on the same network can reference it by that name. Fixes #177 --- lib/container.ex | 12 ++++++++++++ lib/docker/api.ex | 4 +++- test/container_test.exs | 24 ++++++++++++++++++++++++ test/testcontainers_test.exs | 20 ++++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/lib/container.ex b/lib/container.ex index 6c605c7..dd85ea6 100644 --- a/lib/container.ex +++ b/lib/container.ex @@ -30,6 +30,7 @@ defmodule Testcontainers.Container do network_mode: nil, network: nil, hostname: nil, + name: nil, reuse: false, force_reuse: false, pull_policy: nil @@ -284,6 +285,17 @@ defmodule Testcontainers.Container do %__MODULE__{config | hostname: hostname} end + @doc """ + Sets a custom name for the container (equivalent to `docker run --name`). + + Must match `/?[a-zA-Z0-9][a-zA-Z0-9_.-]+`. This is useful when other + containers need to reference this container by name on a shared Docker + network. + """ + def with_name(%__MODULE__{} = config, name) when is_binary(name) do + %__MODULE__{config | name: name} + end + def with_copy_to(%__MODULE__{} = config, target, source) when is_binary(target) and is_binary(source) do %__MODULE__{ diff --git a/lib/docker/api.ex b/lib/docker/api.ex index 1b1ee63..644f1a4 100644 --- a/lib/docker/api.ex +++ b/lib/docker/api.ex @@ -88,7 +88,9 @@ defmodule Testcontainers.Docker.Api do end def create_container(%Container{} = container, conn) do - case Api.Container.container_create(conn, container_create_request(container)) do + opts = if container.name, do: [name: container.name], else: [] + + case Api.Container.container_create(conn, container_create_request(container), opts) do {:error, %Tesla.Env{status: other}} -> {:error, {:http_error, other}} diff --git a/test/container_test.exs b/test/container_test.exs index 80bc16c..0d7c73b 100644 --- a/test/container_test.exs +++ b/test/container_test.exs @@ -213,6 +213,30 @@ defmodule Testcontainers.ContainerTest do end end + describe "with_name/2" do + test "defaults to nil" do + container = Container.new("my-image") + assert container.name == nil + end + + test "sets the name on the container" do + container = + Container.new("my-image") + |> Container.with_name("my-container") + + assert container.name == "my-container" + end + + test "overwrites a previously set name" do + container = + Container.new("my-image") + |> Container.with_name("first") + |> Container.with_name("second") + + assert container.name == "second" + end + end + describe "with_privileged/2" do test "sets privileged to true" do container = Container.new("my-image") diff --git a/test/testcontainers_test.exs b/test/testcontainers_test.exs index c140c99..f16642e 100644 --- a/test/testcontainers_test.exs +++ b/test/testcontainers_test.exs @@ -41,6 +41,26 @@ defmodule TestcontainersTest do :ok = GenServer.stop(pid) end + test "assigns custom name to container via Container.with_name/2" do + name = "testcontainers-name-#{:rand.uniform(1_000_000)}" + + config = + Container.new("nginx:alpine") + |> Container.with_name(name) + + {:ok, pid} = Testcontainers.start_link(name: :name_test) + {:ok, container} = Testcontainers.start_container(config, :name_test) + + conn = Connection.get_connection() |> Tuple.to_list() |> Kernel.hd() + {:ok, %DockerEngineAPI.Model.ContainerInspectResponse{Name: assigned_name}} = + DockerEngineAPI.Api.Container.container_inspect(conn, container.container_id) + + # Docker returns the name prefixed with a leading "/" + assert assigned_name == "/" <> name + + :ok = GenServer.stop(pid) + end + test "initializes successfully when ryuk is disabled" do # Set environment variable to disable Ryuk System.put_env("TESTCONTAINERS_RYUK_DISABLED", "true")