Developer utilities for interacting with running containers at runtime.
Provides a high-level, iex-friendly API for common container operations such as copying files, executing commands, listing contents, and more.
Usage
iex> {:ok, container} = TestcontainerEx.start_container(PostgresContainer.new())
iex> TestcontainerEx.DevTools.exec(container, ["psql", "-U", "postgres", "-c", "SELECT 1"])
{:ok, " ?column? \n----------\n 1\n(1 row)\n"}
iex> TestcontainerEx.DevTools.write_file(container, "/tmp/hello.txt", "world")
:ok
iex> TestcontainerEx.DevTools.read_file(container, "/tmp/hello.txt")
{:ok, "world"}
iex> TestcontainerEx.DevTools.delete_file(container, "/tmp/hello.txt")
:ok
iex> TestcontainerEx.DevTools.list_dir(container, "/tmp")
{:ok, ["file1", "file2"]}All functions accept either a Config.t() struct or a raw container ID string.
Summary
Functions
Copies a file or directory from the container to the host.
Copies a file or directory from the host into the container.
Deletes a file or directory inside the container.
Executes a command inside a running container.
Executes a command and returns the output as a list of lines.
Checks if a file or directory exists inside the container.
Finds PIDs by process name inside the container.
Kills a process inside the container by PID.
Kills processes by name inside the container.
Lists the contents of a directory inside the container.
Lists directory contents with details (permissions, size, etc.).
Returns the running processes inside the container (like ps aux).
Reads a single file from the container and returns its contents.
Reads a file from the container and returns its contents as a list of lines.
Returns whether the container is currently running.
Returns the container's current state (running, paused, etc.).
Returns live resource usage statistics for the container.
Writes string contents to a file inside the container.
Types
@type container_ref() :: TestcontainerEx.Container.Config.t() | String.t()
Functions
@spec copy_from(container_ref(), String.t(), String.t(), keyword()) :: :ok | {:error, term()}
Copies a file or directory from the container to the host.
Options
:base_url— override the Docker engine URL
Examples
iex> DevTools.copy_from(container, "/app/logs/server.log", "/tmp/server.log")
:ok
iex> DevTools.copy_from(container, "/app/data", "/tmp/container_data")
:ok
@spec copy_to(container_ref(), String.t(), String.t() | binary(), keyword()) :: :ok | {:error, term()}
Copies a file or directory from the host into the container.
The source can be:
- A file path — the file is read and uploaded to
dest_path - A directory path — the directory is archived and extracted at
dest_path - A binary — uploaded as a file at
dest_path
Examples
iex> DevTools.copy_to(container, "/app/config.yml", "config.yml")
:ok
iex> DevTools.copy_to(container, "/app/seeds", "/app")
:ok
iex> DevTools.copy_to(container, "/tmp/data.json", ~s({"key": "value"}))
:ok
@spec delete_file(container_ref(), String.t(), keyword()) :: :ok | {:error, term()}
Deletes a file or directory inside the container.
Uses rm -rf internally, so use with caution.
Examples
iex> DevTools.delete_file(container, "/tmp/hello.txt")
:ok
iex> DevTools.delete_file(container, "/tmp/mydir")
:ok
@spec exec(container_ref(), [String.t()], keyword()) :: exec_result()
Executes a command inside a running container.
Returns {:ok, output} on success or {:error, reason} on failure.
Options
:tty— allocate a TTY (default:false):workdir— working directory inside the container:user— user (UID or name) to run as:env— list of environment variables (e.g.["FOO=bar", "BAZ=qux"]):timeout— timeout in ms (default:30_000)
Examples
iex> DevTools.exec(container, ["ls", "-la", "/app"])
{:ok, "total 12\ndrwxr-xr-x 2 root root 4096 Jan 1 00:00 .\n..."}
iex> DevTools.exec(container, ["psql", "-c", "SELECT 1"], user: "postgres")
{:ok, " ?column? \n----------\n 1\n(1 row)\n"}
@spec exec_lines(container_ref(), [String.t()], keyword()) :: {:ok, [String.t()]} | {:error, term()}
Executes a command and returns the output as a list of lines.
Convenience wrapper around exec/2 that splits the output by newlines.
@spec exists?(container_ref(), String.t(), keyword()) :: boolean()
Checks if a file or directory exists inside the container.
Returns true if the path exists, false otherwise.
@spec find_pids(container_ref(), String.t(), keyword()) :: {:ok, [integer()]} | {:error, term()}
Finds PIDs by process name inside the container.
Returns {:ok, pids} where ids is a list of integer PIDs.
Examples
iex> DevTools.find_pids(container, "nginx")
{:ok, [123, 456]}
@spec kill_process(container_ref(), integer(), keyword()) :: :ok | {:error, term()}
Kills a process inside the container by PID.
Options
:signal— signal to send (default:"SIGKILL")
Examples
iex> DevTools.kill_process(container, 123)
:ok
iex> DevTools.kill_process(container, 456, signal: "SIGTERM")
:ok
@spec kill_process_name(container_ref(), String.t(), keyword()) :: :ok | {:error, term()}
Kills processes by name inside the container.
Uses pkill to match against the process name.
Options
:signal— signal to send (default:"SIGKILL"):exact— match exact process name (default:false)
Examples
iex> DevTools.kill_process_name(container, "nginx")
:ok
iex> DevTools.kill_process_name(container, "my_app", signal: "SIGTERM", exact: true)
:ok
@spec list_dir(container_ref(), String.t(), keyword()) :: {:ok, [String.t()]} | {:error, term()}
Lists the contents of a directory inside the container.
Returns {:ok, entries} where entries is a list of file/directory names.
Examples
iex> DevTools.list_dir(container, "/app")
{:ok, ["config.json", "lib", "mix.exs"]}
@spec list_dir_long(container_ref(), String.t(), keyword()) :: {:ok, [String.t()]} | {:error, term()}
Lists directory contents with details (permissions, size, etc.).
Returns {:ok, entries} where entries is a list of formatted strings.
@spec processes( container_ref(), keyword() ) :: {:ok, map()} | {:error, term()}
Returns the running processes inside the container (like ps aux).
Options
:ps_args— ps arguments (default:"-ef")
@spec read_file(container_ref(), String.t(), keyword()) :: {:ok, binary()} | {:error, term()}
Reads a single file from the container and returns its contents.
Examples
iex> DevTools.read_file(container, "/app/config.json")
{:ok, "{\"debug\": true}\n"}
iex> DevTools.read_file(container, "/nonexistent")
{:error, :empty_archive}
@spec read_lines(container_ref(), String.t(), keyword()) :: {:ok, [String.t()]} | {:error, term()}
Reads a file from the container and returns its contents as a list of lines.
Convenience wrapper around read_file/2.
@spec running?( container_ref(), keyword() ) :: boolean()
Returns whether the container is currently running.
@spec state( container_ref(), keyword() ) :: {:ok, map()} | {:error, term()}
Returns the container's current state (running, paused, etc.).
@spec stats( container_ref(), keyword() ) :: {:ok, map()} | {:error, term()}
Returns live resource usage statistics for the container.
Options
:stream— stream stats (default:false)
@spec write_file(container_ref(), String.t(), String.t(), keyword()) :: :ok | {:error, term()}
Writes string contents to a file inside the container.
Convenience wrapper around copy_to/3 for writing text content.
Examples
iex> DevTools.write_file(container, "/tmp/hello.txt", "world")
:ok
iex> DevTools.write_file(container, "/app/config.json", ~s({"debug": true}))
:ok