# Erlexec 2.6.0: new features - run\_container/1 and run\_graph/2

**URL:** <https://erlangforums.com/t/erlexec-2-6-0-new-features-run-container-1-and-run-graph-2/6119>\
**Category:** Chat / Discussions\
**Tags:** library, process, os, erlexec\
**Created:** [November 9, 2026, 4:49am UTC](https://erlangforums.com/t/erlexec-2-6-0-new-features-run-container-1-and-run-graph-2/6119 "2026-11-09T04:49:06Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![saleyn](https://erlangforums.com/user_avatar/erlangforums.com/saleyn/32/1188_2.png) [@saleyn](https://erlangforums.com/u/saleyn)\
**Post date:** [November 9, 2026, 4:49am UTC](https://erlangforums.com/t/erlexec-2-6-0-new-features-run-container-1-and-run-graph-2/6119/1 "2026-11-09T04:49:06Z")

</div>

The following two features were added to [erlexec](https://github.com/saleyn/erlexec).

## Container: **`exec:run_container/1`: run a command in a container**

You describe the container in a map, and `erlexec` builds the `podman` or `docker` command line and runs it:

```erlang
exec:run_container(#{
  image => "alpine:3.20",
  command => "echo hello",
  env => #{"FOO" => "bar"},
  volumes => [{"/tmp", "/work", "ro"}],
  ports => [{"127.0.0.1", 8080, 80}],
  cpu_limit => "500m",
  memory_limit => "256M",
  timeout => 5000
}).

```

- The runtime defaults to `auto`, which prefers `podman` and falls back to `docker`. You can also name one explicitly or give a path to an executable.
- Runtime paths are cached in `persistent_term`. A cached path that no longer exists is dropped and looked up again.
- `remove` defaults to `true`, so containers are removed when they exit.
- `timeout` uses the normal exec timeout. Only `on_timeout => kill` is supported.
- `exec_options` passes extra options through to `exec:run_link/2`.

The full list of spec keys is in the `exec_container` module docs.

## Graph: **`exec:run_graph/2`: run a pipeline of commands**

A graph is a list of tasks. Each task’s `stdout` or `stderr` can be routed to another task’s `stdin`, to one or more tasks, or to a file:

```erlang
Graph = [
  #{id => producer,
    cmd => "printf 'a\nb\nc\n'",
    stdout => [filter],

  #{id => filter,
    cmd => "grep '^b$'"}
],
{ok, [{stdout, [<<"b\n">>]}]} = exec:run_graph(Graph, [sync, stdout]).

```

- `sync` blocks the caller and returns the collected output. Without it, `run_graph/2` returns `{ok, Worker, GraphOsPid}` and sends messages to the caller.
- In async mode, `monitor` reports when the whole graph finishes, and `task_monitor` reports each task as it finishes.
- A per-task `timeout` can be set in the task map. `timeout` in the graph options limits the whole graph’s run time.
- `stats` returns resource usage per task.
- Options that aren’t graph-specific, such as `timeout` and `stats`, are passed to every task.

Feedback is welcome, especially on the graph options and the container spec keys. If you try either one, tell me what didn’t behave as you expected.

Github: [erlexec](https://github.com/saleyn/erlexec)  
Hex.pm: [erlexec](https://hex.pm/packages/erlexec)
