Microservices Deployment Using Nomad on Ubuntu

Published on December 14, 2023

Sr Technical Writer

Microservices Deployment Using Nomad on Ubuntu


The world of DevOps and container orchestration is constantly changing, and picking the right tool can make a big difference in how efficiently microservices are deployed. One tool that stands out is HashiCorp Nomad. In this guide, we’ll dive into how you can deploy a simple microservice using Nomad on a DigitalOcean Droplet running Ubuntu server.

Nomad is a lightweight workload scheduler that manages application deployment and scaling across a cluster of machines. It supports multiple workload types, integrates with other HashiCorp tools, and is infrastructure agnostic. Nomad’s simplicity, versatility, scalability, resource efficiency, and integration make it an excellent choice for deploying and managing microservices.

Check out Nomad’s official documentation and its Comparison guide for more details and features.


Before we begin, make sure you have the following installed:

  • Doctl installed and configured on your system, which will be used to deploy a DigitalOcean Droplet running Ubuntu server.


Step 1: Deploy a DigitalOcean Droplet using ‘doctl’

First and foremost, you will need to get the SSH-key-id and Access Token, which will be used to run the doctl command to create a Droplet.

Let’s set things up:

  1. You can get your SSH-key-id using the command:
doctl compute ssh-key list
  1. You can create an access token here: Create Access Token

Now, let’s create an Ubuntu Droplet:

doctl compute droplet create my-droplet --size s-2vcpu-4gb --region nyc1 --image ubuntu-22-04-x64 --ssh-keys <YOUR_SSH_KEY_ID> --access-token '<ACCESS_TOKEN>' --output json"

The above command creates a new DigitalOcean Droplet named “my-droplet” with a specified size, region, image,SSH key ID and access token.

You can use the following command to get the supported sizes for Droplets and their hourly and monthly prices:

doctl compute size list

You can refer to the doctl commands reference to learn more and play around with doctl.

Now, to SSH into your Ubuntu Droplet, we will first need the Public IP of the Droplet, which can be found using the following doctl command:

doctl compute droplet get my-droplet

Note the Public IPv4 address from the above command and then SSH to the Droplet from your local server.

Once you know the Public IPv4 address of your Ubuntu Droplet, you will need to add SSH keys to connect to your Droplet remotely from your local system via SSH.

Now that you have added your SSH keys, you can log in to the Ubuntu Droplet remotely via SSH:

ssh root@<PUBLIC_IP>

Step 2: Installing Nomad and Docker Engine on your Droplet

You can refer to the following guides to install Nomad and Docker engine on an Ubuntu server:

  • Nomad installed on your DigitalOcean Ubuntu Droplet.

  • Docker Engine installed and running on your Ubuntu Droplet.

Step 3: Setting up Nomad

Once you have the Ubuntu Droplet deployed with Nomad and Docker installed, you can start Nomad in “dev mode” using the following command in the terminal:

nomad agent -dev

You will observe an output like the one below:

==> No configuration files loaded ==> Starting Nomad agent... ==> Nomad agent configuration: Advertise Addrs: HTTP:; RPC:; Serf: Bind Addrs: HTTP: []; RPC:; Serf: Client: true Log Level: DEBUG Node Id: 51b0f49b-564b-5d1c-8e99-a17336c2a597 Region: Global (DC: dc1) Server: true Version: 1.6.2 ==> Nomad agent started! Log data will stream in below: 2023-12-05T18:43:58.414+0530 [INFO] nomad.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:e707dbd2-be06-7cfc-dff0-a11714eec76f Address:}]" 2023-12-05T18:43:58.415+0530 [INFO] nomad.raft: entering follower state: follower="Node at [Follower]" leader-address= leader-id=

This will start the Nomad agent on your machine as the server and client components. In dev mode, Nomad runs on a single node and does not persist in any data, making it ideal for experimentation and development.

Once the Nomad agent starts running, you can access the Nomad web user interface by visiting http://localhost:4646 in your browser. In our case, we need some tunneling to access the Nomad UI from our Ubuntu Server. We can use Pinggy, a tool that provides Public URLs for Localhost. It generates a temporary URL through which one can access the Nomad UI.

ssh -p 443 -R0:localhost:4646 -L4300:localhost:4300 qr@a.pinggy.io

Copy and run the above SSH command on your Ubuntu server to get Nomad UI URLs that can be accessed from your phone browser or any other device.

image alt text

Copy the URLs displayed in the above screenshot.

