Passing local config file to task

Hey Mike,

The artifact stanza is not parsed until the job is starting on the client, so files specified in the source attribute are resolved relative to the client—specifically the task’s working directory in the allocation’s filesystem—not the submitting user.

If you do not want to use a hosted location, then another option is via the job file itself. For small files and simple configurations, this is okay. An important thing to remember is that the entire job specification is stored in the server’s memory until the job is eligible for garbage collection, so this is a consideration for things like batch jobs or jobs where there are a significant number of them running or waiting to be eligible for garbage collection.

You can use the template stanza to write one or more files to the allocation as it starts. For a very static job, you might even insert the configuration directly in the job using the data attribute and the heredoc syntax. However, if you want to keep the content separate from the job but also use a local file, you can combine the template stanza, an HCL2 input variable, and the HCL2 file function.

HCL2 functions run before the job is submitted to the cluster, so the file function writes the specified file’s contents directly in place as the value of the template’s data attribute. You can supply the path as a constant or use an HCL2 input variable to make it runtime specific.

To use the file function, your job would look something like this:

variable "redis_config_file" {
  type = string
  description = "local path to the redis configuration to inject into the job."
}

job "example" {
  region = "global"
  datacenters = ["dc1"]
  type = "service"
  group "services" {
    count = 1
    network {
      mode = "host"
      port "redis" {
        static = 6379
      }
    }
    task "redis" {
      driver = "docker"

      template {
        destination = "local/redis.conf"
        data = file(var.redis_config_file)
      }

      volume_mount {
        volume      = "redis-data"
        destination = "/data"
        read_only   = false
      }

      config {
        image      = "redis:6.2.1-alpine3.13"
        ports      = ["redis"]
        force_pull = false
        args = [
          "redis-server",
          "/redis.conf",
        ]
        mounts = [
          {
            type   = "bind"
            source = "local/redis.conf"
            target = "/redis.conf"
          },
        ]
      }
    }
  }
}

Embedding artifacts in the job specification should be done with care, because the job specifications are stored in Server memory for the lifecycle of the object and until it is garbage collected.

You can put the variable stanza anywhere in the job. I tend to put them at the top of the job, but that is a stylistic preference.

To run the above job, you would need to provide the path to the local redis.conf file by flag (-var redis_config_file=./redis/redis.conf) or environment variable ( NOMAD_VAR_redis_config_file=./redis/redis.conf).

Here is a more complete example of the command using flags.

$ nomad job run -var redis_config_file=./redis/redis.conf example.nomad

Hope this help get you going!

Best,
-cv


Charlie Voiselle
Product Education Engineer, Nomad

5 Likes