According to the Marathon documentation:
servicePort: When you create a new application in Marathon (either through the REST API or the front end), you may assign one or more service ports to it. You can specify all valid port numbers as service ports or you can use 0 to indicate that Marathon should allocate free service ports to the app automatically. If you do choose your own service port, you have to ensure yourself that it is unique across all of your applications.
Let me elaborate on this in the light of the two main network configurations for Marathon, giving some information about them while I'm at it.
Host Mode
Use: default option for Docker applications, only option for non-Docker applications
Under this configuration your application will bind directly to ports of the host.
Without using service ports
You can ask Marathon to provide you with, say, any two ports from the host, same which you want to feed to your application. There are two ways to do this in your application configuration file:
"ports": [
0, 0
],
or
"portDefinitions": [
{"port": 0}, {"port": 0}
],
By doing this Marathon will reserve two ports from the available port range and assign them to the environment variables
PORT1
, and PORT2
.
It is very easy then to invoke them directly in your Dockerfile
:
CMD ./launch.sh --listen-on $PORT1 --monitor-on $PORT2
or in your cmd
definition in your Marathon configuration:
"cmd": "./launch.sh --listen-on $PORT1 --monitor-on $PORT2"
Using service ports
Say you are running your application in several hosts (running several instances) and you want to be able to connect to your app on any host in a specific port. That is when service ports come in the picture.
By writing in your configuration file:
"ports": [
3000, 3001
],
or:
"portDefinitions": [
{"port": 3000}, {"port": 3001}
],
... Marathon will STILL assign random ports on the host, it will STILL assign them to the environment variables PORT1
and PORT2
, AND it will also reserve the ports 3000 and 3001 for you to use.
It is up to you to use a service discovery mechanism to route traffic from those service ports to $PORT1
and $PORT2
.
You can make service ports equal to host ports (for example if you want to avoid having a service discovery mechanism) and have consistent ports for your app across hosts. You can do so by adding "requirePorts": true
after your ports specification.
The caveat here is that Marathon will only be able to schedule your application in nodes that have these ports available.
Bridge Mode
Use: for Docker applications only
Under this configuration a few specified container ports are bound to host ports.
Without using service ports
In this mode you don't use the "ports" or the "portDefinitions" directives, you use "portMappings" instead. By doing so you are effectively telling Docker to map traffic from specific container ports to host ports and vice versa.
You can map container ports to host ports by specifying:
"portMappings": [
{ "containerPort": 80, "hostPort": 0, "protocol": "tcp"},
{ "containerPort": 443, "hostPort": 0, "protocol": "tcp"}
]
In this case:
- Setting hostPort
to 0 makes it, again, choose a random port from the
available port range. Again these ports are assigned to PORT1
and
PORT2
env variables respectively.
- Setting containerPort
to 0 will make it be equal to hostPort
.
Using service ports
As before, you can enable service ports that will be consistent for you application across hosts by specifying them in your config as follows:
"portMappings": [
{ "containerPort": 80, "hostPort": 0, "protocol": "tcp", "servicePort": 3000},
{ "containerPort": 443, "hostPort": 0, "protocol": "tcp", "servicePort": 3001}
]
Once again it is up to you to use a service discovery mechanism to route traffic from those service ports to $PORT1
and $PORT2
.
For more information see:
Marathon ports:
https://mesosphere.github.io/marathon/docs/ports.html
Docker host mode:
http://www.dasblinkenlichten.com/docker-networking-101-host-mode/
Docker bridge mode:
http://www.dasblinkenlichten.com/docker-networking-101/