image alt text

Here is the Nomad UI. You can view the Job details, details of the deployment, etc, from this UI throughout the tutorial.

Step 4: Nomad Job Specification

Nomad jobs are defined by the Nomad job specification, also known as “jobspec”. The job spec schema is written in HCL.

The job specification is divided into smaller sections, which you can find in the navigation menu. Nomad HCL is parsed in the command line and then sent to Nomad in JSON format via the HTTP API.

Let’s talk about each in a bit more detail:

  • task - Nomad uses tasks as the smallest unit of work. These tasks are executed by task drivers such as docker or exec, which allow Nomad to be flexible in the tasks it supports. Tasks specify their required task driver, configuration for the driver, constraints, and resources required.

  • group -A group refers to a set of tasks that are executed on a single Nomad client."

  • Job - A job is the core unit of control for Nomad and defines the application and its configurations. It can contain one or many tasks.

  • job specification - A job specification, also known as a jobspec defines the schema for Nomad jobs. This describes the type of job, the tasks and resources necessary for the job to run, job information like which clients it can run on, and more.

  • allocation - An allocation is a mapping between a task group in a job and a client node. When a job is run, Nomad will choose a client capable of running it and allocate resources on the machine for the task(s) in the task group defined in the job.

The above constructs make up a Job in Nomad.

Now that Nomad is operational, we can schedule our first job. Our initial task will involve running the http-echo Docker container. This straightforward application generates an HTML page displaying the arguments passed to the http-echo process, such as “Hello World”. The process dynamically listens on a port specified by another argument.

Let’s create a job file that ends with the name “microservice.nomad”—all the job files in Nomad end with .nomad suffix .

