This gist demonstrates how to run a docker container with nomad, using a wrapper script.
With the wrapper, we can more easily run the container in the way we need to and without being limited by Nomad's docker driver. For example, while Nomad will have great support for volumes in the future, it has no such support right now, and the driver does not expose a config parameter to tune the volumes mounted in the docker container. This is also a great way to use consul to lookup services before starting your app, or to retrieve credentials from Vault. When running legacy applications with nomad, the wrapper script is the place to put that type of look-up logic.
We use a wrapper script and the raw_exec
driver to run the container with the parameters we need.
Also, in the real-world, we sometimes run home-grown tools that may have external dependencies, funny expectations, or parameters that should be enabled if other parameters have been. In my experience, it's been easier to have Nomad run these types of apps with the help of a wrapper script.
Why not call docker directly? A wrapper script makes it easy to work with the docker workflow, details like needing to stop and remove the named container before creating a new one.
- Place
run-postgres
in some$PATH
, such as/usr/local/bin/run-postgres
. Keep in mind, that wrapper script will need to exist on the hosts that could run the nomad job. - If you wish to limit the hosts where this job can run, configure a constraint with those agents. For example, to flag specific hosts as in the
database
tier, add the following to those agents'config.json
:
"meta": {
"tier": "database"
},
- Copy
postgres.hcl
somewhere, and edit it. Be sure to update thedatacenters
and constraints nomad run postgres.hcl
If that was successful, you'll see good things with nomad status postgres
, and the container should show up with docker ps
- This wrapper is in python, however you can use whatever language you wish for the wrapper with raw_exec
- This method uses the
raw_exec
driver, and so isolation is reduced - The way the docker-py works, it's a bit cumbersome/awkward to create a completely generic wrapper script, and each time I have done this, the app has had significantly different desires, so I have generally written a wrapper for each app I wish to run, rather than one wrapper to rule them all.
- This example uses a non-unique name for the docker container, you might also want to use
NOMAD_TASK_NAME
to pass that on through - The
PGDATA
env var is used to specify the path to mount into the docker container, this maps to docker's--workdir
. - If the container fails for some reason (after starting), the script will exit and the job will show up as stopped/failed in nomad (which will then restart you job, depending on the job's restart policy).
- If you stop the job with
nomad stop postgres
, the script will exit, but the docker container will stay running. The script will attempt to stop/remove a running container when it starts, so that is fine for updates. Usedocker stop postgres
if you absolutely need to stop the container manually. The script can also include a signal handler that catches the signal from nomad and stops the container for you.