How to Deploy Adonis Applications to Azure with Nanobox

AdonisJs is a web framework build with Node.js. It's a scoop of fresh air drizzled with elegant syntax, favoring developer joy and stability over anything else. Microsoft Azure is Microsoft's cloud offering built for deploying and managing applications on their global network of data centers.

In this article, I'm going to walk through deploying an Adonis application to Azure using Nanobox. Nanobox uses Docker to build local development and staging environments, as well as scalable, highly-available production environments on Azure.

Before You Begin

If you haven't already, create a free Nanobox account and download Nanobox Desktop.

Setup An Adonis Project

Prerequisite: This guide assumes you already have Node and NPM installed. If not, you can quickly install Node (which includes NPM) and return.

Where to start:

Starting From Scratch

Install adonisjs/cli and create a new app:

# install adonisjs/cli
npm i -g @adonisjs/cli

# create a new app
adonis new nanobox-adonis

# change into your new app and test it (optional)
cd nanobox-adonis && adonis serve --dev

NOTE: If you want to use adonis serve with Nanobox (rather than npm start) you'll either need to ensure that @adonisjs/cli is included in your package.json or install it as an extra_step in your boxfile.yml

Configure Your App

Nanobox uses a simple yaml config file called the boxfile.yml to build and configure your app's environment.

Add a boxfile.yml

Create a boxfile.yml in the root of your project with the following:

run.config:
  engine: nodejs
  extra_packages:
    - nginx

web.main:
  start:
    nginx: nginx -c /app/etc/nginx.conf
    adonis: npm start

data.db:
  image: nanobox/postgresql:9.6

NOTE: You may need to modify some boxfile configurations specific to your project (such as the database). You'll find more info on this in the docs and guides.

Test Your App Locally (optional)

Nanobox provides a local development environment that allows you to run your app locally before you deploy it.

# (optional) add a DNS alias to access your app from the browser
nanobox dns add local adonis.local

# start your app
nanobox run npm start

If you added a DNS alias, access your app at adonis.local:3333. If not, you can access it via the IP provided in the console after you've started your server.

Whenever you exit out of the Nanobox console, it'll shut down your VM and drop you back into your host OS.

Configure Adonis

IMPORTANT: Whether you created the application yourself or with the generator, there are three important pieces of configuration that every application must have:

  • Your app must bind to all IP's (0.0.0.0). Why?
  • Your app must listen on port 8080. Why?
  • Your app must use environment variables (evars) to connect to Nanobox services. Why?

Find your .env file and update it to bind to all IP's:

# .env
HOST=0.0.0.0

Update the Database Connection

When Nanobox spins up a database, it generates environment variables (evars) for the necessary connection credentials.

You can access the following evars when configuring your database connection:

process.env.DATA_DB_HOST
process.env.DATA_DB_USER
process.env.DATA_DB_PASS

The following is an example database configuration using Postgres:

Install a Database Adapter

# install your database adapter (in this case postgres) and save it as a dependency
npm i pg-promise --save

NOTE: If you're using a different database (such as MongoDB) you'll need to install the corresponding adapter.

Create a Database Connection

Update config/database.js to connect using Nanobox evars:

pg: {
  client: 'pg',
  connection: {
    host: Env.get('DATA_DB_HOST', 'localhost'),
    port: Env.get('DB_PORT', ''),
    user: Env.get('DATA_DB_USER', 'root'),
    password: Env.get('DATA_DB_PASS', ''),
    database: Env.get('DB_DATABASE', 'adonis')
  }
}

Update your .env file to use the correct adapter (in this example that would be pg) and connect to the correct database and port:

# .env
DB_CONNECTION=pg
DB_PORT=5432
DB_DATABASE=gonano

NOTE: Nanobox provides a default database named gonano, but you're welcome to create your own. Also, Nanobox will always use a service's default port when trying to connect. So in this example use 5432, Postgres' default.

Configure Nginx (optional)

It's recommended to use an Nginx reverse proxy to serve static assets. Most Node frameworks are compiled and served static.

Create an etc/nginx.conf in your project with the following contents:

worker_processes 1;
daemon off;

events {
    worker_connections 1024;
}

http {
    include /data/etc/nginx/mime.types;
    sendfile on;

    gzip              on;
    gzip_http_version 1.0;
    gzip_proxied      any;
    gzip_min_length   500;
    gzip_disable      "MSIE [1-6]\.";
    gzip_types        text/plain text/xml text/css
                      text/comma-separated-values
                      text/javascript
                      application/x-javascript
                      application/atom+xml;

    # Proxy upstream to adonis
    upstream adonis {
        server 127.0.0.1:3333;
    }

    # Configuration for Nginx
    server {

        # Listen on port 8080
        listen 8080;

        # Settings to serve static files
        location ^~ /static/  {
            root /app/;
        }

        # Serve a static file (ex. favico)
        # outside /static directory
        location = /favico.ico  {
            root /app/favico.ico;
        }

        # Proxy connections to adonis
        location / {
            proxy_pass         http://adonis;
            proxy_redirect     off;
            proxy_set_header   Host $host;
        }
    }
}