job "http-microservice" {
  datacenters = ["dc1"]
  group "echo" {
    count = 1
    task "server" {
      driver = "docker"
      config {
        image = "hashicorp/http-echo:latest"
        args  = [
          "-listen", ":${NOMAD_PORT_http}",
          "-text", "Hello and welcome to ${NOMAD_IP_http} running on port ${NOMAD_PORT_http}. This is my first microservice deployment using Nomad.",
      resources {
        network {
          mbits = 10
          port "http" {}

In this example, we defined a job called http-microservice, set the driver to use docker, and passed the necessary text and port arguments to the container. As we need network access to the container to display the resulting webpage, we define the resources section as requiring a network with a port that Nomad dynamically chooses from the host machine to the container during runtime.

Nomad supports using dynamic port assignment, i.e., you don’t need to specify a port.

Step 5: Running the Nomad Job

We can submit/run new or update existing jobs with the nomad job run command, using job files that conform to the job specification format.

nomad job run microservice.nomad


==> 2023-12-06T13:58:25+05:30: Monitoring evaluation "bd6dd191" 2023-12-06T13:58:25+05:30: Evaluation triggered by job "http-microservice" 2023-12-06T13:58:25+05:30: Evaluation within deployment: "b8499a02" 2023-12-06T13:58:25+05:30: Evaluation status changed: "pending" -> "complete" ==> 2023-12-06T13:58:25+05:30: Evaluation "bd6dd191" finished with status "complete" ==> 2023-12-06T13:58:25+05:30: Monitoring deployment "b8499a02" ✓ Deployment "b8499a02" successful 2023-12-06T13:58:25+05:30 ID = b8499a02 Job ID = http-microservice Job Version = 0 Status = successful Description = Deployment completed successfully Deployed Task Group Desired Placed Healthy Unhealthy Progress Deadline echo 1 1 1 0 2023-12-06T14:08:23+05:30

image alt text

We can check the status of a job using the command:

nomad job status http-microservice
ID = http-microservice Name = http-microservice Submit Date = 2023-12-13T13:44:55+05:30 Type = service Priority = 50 Datacenters = dc1 Namespace = default Node Pool = default Status = running Periodic = false Parameterized = false Summary Task Group Queued Starting Running Failed Complete Lost Unknown echo 0 0 1 0 0 0 0 Latest Deployment ID = 9a72c817 Status = successful Description = Deployment completed successfully Deployed Task Group Desired Placed Healthy Unhealthy Progress Deadline echo 1 1 1 0 2023-12-13T14:00:33+05:30 Allocations ID Node ID Task Group Version Desired Status Created Modified 84d70c8f aa3f6a1a echo 0 run running 5m19s ago 5m6s ago

Please make a note of the allocation ID in the above output:84d70c8f. Allocation ID is used to troubleshoot deployment issues in Nomad.

You can also access the Nomad UI using the below command to check the Jobs and other important details of your deployment on your local desktop:

nomad ui <job_name>

In our case:

nomad ui http-microservice

We can use the command nomad alloc-status <allocation_id> to get the port on which the microservice is deployed. When deploying jobs with dynamic ports, finding the exact port on which a specific task has been deployed can be challenging because the port is dynamically allocated at runtime. This command is also great for troubleshooting any deployment issues in Nomad.

We can get the allocation_id using the command nomad job status http-microservice specified in the above section.

nomad alloc-status 84d70c8f


ID = 84d70c8f-0687-e1c7-27fe-172ae274580b Eval ID = 404f0d71 Name = http-microservice.echo[0] Node ID = aa3f6a1a Node Name = XXXXXXXX Job ID = http-microservice Job Version = 0 Client Status = running Client Description = Tasks are running Desired Status = run Desired Description = <none> Created = 11m3s ago Modified = 10m50s ago Deployment ID = 9a72c817 Deployment Health = healthy Task "server" is "running" Task Resources: CPU Memory Disk Addresses 0/100 MHz 9.0 MiB/300 MiB 300 MiB http: Task Events: Started At = 2023-12-13T08:20:23Z Finished At = N/A Total Restarts = 0 Last Restart = N/A Recent Events: Time Type Description 2023-12-13T13:50:23+05:30 Started Task started by client 2023-12-13T13:50:20+05:30 Driver Downloading image 2023-12-13T13:50:19+05:30 Task Setup Building Task Directory 2023-12-13T13:50:19+05:30 Received Task received by client

From the above, we can make a note of the address on which the microservice is running, which is, and send a curl request to get the status of the microservice.

curl -i
curl: (56) Recv failure: Connection reset by peer anish@W2MK93VGYX nomad.d % curl -i HTTP/1.1 200 OK X-App-Name: http-echo X-App-Version: 1.0.0 Date: Wed, 13 Dec 2023 08:24:59 GMT Content-Length: 108 Content-Type: text/plain; charset=utf-8 Hello and welcome to running on port 20004. This is my first microservice deployment using Nomad.

We can verify that the microservice has been successfully deployed from the above.

Scaling up our App

One of the key benefits of using Nomad is its ability to scale your microservices based on demand. To scale up your job, simply modify the job file to increase the count parameter or use the nomad job scale <job> <count> command.

Let’s scale our hello-world microservice:

nomad job scale http-microservice 3


2023-12-05T19:28:45+05:30: Evaluation status changed: "pending" -> "complete ==> 2023-12-05T19:28:45+05:30: Evaluation "84241aca" finished with status "complete" ==> 2023-12-05T19:28:45+05:30: Monitoring deployment "a26236c7" ✓ Deployment "a26236c7" successful 2023-12-05T19:28:58+05:30 ID = a26236c7 Job ID = http-microservice Job Version = 1 Status = successful Description = Deployment completed successfully Deployed Task Group Desired Placed Healthy Unhealthy Progress Deadline echo 3 3 3 0 2023-12-05T19:38:57+05:30**

On the Nomad UI(http://localhost:4646/ui/jobs), we can see the changes being reflected on the go:

image alt text

Some additional features and concepts you can explore in Nomad

Nomad offers a range of advanced features and concepts that can further enhance your deployment strategy:

1. Task Drivers:

Nomad supports multiple task drivers, allowing you to choose the best runtime environment for your applications. Explore different task drivers for various workload types.

2. Task Groups:

Organize your tasks into groups for logical separation and resource allocation. Task groups enable you to define specific constraints and settings for different sets of tasks.

3. Update Policies:

Nomad provides flexible update policies for controlling how your jobs are updated. Explore strategies like rolling updates to ensure zero downtime during deployments.

4. Service Discovery:

Utilize Nomad’s integration with Consul for seamless service discovery. This is crucial for dynamic microservices architectures where services need to locate and communicate with each other.


Congratulations! You’ve successfully deployed a simple microservice and explored some advanced features of Nomad. Nomad’s simplicity, versatility, and integration capabilities make it a compelling choice for DevOps engineers managing microservices at scale. Consider exploring more features and integrating Nomad into your broader infrastructure to maximize efficiency and scalability.

You can check out Nomad’s tutorial library and its comprehensive and detailed introduction guide to gain deeper insights into using Nomad.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar

Sr Technical Writer

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel