Skip to content

Deployer une application avec Nomad

Guide pour déployer des applications sur Nomad, avec ou sans Docker.

Structure des fichiers

~/labs/nomad/
├── nomad-config.hcl      # Configuration de l'agent Nomad
├── mon-app.nomad.hcl     # Job file pour mon-app
└── autre-app.nomad.hcl   # Job file pour autre-app

Les fichiers de job (.nomad.hcl) peuvent aussi être placés dans le dossier du projet :

~/labs/apps/mon-projet/
├── src/
├── mon-projet.nomad      # Job file colocalisé avec le code
└── ...

Prérequis

Nomad doit être installé et configuré. Fichier de configuration minimal (~/labs/nomad/nomad-config.hcl) :

datacenter = "dc1"
data_dir   = "/tmp/nomad"

client {
  enabled = true
}

server {
  enabled          = true
  bootstrap_expect = 1
}

plugin "docker" {
  config {
    volumes {
      enabled = true
    }
  }
}

Lancer Nomad :

sudo nomad agent -dev -config=nomad-config.hcl

Avec Docker

Exemple 1 : Site statique avec nginx

Fichier : ~/labs/nomad/docs.nomad.hcl

job "docs" {
  datacenters = ["dc1"]
  type = "service"

  group "web" {
    network {
      port "http" {
        static = 8001
        to     = 80
      }
    }

    task "nginx" {
      driver = "docker"

      config {
        image = "nginx:alpine"
        ports = ["http"]

        # Monte le dossier local ~/labs/docs/site dans /usr/share/nginx/html du container
        volumes = [
          "/home/user/labs/docs/site:/usr/share/nginx/html:ro"
        ]
      }

      resources {
        cpu    = 50
        memory = 32
      }
    }
  }
}

Deployer :

nomad job run ~/labs/nomad/docs.nomad.hcl

Exemple 2 : Application PHP

Fichier : ~/labs/nomad/mon-app-php.nomad.hcl

job "mon-app-php" {
  datacenters = ["dc1"]
  type        = "service"

  group "web" {
    count = 1

    network {
      port "http" {
        static = 8080
        to     = 80
      }
    }

    task "php" {
      driver = "docker"

      config {
        image = "php:8.4-cli"
        args  = ["-S", "0.0.0.0:80", "-t", "/app"]
        ports = ["http"]

        # Monte le dossier local ~/labs/apps/mon-app dans /app du container
        volumes = [
          "/home/user/labs/apps/mon-app:/app:ro"
        ]
      }

      resources {
        cpu    = 200
        memory = 128
      }
    }
  }
}

Deployer :

nomad job run ~/labs/nomad/mon-app-php.nomad.hcl

Exemple 3 : Application Node.js

Fichier : ~/labs/nomad/api-node.nomad.hcl

job "api-node" {
  datacenters = ["dc1"]
  type        = "service"

  group "api" {
    network {
      port "http" {
        static = 3000
        to     = 3000
      }
    }

    task "node" {
      driver = "docker"

      config {
        image = "node:20-alpine"
        ports = ["http"]
        command = "node"
        args = ["server.js"]

        # Monte le dossier local ~/labs/apps/mon-api dans /app du container
        volumes = [
          "/home/user/labs/apps/mon-api:/app"
        ]

        work_dir = "/app"
      }

      resources {
        cpu    = 200
        memory = 256
      }
    }
  }
}

Deployer :

nomad job run ~/labs/nomad/api-node.nomad.hcl

Sans Docker (driver exec/raw_exec)

Pour exécuter des binaires directement sur l'hôte sans conteneur.

Exemple 1 : Script Python

job "api-python" {
  datacenters = ["dc1"]
  type        = "service"

  group "api" {
    network {
      port "http" {
        static = 5000
      }
    }

    task "flask" {
      driver = "raw_exec"

      config {
        command = "/usr/bin/python3"
        args    = ["/home/user/app/main.py"]
      }

      env {
        FLASK_PORT = "${NOMAD_PORT_http}"
      }

      resources {
        cpu    = 200
        memory = 256
      }
    }
  }
}

Exemple 2 : Binaire Go/Rust

job "mon-service" {
  datacenters = ["dc1"]
  type        = "service"

  group "app" {
    network {
      port "http" {
        static = 8080
      }
    }

    task "server" {
      driver = "raw_exec"

      config {
        command = "/home/user/bin/mon-serveur"
        args    = ["--port", "${NOMAD_PORT_http}"]
      }

      resources {
        cpu    = 100
        memory = 64
      }
    }
  }
}

Exemple 3 : Service systemd-like

job "worker" {
  datacenters = ["dc1"]
  type        = "service"

  group "background" {
    task "processor" {
      driver = "raw_exec"

      config {
        command = "/bin/bash"
        args    = ["-c", "while true; do /home/user/scripts/process.sh; sleep 60; done"]
      }

      resources {
        cpu    = 100
        memory = 128
      }
    }
  }
}

Commandes utiles

Deployer un job

nomad job run mon-job.nomad

Voir le statut

nomad job status mon-job

Voir les logs

nomad alloc logs <alloc-id>

Arreter un job

nomad job stop mon-job

Lister les jobs actifs

nomad job status

Configuration reseau

Option Description
static Port fixe sur l'hôte
to Port dans le conteneur (Docker)
Sans static Port dynamique assigné par Nomad

Port dynamique

network {
  port "http" {}  # Nomad assigne un port disponible
}

Accéder au port dynamique dans la task :

env {
  PORT = "${NOMAD_PORT_http}"
}

Drivers disponibles

Driver Usage
docker Conteneurs Docker
exec Binaires isolés (chroot)
raw_exec Binaires sans isolation
java Applications Java
qemu Machines virtuelles

Ressources

Les ressources limitent ce que la task peut consommer :

resources {
  cpu    = 500   # MHz
  memory = 256   # MB
}