How to Deploy AdonisJS Apps to Heroku

Ewomazino ukah
7 min readJul 8, 2018

Adonisjs is a node.js framework built with a similar architecture to laravel. It has the same expressive syntax and uses concepts such as service providers. I recently worked on a project using adonisjs, so today I would be showing you the steps to deploy an adonisjs app on heroku. I would divide the tutorial into two main parts:

  1. Creating a basic api/app
  2. Hosting the app on heroku

Creating the basic Api/App

Follow the instructions here https://adonisjs.com/docs/4.1/installation to setup a new adonisjs project.

Since I want to create just a simple api service, I would run the command

adonis new yardstick --api-only

Open up the project in your favorite IDE/text-editor. I would be using postgres database. Enter your credentials in your .env file, like so:

DB_CONNECTION=pg
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres
DB_DATABASE=yardstick

I set DB_CONNECTION to pg because I would be using the postgres driver. The name of the database here is yardstick, the user and password is postgres. Also if you are using the default settings of postgres, your database port should be 5432

next lets quickly create that database. run these commands in your terminal:

1) psql -U postgres -W
2) create database yardstick;

The first command would prompt you to enter your database password, while the second one creates the database “yardstick”.

Also install the postgres npm package

npm install pg --save

To keep things really simple we are just going to make use of the user migration, that comes with a brand new install of adonisjs and create an endpoint:

GET/users : To lists all users

Lets also define a factory for our user model and create a UserSeeder.js file for seeding our database. Open database/factory.js and enter the following:

const Factory = use('Factory')Factory.blueprint(‘App/Models/User’, (faker) => {
return {
username: faker.username(),
email: faker.email(),
password: faker.string({ length: 8 })
}
}
)

Behind the scenes, adonisjs uses chancejs http://chancejs.com/, and passes an instance of it to our callback, which we have called “faker” here. The lines of code above help us to create a factory defination for our App/Models/User model. To create the UserSeeder.js file we would leverage adonisjs command line utility by running this command:

adonis make:seed UserSeeder

This would create a new UserSeeder.js file in our database/seeds folder. In order to actually seed our database using our user model factory, update your UserSeeder class like so:

const Factory = use('Factory')class UserSeeder {
async run () {
await Factory.model('App/Models/User').createMany(100)
}
}
module.exports = UserSeeder

Now when we run our seed command, this would create 100 dummy users for us. So lets run our migrations and seed our database. (ensure you run all adonis commands from within your project directory)

adonis migration:run
adonis seed

Now lets create the endpoint to list our users, run the adonis command for creating a resourceful Http controller.

adonis make:controller UserController --resource

Next, we would create a route to list all users in our start/routes.js and also edit our UserController.js index method. Open the app/Controllers/UserController.js file and enter the following in the index method.

const User = use('App/Models/User')class UserController {
async index ({request, response}) {
const reqData = request.all()
const limit = reqData.limit || 20
const page = reqData.page || 1

let builder = User.query()
const users = await builder
.orderBy(‘id’, ‘desc’)
.paginate(page, limit)
response.status(200).json({
message: ‘All Users’,
data: users
})
}
...
}

Also, enter the following in the start/routes.js file

Route.get('/', ({request, response}) => {
return response.status(200).json({
message: 'welcome to our api'
})
})
Route.get(‘/users’, ‘UserController.index’)

To view our users, run the adonis serve command

adonis serve

After running the serve command, open the url http://127.0.0.1:9238/users ( i’m using port 9238 because that is the default port on my pc) on postman or browser. You should see a similar result as the one below

http://127.0.0.1:9238/users

Hosting the app on heroku