That's it! On to the main event, deploying your application!

Setup Your Azure Account

If you haven't already, create a Microsoft Azure account. In your Azure Portal, click on "More Services" at the bottom of the left nav and filter for "Subscriptions". Click on your Subscription ID.

Azure Subscription ID

Copy and store your Subscription ID. You're going to need it later.

Register Resource Providers

Inside your Subscription ID options, filter for and select "Resource providers". Register "Microsoft.Compute", "Microsoft.Network", and "Microsoft.Storage" by clicking on the "Register" button to the right of each option. These are the resources necessary for Nanobox to build and provision your application on Azure.

Select Azure Resource Providers

Get Your Active Directory ID

In the left nav, select "Azure Active Directory" and go to "Properties". Copy the "Directory ID".

Active Directory ID

Copy and store your Active Directory ID. You're going to need it later.

Create a New Application Registration

Still inside Azure Active Directory, select "App Registrations" and create a new app registration. An "App Registration" is essentially an API integration. You're giving Nanobox access to your Azure resources through a registered "app".

Create New App Registration

Enter the required information:

Name - This can be whatever you'd like.
Application type - Web app / API
Sign-on URL - This isn't used by Nanobox, so put whatever you'd like.

App Registration Credentials

After saving your new app registration, Copy and store your Application ID. You're going to need it later. Click on your new app registration in your list of registered apps, then select "Keys". Provide a key description and expiration, then save.

Key Details

Copy and store the key value. You won't be able to retrieve it after you navigate away from this section and you're going to need it later.

Key Value

Create a New Provider Account

In your Nanobox dashboard, go to the Hosting Accounts section of your account admin and click "Add Account", select Azure, and click "Proceed".

Add a New Azure Provider

Enter the required credentials.

Subscription ID - Azure Subscription ID
Tenant ID - Azure Active Directory ID
Application ID - Azure Application ID
Authentication Key - Azure Application Registration Key Value
Cloud Environment - Should be set to default

Enter Azure Auth Credentials

Click "Verify & Proceed". Name your provider, select your default region, then click "Finalize/Create".

Name Your Provider & Select a Default Region

Launch a New App

Go to the home page of your Nanobox dashboard and click the "Launch New App" button. Select your Azure provider from the dropdown and choose the region in which you'd like to deploy your app.

Select your Azure provider

Confirm and click "Let's Go!" Nanobox will order an server on Azure under your account. When the server is up, Nanobox will provision platform components necessary for your app to run:

  • Load-Balancer: The public endpoint for your application. Routes and load-balances requests to web nodes.
  • Monitor: Monitors the health of your server(s) and application components.
  • Logger: Streams and stores your app's aggregated log stream.
  • Message Bus: Sends app information to the Nanobox dashboard.
  • Warehouse: Storage used for deploy packages, backups, etc.

Once all the platform components are provisioned and running, you're ready to deploy your app.

Stage Your App Locally

Nanobox provides "dry-run" functionality that simulates a full production deploy on your local machine. This step is optional, but recommended. If the app deploys successfully in a dry-run environment, it will work when deployed to your live environment.

nanobox deploy dry-run

More information about dry-run environments is available in the Dry-Run documentation.

Deploy

Add Your New App as a Remote

From the root of your project directory, add your newly created app as a remote.

nanobox remote add app-name

This connects your local codebase to your live app. More information about the remote command is available in the Nanobox Documentation.

Deploy to Your Live App

With your app added as a remote, you're ready to deploy.

nanobox deploy

Nanobox will compile and package your application code, send it up to your live app, provision all your app's components inside your live server, network everything together, and voila! Your app will be live.

Manage & Scale

Once your app is deployed, Nanobox makes it easy to manage and scale your production infrastructure. In your Nanobox dashboard you'll find health metrics for all your app's servers/containers. Your application logs are streamed in your dashboard and can be streamed using the Nanobox CLI.

Although every app starts out on a single server with containerized components, you can break components out into individual servers and/or scalable clusters through the Nanobox dashboard. Nanobox handles the deep DevOps stuff so you don't have to. Enjoy!

Get in Touch


FAQ

Why 0.0.0.0

Nanobox uses Docker to containerize your application within its own private network. Using 127.0.0.1 or localhost (the "loopback" IP) inside of a container will loopback to the container, not the host machine. In order for requests to reach your application, your application needs to listen on all available IP's.

Why Port 8080

Nanobox provides your application with a router that directs traffic through a private network created for your app. The router listens on ports 80 and 443, terminates SSL, and forwards all requests to port 8080.

Note: Your app/framework can listen on a port other than 8080, but you will need to implement a proxy that listens on 8080 and forwards to your custom port.

Why Use Environment Variables

Environment variables serve two purposes:

  • They obscure sensitive information in your codebase. Environment variables referenced in your code are populated at runtime, keeping potentially sensitive values out of your codebase.

  • Due to the dynamic nature of containerized applications, it's hard to predict the host IP of running services. These IP's are subject to change as your infrastructure changes. When creating your infrastructure, Nanobox knows what these values are and creates evars for necessary connection details.

Posted in Adonis, Node.js, Azure, Deployment, Nanobox