A containerizer is a Mesos agent component responsible for launching containers, within which you can run a Marathon app. Running apps in containers offers a number of benefits, including the ability to isolate tasks from one another and control task resources programmatically.
Marathon enables users to launch containers with container images using two different runtimes:
The Universal Container Runtime (UCR) extends the Mesos containerizer to support provisioning Docker container images (AppC which is deprecated in v1.8). This means that you can use both the Mesos containerizer and other container image types. You can still use the Docker container runtime directly (instructions are below), but the Universal Container Runtime supports running Docker images without depending on the Docker Engine, which allows for better integration with Mesos.
The following Marathon features only work with the UCR:
To provision containers with the UCR, specify the container type MESOS
and a the appropriate object in your application definition. Here, we specify a Docker container with the docker
object.
The UCR containerizer provides a pullConfig
parameter with a secret
field for authentication with a private Docker registry.
credential
, with a principal
and an optional secret
field to authenticate when downloading the Docker image.
{
"id":"mesos-docker",
"container":{
"docker":{
"image":"mesosphere/inky",
"pullConfig": {
"secret": "pullConfigSecret"
}
},
"type":"MESOS"
},
"secrets": {
"pullConfigSecret": {
"source": "/mesos-docker/pullConfig"
}
"args":[
"<my-arg>"
],
"cpus":0.2,
"mem":16.0,
"instances":1
}
Important: If you leave the args
field empty, the default entry point will be the launch command for the container. If your container does not have a default entry point, you must specify a command in the args
field. If you do not, your app will fail to deploy.
The Docker containerizer relies on the external Docker engine runtime to provision the containers.
DC/OS clusters are already configured to run Docker containers, so DC/OS users do not need to follow the configuration steps below.
```bash
$ echo 'docker,mesos' > /etc/mesos-slave/containerizers
```
Increase the executor timeout to account for the potential delay pulling a docker image to the agent node.
$ echo '10mins' > /etc/mesos-slave/executor_registration_timeout
Restart the agent process to load the new configuration.
Increase the Marathon command line option
--task_launch_timeout
to at least the executor timeout, in milliseconds,
you set on your agent nodes in the previous step.
To use the native container support, add a container
field to your
app definition JSON:
{
"container": {
"type": "DOCKER",
"docker": {
"network": "HOST",
"image": "group/image"
},
"volumes": [
{
"containerPath": "/etc/a",
"hostPath": "/var/data/a",
"mode": "RO"
},
{
"containerPath": "/etc/b",
"hostPath": "/var/data/b",
"mode": "RW"
}
]
}
}
where volumes
and type
are optional (the default type is DOCKER
). More
container types may be added later.
For convenience, the mount point of the Mesos sandbox is available in the
environment as $MESOS_SANDBOX
.
Note: Requires Mesos 0.20.1 and Marathon 0.7.1
Bridged networking makes it easy to run programs that bind to statically configured ports in Docker containers. Marathon can “bridge” the gap between the port resource accounting done by Mesos and the host ports that are bound by Docker.
Dynamic port mapping:
Let’s begin by taking an example app definition:
{
"id": "bridged-webapp",
"cmd": "python3 -m http.server 8080",
"cpus": 0.5,
"mem": 64.0,
"instances": 2,
"networks": [ { "mode": "container/bridge" } ],
"container": {
"type": "DOCKER",
"docker": {
"image": "python:3"
},
"portMappings": [
{ "containerPort": 8080, "hostPort": 0, "servicePort": 9000, "protocol": "tcp" },
{ "containerPort": 161, "hostPort": 0, "protocol": "udp"}
]
},
"healthChecks": [
{
"protocol": "HTTP",
"portIndex": 0,
"path": "/",
"gracePeriodSeconds": 5,
"intervalSeconds": 20,
"maxConsecutiveFailures": 3
}
]
}
Here "hostPort": 0
retains the traditional meaning in Marathon, which is “a
random port from the range included in the Mesos resource offer”. The resulting
host ports for each task are exposed via the task details in the REST API and
the Marathon web UI. "hostPort"
is optional and defaults to 0
.
“containerPort” refers to the port the application listens to inside of the container.
Since v0.9.0: "containerPort"
is optional and now defaults to 0
.
When "containerPort": 0
, Marathon assigns
the container port the same value as the assigned hostPort
. This is especially useful for apps that
advertise the port they are listening on to the outside world for P2P communication. Without “containerPort”: 0 they
would erroneously advertise their private container port which is usually not the same as the externally visible host
port.
"servicePort"
is a helper port intended for doing service discovery using
a well-known port per service. The assigned servicePort
value is not used/interpreted by Marathon itself but
supposed to be used by the load balancer infrastructure.
See Service Discovery Load Balancing doc page.
The servicePort
parameter is optional
and defaults to 0
. Like hostPort
, If the value is 0
, a random port will
be assigned. If a servicePort
value is assigned by Marathon then Marathon guarantees that its value
is unique across the cluster. The values for random service ports are in the
range [local_port_min, local_port_max]
where local_port_min
and
local_port_max
are command line options with default values of 10000
and
20000
, respectively.
The "protocol"
parameter is optional and defaults to "tcp"
. Its possible values are "tcp"
and "udp"
.
Static port mapping:
It’s also possible to specify non-zero host ports. When doing this
you must ensure that the target ports are included in some resource offers!
The Mesos agent node announces port resources in the range [31000-32000]
by
default. This can be overridden; for example to also expose ports in the range
[8000-9000]
:
--resources="ports(*):[8000-9000, 31000-32000]"
See the network configuration documentation for more details on how Docker handles networking.
See the private registry
documentation for more details on how to initiate a docker pull
from a private docker registry
using Marathon.
Marathon 0.8.2 with Mesos 0.22.0 supports an option to force Docker to pull the image before launching each task.
{
"type": "DOCKER",
"docker": {
"image": "group/image",
"forcePullImage": true
}
}
As of version 0.7.0, Marathon supports an args
field in the app JSON. It is
invalid to supply both cmd
and args
for the same app. The behavior of cmd
is as in previous releases (the value is wrapped by Mesos via
/bin/sh -c '${app.cmd}
).
This new ("args"
) mode of specifying a command allows for safe usage of
containerizer features like custom Docker ENTRYPOINT
s. For example, given
the following Dockerfile with an ENTRYPOINT
defined:
FROM busybox
LABEL maintainer="support@mesosphere.io"
CMD ["inky"]
ENTRYPOINT ["echo"]
Supplying the following app definition will download the public
“mesosphere/inky” Docker container
and execute echo hello
:
{
"id": "inky",
"container": {
"docker": {
"image": "mesosphere/inky"
},
"type": "DOCKER",
"volumes": []
},
"args": ["hello"],
"cpus": 0.2,
"mem": 32.0,
"instances": 1
}
Named arguments can be passed as an array of consecutive argc, argv
tuples,
e.g.:
"args": [
"--name", "etcd0",
"--initial-cluster-state", "new"
]
Starting with version 0.7.6, Marathon supports two new keys for docker
containers: privileged
and parameters
. The privileged
flag allows users
to run containers in privileged mode. This flag is false
by default. The
parameters
object allows users to supply arbitrary command-line options
for the docker run
command executed by the Mesos containerizer. Note that
any parameters passed in this manner are not guaranteed to be supported in
the future, as Mesos may not always interact with Docker via the CLI.
{
"id": "privileged-job",
"container": {
"docker": {
"image": "mesosphere/inky",
"privileged": true,
"parameters": [
{ "key": "hostname", "value": "a.corp.org" },
{ "key": "volumes-from", "value": "another-container" },
{ "key": "lxc-conf", "value": "..." }
]
},
"type": "DOCKER",
"volumes": []
},
"args": ["hello"],
"cpus": 0.2,
"mem": 32.0,
"instances": 1
}