Now that we have our basic app set up, we can go ahead to initialize git and create our heroku app, if you don’t already have heroku setup on your computer or you are completely new to heroku, follow this article (https://devcenter.heroku.com/articles/heroku-cli) to create an account and setup your computer.

//initialize git
git init
git add .git commit -m "Initialize git repo"
//creates heroku app and adds heroku to git remote
heroku create
Command line output after running “heroku create” command

Now when you login to your heroku dashboard, you should see your newly created app there like mine

Newly created heroku app

lets make a quick list of things we need to do to configure our heroku app to work properly:

  1. Create a Procfile
  2. Setup postgres database
  3. Configure our app to use the postgres database

1. Create a Procfile

All Heroku applications run in a collection of lightweight Linux containers called dynos. Creating a ‘ Procfile’ at the root of our app directory would enable us to specify the commands that are exceuted by the app’s dynos. You can read up on dynos here https://devcenter.heroku.com/articles/dynos. Also for more information on Procfile read this article https://devcenter.heroku.com/articles/procfile.

Next create a procfile at the root of the app’s directory, and enter the following:

release: ENV_SILENT=true node ace migration:run — force
web: ENV_SILENT=true npm start

Here, we are telling heroku to run a command for the ‘release’ process type and the ‘web’ process type.

A Procfile declares its process types on individual lines, each with the following format:

<process type>: <command>
  • <process type> is an alphanumeric name for your command, such as web, worker, urgentworker, clock, and so on.
  • <command> indicates the command that every dyno of the process type should execute on startup, such as rake jobs:work.

The release process type is used to specify the command to run during your app’s release phase, in this case we are telling heroku to run our migrations with the ‘-force’ flag to force it since our app is in a production environment.

The web process type is used to start up our adonis js app. we are using the command npm start since our app is essentially a node js app.

lastly we are setting ENV_SILENT=true in order to suppress any environment errors.

2. Setup postgres database by adding the postgres addon

Navigate to the resources tab in the heroku dashboard, search for “postgres” under addons and select “Heroku postgres”. You should see a screen similar to the one below.

Select the plan you want, we would use the free hobby dev plan here and click provision.

We should now have a new entry in our environment variables. Navigate to the settings tab and click “Reveal config” vars button to display the environment variables.

Environment Variables

3. Configure our app to use the postgres database

open config/database.js and create two variables at the top of the file.

const Url = require('url-parse')const DATABASE_URL = new Url(Env.get('DATABASE_URL'))

Install url-parse, if you don’t already have it installed and make sure you use the — save flag to update our package.json file. The DATABASE_URL constant would store an instance of url-parse with the url set to our DATABASE_URL environment variable. Edit the postgres configuration in the config/database.js file to look like this:

pg: {
client: 'pg',
connection: {
host: Env.get('DB_HOST', DATABASE_URL.hostname),
port: Env.get('DB_PORT', DATABASE_URL.port),
user: Env.get('DB_USER', DATABASE_URL.username),
password: Env.get('DB_PASSWORD', DATABASE_URL.password),
database: Env.get('DB_DATABASE', DATABASE_URL.pathname.substr(1))
}
}

Here we are setting the default values for the connection object to values from our DATABASE_URL constant. They would be used when we push the project to heroku since DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, and DB_DATABASE would not be available.

Next, commit your work and push it to heroku

git add .git commit -m "Modify db config for heroku postgres"git push heroku master

Okay, if you have been following along, you should get the following error

Error output when pushing to heroku

So this error occured because in our config/database.js file we don’t have a value for our DB_CONNECTION in our postgres config and adonis js is falling back to the default of sqlite which we do not have installed. so head over to the settings tab on the heroku dashboard and set DB_CONNECTION to ‘pg’.

Next, commit your work and push to heroku.

git add .git commit -m "set DB_CONNECTION default to pg"git push heroku master

To view the app, run

heroku open

Verify that our app works by checking GET / and GET /users. You should have a similar output.

GET /
GET /users

Notice in our GET /users response that the data is empty. In order to seed our users run the command:

heroku run ENV_SILENT=true node ace seed --force

So now when we visit GET /users, we should see our users:

GET /users

And that´s all, Let me know your thoughts and I hope you like it :). See you in the next post.

--

--