Skip to content

Commit cba3454

Browse files
authored
TASK-6694: New documentation for Momentum in container (#795)
Signed-off-by: Doug Koerich <[email protected]>
1 parent 5bafd5c commit cba3454

File tree

7 files changed

+305
-0
lines changed

7 files changed

+305
-0
lines changed

components/site/momentumHomePageContent.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const content = [
2828
url: '/momentum/4/p-reference',
2929
level: 3,
3030
},
31+
{ label: 'Running in a Container', url: '/momentum/4/p-container', level: 3 },
3132
],
3233
[
3334
{ label: 'Momentum 3.x Documentation', level: 1 },
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
lastUpdated: "07/01/2025"
3+
title: "Building an Image"
4+
description: "Instructions for building a Docker container image for Momentum."
5+
---
6+
7+
## <a name="containers.building"></a> Building the Momentum container
8+
9+
Use a *Dockerfile* to build a Momentum container image.
10+
11+
> **NOTE:** Momentum requires a valid license and working configuration to run. You can either include them into your container image or attach them later to the container at runtime (like in the example below, where they will be found in the mounted `/opt/msys/ecelerity/etc/` tree).
12+
13+
**Example:**
14+
```dockerfile
15+
FROM rockylinux:9
16+
17+
# Install dependencies and utilities
18+
RUN dnf update -y && \
19+
dnf install -y bzip2 epel-release iproute iputils net-tools openssl perl procps-ng sudo unbound && \
20+
dnf clean all && rm -rf /var/cache/dnf
21+
22+
# Copy and unpack the bundle into the container
23+
ARG version=5.0.0.xxxxx
24+
ADD momentum-mta-bundle-${version}.rhel9.x86_64.tar.gz /var/tmp/
25+
26+
# Install as per the Momentum Installation Guide
27+
RUN cd /var/tmp/momentum-mta-${version} && \
28+
./setrepodir && \
29+
dnf install -y --config momentum.repo --enablerepo=momentum msys-role-mta msys-ecelerity-mobility msys-ecelerity-engagement-proxy && \
30+
dnf clean all && rm -rf /var/cache/dnf && \
31+
rm -rf /var/tmp/momentum-mta-bundle-${version}.rhel9.x86_64.tar.gz momentum-mta-${version}
32+
33+
# Setup initial configuration as per the same Momentum Installation Guide
34+
RUN sudo -u ecuser mkdir -p /opt/msys/ecelerity/etc/conf/default && \
35+
cd /opt/msys/ecelerity/etc/sample-configs/default && \
36+
sudo -u ecuser cp ecelerity.conf ecelerity-cluster.conf common.conf /opt/msys/ecelerity/etc/conf/default
37+
38+
# Environment variables for the gimli (heartbeat) monitor
39+
ENV GIMLI_QUIET=1 \
40+
GIMLI_DETACH=0 \
41+
GIMLI_PID_FILE=/var/run/ecelerity.monitor.pid \
42+
GIMLI_TRACE_DIR=/var/log/ecelerity/traces
43+
44+
# Paths that could be (bind-)mounted
45+
VOLUME ["/opt/msys/ecelerity/etc/conf/default", "/var/log/ecelerity", "/var/spool/ecelerity"]
46+
47+
# Ports that could be exposed
48+
EXPOSE 25 2025
49+
50+
# Start the MTA service in the foreground inside the container
51+
CMD ["/opt/msys/gimli/bin/monitor", "/opt/msys/ecelerity/sbin/run.ecelerity"]
52+
````
53+
54+
To build the Docker image from the above Dockerfile:
55+
1. Copy the Momentum MTA bundle to the same directory as the Dockerfile.
56+
2. Run the following command in that directory:
57+
```bash
58+
docker build --tag momentum-mta:$VERSION --build-arg version=$VERSION .
59+
```
60+
where `$VERSION` is the version of the Momentum MTA bundle you are using (e.g., `5.0.0.12345`).
61+
62+
## <a name="containers.persistence"></a> Persistence of data
63+
64+
By default, all files in a container do **NOT** persist when the container exits. On the other hand, Momentum stores state data (e.g. spooled messages) in the filesystem, and a restart of the service would take it back from the saved state. Momentum also generates some files for post-processing, such as logs and traces.
65+
66+
To ensure that these files persist across container restarts, you should use [bind mounts](https://docs.docker.com/engine/storage/bind-mounts/) to persist the following (but not limited to) directories in the container:
67+
- `/var/spool/ecelerity`: directory that keeps the spool files for emails not yet delivered.
68+
- `/var/log/ecelerity`: directory that stores the logs and traces generated by Momentum.
69+
70+
Optionally, you can also mount the configuration directory:
71+
- `/opt/msys/ecelerity/etc/conf/default`: directory that contains the configuration files for Momentum, such as `ecelerity.conf`.
72+
73+
## <a name="containers.listeners"></a> Exposing listeners
74+
75+
Momentum listens on several ports for different purposes. When running in a container, you can expose these ports to the host system using Docker's port mapping feature. For a more comprehensive explanation of that, see Docker's [documentation](https://docs.docker.com/engine/network/).
76+
77+
### <a name="containers.listeners.exposing"></a> Bridge mode
78+
79+
By default, Docker runs containers in "bridge" mode, which means that the container has its own network namespace and can communicate with the host through a virtual bridge. The host addresses aren't visible inside the container, and you *must* use port mapping to expose the necessary ports for traffic sent to the host to reach Momentum.
80+
81+
To expose the ports, you use the `-p` option when running the container.
82+
83+
### <a name="containers.listeners.host"></a> Host mode
84+
85+
Alternatively, you can run the container in "host" mode, which makes the host interfaces transparent to the container, i.e., allows the container to share the host's network stack. In this case, you do not need to map ports, as the container will listen on the same ports as the host.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
lastUpdated: "07/01/2025"
3+
title: "Using Docker Compose"
4+
description: "Instructions for using Docker Compose to run the Momentum container."
5+
---
6+
7+
8+
While the `docker run` command is useful for launching single containers manually, **Docker Compose** offers a more structured, maintainable, and scalable way to define and manage containers. This is especially valuable for services like Momentum which may involve multiple volumes, environment variables, port mappings, and resource configurations.
9+
10+
## <a name="containers.compose.benefits"></a> Benefits of using Docker Compose
11+
12+
- **Centralized configuration (YAML file)**: all settings — environment variables, volumes, port bindings, restart policies, resource limits — are defined in a single `docker-compose.yml` file. This makes configurations clear, reproducible, and version-controlled.
13+
- **Easier management**: if the container requires several mounts, ports, or links to other services (e.g., metrics, monitoring agents), Docker Compose handles that in one command, without long and error-prone `docker run` lines.
14+
- **Improved readability and maintainability**: instead of complicated CLI commands, configuration is written in a clean, readable YAML format, simplifying troubleshooting.
15+
- **Environment-specific overrides**: Docker Compose supports separate override files (e.g., `docker-compose.override.yml` or `.env`) for environment-specific settings (development, staging, production).
16+
- **Container lifecycle management**: with Docker Compose, you can start, stop, restart, or destroy entire service stacks with simple commands (up, down, restart, etc.).
17+
- **Restart policies and fault tolerance**: easily define behavior on crash or reboot (`restart: unless-stopped`, `always`, etc.) directly in the `docker-compose.yml` file.
18+
19+
## <a name="containers.compose.running"></a> Running the Momentum container
20+
21+
To create a Momentum container using Docker Compose, put a `docker-compose.yml` file in your project directory.
22+
23+
**Example:**
24+
```yaml
25+
services:
26+
mta:
27+
cap_add:
28+
- NET_BIND_SERVICE
29+
- SYS_PTRACE
30+
command: "/opt/msys/gimli/bin/monitor /opt/msys/ecelerity/sbin/run.ecelerity"
31+
container_name: mta
32+
cpus: 4
33+
environment:
34+
- GIMLI_QUIET=1
35+
- GIMLI_DETACH=0
36+
- GIMLI_PID_FILE=/var/run/ecelerity.monitor.pid
37+
- GIMLI_TRACE_DIR=/var/log/ecelerity/traces
38+
hostname: mta.test
39+
image: momentum-mta:${VERSION}
40+
mem_limit: 8g
41+
network_mode: host
42+
#ports: # Uncomment if mode changes to "bridge"
43+
# - "25:25"
44+
# - "2025:2025"
45+
restart: unless-stopped
46+
volumes:
47+
- type: bind
48+
read_only: true
49+
source: /path/to/your/config
50+
target: /opt/msys/ecelerity/etc/conf/default
51+
- type: bind
52+
source: /path/to/your/logs
53+
target: /var/log/ecelerity
54+
- type: bind
55+
source: /path/to/your/spool
56+
target: /var/spool/ecelerity
57+
```
58+
59+
To run the container using Docker Compose with the `docker-compose.yml` contents of the example above, execute the following command in the same directory as the YAML file:
60+
61+
```
62+
VERSION=5.0.0.xxxxx docker compose up -d
63+
```
64+
65+
### <a name="containers.compose.limits"></a> Setting resource limits
66+
67+
Notice it is possible to set resource limits (CPU and memory) directly in the `docker-compose.yml` file, which is not possible with the `docker run` command. The limits set in the example above are:
68+
- `cpus: 4`: limits the container to use 4 CPU cores.
69+
- `mem_limit: 8g`: limits the container to use a maximum of 8 GB of memory.
70+
71+
and they can be checked with the following command:
72+
```
73+
docker inspect mta | grep -Eiw 'NanoCpus|Memory'
74+
```
75+
which should return something like:
76+
```
77+
"NanoCpus": 4000000000,
78+
"Memory": 8589934592,
79+
```
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
lastUpdated: "07/01/2025"
3+
title: "Running and Accessing the Container"
4+
description: "Instructions for running the Docker container built with Momentum."
5+
---
6+
7+
8+
## <a name="containers.running"></a> Running the Momentum container
9+
10+
For a manual run for test of the Momentum container from the image built as per [here](/momentum/4/4-container-building), you can use the following command:
11+
12+
```bash
13+
docker run -d --name mta --hostname mta.test \
14+
-v /path/to/your/config:/opt/msys/ecelerity/etc/conf/default:ro \
15+
-v /path/to/your/logs:/var/log/ecelerity \
16+
-v /path/to/your/spool:/var/spool/ecelerity \
17+
-p 25:25 -p 2025:2025 \
18+
--cap-add=NET_BIND_SERVICE --cap-add=SYS_PTRACE \
19+
momentum-mta:$VERSION
20+
```
21+
22+
where `$VERSION` is the version of Momentum used to build and tag the image (e.g., `5.0.0.12345`).
23+
24+
> **NOTE:** To run Momentum in your production environment, you will likely want to customize mounting of volumes and mapping of ports to suit your deployment needs.
25+
26+
In the command above, notice the following:
27+
- The `:ro` suffix on the volume mount for `/opt/msys/ecelerity/etc/conf/default` indicates that the configuration is mounted in read-only mode.
28+
- Since the "bridge" network mode (the default) is being used, the `-p` options map the container's ports to the host's ports.
29+
- The `--cap-add=NET_BIND_SERVICE` capability allows the container to bind to low-numbered ports (like 25).
30+
- The `--cap-add=SYS_PTRACE` capability allows the container to use the `ptrace` system call, which is required by **gimli** for monitoring.
31+
32+
You can check the container is running with the following command:
33+
```
34+
docker ps
35+
```
36+
and see the `mta` container listed with its status as "Up":
37+
```
38+
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39+
319be9d4affd momentum-mta:5.0.0.12345 "/opt/msys/gimli/bin…" 4 seconds ago Up 3 seconds 0.0.0.0:25->25/tcp, [::]:25->25/tcp, 0.0.0.0:2025->2025/tcp, [::]:2025->2025/tcp mta
40+
```
41+
You can also see in the logs of the container:
42+
```bash
43+
docker logs mta
44+
```
45+
that Momentum license was validated:
46+
```
47+
[Wed 11 Jun 2025 18:27:48] <0x7f5926da1200> Validating software license.
48+
(...)
49+
[Wed 11 Jun 2025 18:27:48] <0x7f5926da1200> Valid license.
50+
```
51+
52+
## <a name="containers.accessing"></a> Accessing the container
53+
54+
Use the `docker exec` command to access the `mta` container via a terminal session. For example, to inspect the running processes inside the container, you can run:
55+
```
56+
docker exec mta ps -efH
57+
```
58+
obtaining output similar to:
59+
```
60+
UID PID PPID C STIME TTY TIME CMD
61+
root 239 0 0 18:39 ? 00:00:00 ps -efH
62+
root 1 0 0 18:27 ? 00:00:00 /opt/msys/ecelerity/sbin/run.ecelerity: monitoring child 7
63+
ecuser 7 1 0 18:27 ? 00:00:02 /opt/msys/ecelerity/sbin/ecelerity
64+
```
65+
66+
You can also run a shell inside the container:
67+
```
68+
docker exec -it mta /bin/bash
69+
```
70+
This will give you a shell prompt inside the container, allowing you to run commands from there, including the `ec_console`:
71+
```
72+
me@host:~$ docker exec -it mta /bin/bash
73+
[root@mta /]# hostname
74+
mta.test
75+
[root@mta /]# echo "sysinfo" | sudo -u ecuser /opt/msys/ecelerity/bin/ec_console
76+
Ecelerity Version: 5.0.0.74264 r(msys-ecelerity:tags/5.0.0-ga^0) (64-bit)
77+
build date: Feb 20 2025 (RELEASE)
78+
product name: Ecelerity Momentum
79+
Rocky Linux release 9.5 (Blue Onyx)
80+
Linux mta.test 5.14.0-503.22.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jan 15 08:02:15 EST 2025 x86_64
81+
82+
[root@mta /]# exit
83+
exit
84+
me@host:~$
85+
```

content/momentum/4/4-container.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
lastUpdated: "07/01/2025"
3+
title: "Running Momentum in a Container"
4+
description: "Rationale for running Momentum in a containerized environment, and instructions for doing so."
5+
---
6+
7+
8+
Running Momentum in a container is a strategic move toward simplifying deployment, increasing portability, and standardizing runtime environments through development, staging and production. It allows the MTA to operate as a self-contained, version-controlled unit that can be easily replicated and scaled.
9+
10+
Guidance is provided here to run Momentum inside a Linux-based container.
11+
12+
**NOTES:**
13+
14+
- This feature is *experimental*. We are actively seeking feedback to make Momentum more container-friendly.
15+
- Docker engine and Docker Compose must be installed on the host system where Momentum container will be built and/or run.
16+
- This document assumes familiarity with Docker and containerization concepts. For more information on it, see Docker's [documentation](https://docs.docker.com/).
17+
18+
## <a name="containers.benefits"></a> Rationale
19+
20+
Running Momentum in a container provides several benefits:
21+
- **Portability across environments**: Containers abstract away OS-level differences.
22+
- **Simplified deployment**: Packaging Momentum and its dependencies makes deployments predictable and repeatable.
23+
- **Isolation and stability**: Momentum runs in a sandboxed environment, isolated from the host and other services, minimizing the risk of conflicts with host-level libraries or services.
24+
- **Scalability**: Containers can be easily scaled up or down based on load, allowing for efficient resource utilization.
25+
- **Easier upgrades**: Versioning container images makes it straightforward to deploy a new version of Momentum in parallel with minimum downtime.
26+
- **Better resource management**: Containers can be configured with explicit CPU and memory limits, preventing from consuming unexpected system resources.
27+
- **Fault tolerance and persistence**: By combining containers with persistent volumes, configuration, policies, spooled messages, and logs can be retained across container restarts, ensuring that critical data is not lost.
28+
- **DevOps and automation friendly**: Containers integrate well with CI/CD pipelines, Docker Compose, and orchestration tools (like Kubernetes and Swarm), enabling fast testing, staging, and deployment cycles.
29+
30+
## <a name="containers.planning"></a> Planning for Containerization
31+
32+
Before deploying Momentum in a container, consider the following:
33+
- **Container image**: When building your own image, select a RHEL-compatible base OS and set the proper environment variables.
34+
- **Configuration management**: Plan how to manage configuration and other module files, such as `ecelerity.conf`, Lua scripts, etc. You can use bind mounts or Docker volumes to provide such files to the container.
35+
- **Data persistence**: Likewise, determine how to persist data across container restarts. Use Docker volumes or bind mounts to store spooled messages and logs outside the container. It might be required to handle volume ownership and permissions to ensure Momentum can read/write to these volumes.
36+
- **Networking**: Decide how to expose ports and configure networking. You can use Docker's port mapping to expose the necessary ports for the different Momentum listeners.

content/momentum/4/p-container.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
lastUpdated: "07/01/2025"
3+
title: "Running in a Container"
4+
description: "Instructions for running Momentum as a standalone MTA in a containerized environment based on Docker."
5+
---
6+
7+
Momentum can be run as a standalone MTA in a Docker container.

content/momentum/navigation.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,18 @@
583583
title: Connection Context Variables
584584
- link: /momentum/4/4-policy-context-mess
585585
title: Message Context Variables
586+
- link: /momentum/4/p-container
587+
title: Running in a Container
588+
items:
589+
- link: '/momentum/4/4-container'
590+
title: Running Momentum in a Container
591+
items:
592+
- link: /momentum/4/4-container-building
593+
title: Building an Image
594+
- link: /momentum/4/4-container-running
595+
title: Running and Accessing the Container
596+
- link: /momentum/4/4-container-compose
597+
title: Using Docker Compose
586598
- link: /momentum/4/p-reference
587599
title: Reference
588600
items:

0 commit comments

Comments
 (0)