Simple dynamic port mapping

I want to publish a specific port in my container to a dynamic port allocated by Nomad.

I’ve been playing with Nomad a bit, but I can’t seem to find a clear answer on how to do this simple networking task.

Running a docker container by itself, I can do something like:

docker run -p 3000:3000 my_image:tag

In Nomad, I can configure a static port 3000 for a group and then expose it in the config stanza for a task, easy enough.

However, I need to use dynamic port allocation because I’ll be running several of these at the same time on the same host network. So the equivalent docker command would be:

docker run -p ${NOMAD_PORT_foo}:3000 my_image:tag

There’s docs on exposing the port to the tasks, but how do I have the job map traffic from inside the container on port 3000 to port NOMAD_PORT_foo?

A logical solution (I would’ve thought) would be to pass the docker cli option for port binding as an arg, but that doesn’t seem to be exposed.

This definition, for example, fails because it doesn’t pass these appropriately (and maybe it wouldn’t have worked anyways), but this is the effect I’m trying to achieve.

group "example" {
    network {
        mode = "host"
        port "http" {}
    }

    task "app" {
        driver = "docker"
        image = "app:latest"
        args = ["-p", "${NOMAD_PORT_http}:3000"]
    }
}

Anyone know how to do this?

Note that bridge mode is not always an option for me because that only works on linux hosts and I don’t want to use consul if I don’t have to because my use case is pretty simple at the moment.

You should not use the -p argument when mapping ports in Nomad. Instead, use the ports = [ ] argument in the Docker configuration. There’s more information in the Allocating Ports section of the Nomad Docker task driver documentation. You will also need to use the information in Using the Port Map from the same page since your job doesn’t seem to expect to find the port configuration in the environment.

I made an example container based on the Dockerizing a Node.js web app example , which uses 8080 as the application’s port. Here’s the configuration that I used to connect it to my Nomad-generated port.

job "webapp" {
	datacenters = ["dc1"]

	group "example" {
		network {
			mode = "host"
			port "http" {
				to = "8080"
			}
		}

		task "app" {
			driver = "docker"

			config {
				image = "voiselle/node-web-app"
				ports = ["http"]
			}
		}
	}
}

Hopefully this gets you unstuck.

Best,
Charlie

Thanks for the help! This got me going for sure, I guess I was confused by the “to/from” difference between nomad/docker.

Thanks again!

1 Like