Deploy - Node/Sequelize
Heroku Deployment with Node + Sequelize
Objectives
Describe what Platform as a Service (PaaS) is
Identify other methods of deployment, and their benefits and drawbacks
Take a working Node/Sequelize app and deploy it to Heroku
Make changes to an existing deployment
Utilize methods for debugging server errors
Introduction
When we have finished developing a version of our app, we likely want to put it on the internet for other people to see.
You can use our Auth Boilerplate app for deployment.
Localhost
Most of what we've developed so far has just run on our own computers. Both our database and our web server have been on our computer. We've done this because it's much easier to develop locally because we don't actually need an internet connection. However, people can't access it easily unless they are also on our local network.
Options?
Buy Another Computer
We could just buy another computer somewhere else and use it to run our applications - or even more than one, if needed, and by the way, a server is a computer. We could connect this other computer to the internet and with a bit of configuration, we could allow people to connect to it using a URL.
However, we'd have to buy and look after this computer, have somewhere to store it and ensure that it was working and always connected to the internet. Also, if someone hit an error when they used our app, we might have to stop and start it? Maybe there is a better way?
Use a Cloud Computing Platform
We could also use Amazon Web Services or similar cloud services, which provide the servers needed to host applications via the cloud. While many companies use AWS for deployment (such as Netflix), we are expected to not only deploy our system, but also set up the system architecture for our application. This includes logging in to the remote server, setting up the web server, and managing configuration and databases. While this provides a lot of flexibility for larger applications, there's a large learning curve that leans towards Linux system administration. Luckily, there is an even better way.
Abstracting Cloud Computing
Heroku is a cloud-based, Platform as a Service (PaaS). Essentially it's a group of virtual machines that run on Amazon Web Services (EC2) and hosts your application code in the cloud. By using git, you can deploy your code directly to Heroku's machines - they call them "dynos" - and seconds later your changes will be live in production.
To deploy an app to Heroku, it's a fairly straightforward step-by-step process.
First you need to link your machine to your Heroku account - a similar process to what we did with Github.
Before Deploying
Check Your Github Repo
Do you notice a folder called "node_modules"? Or your .env file with your environment variables?
Oops! That's not supposed to be there! node_modules and .env should never escape from your local machine. It's going to goof up our stuff and cause errors if we leave it in there when we deploy to Heroku, so let's get rid of them!
If you don't already have a
.gitignore
file, create it now in the top-levelMake sure
node_modules
folder is included in .gitignore. This ensures that once we delete thenode_modules
folder, git won't find it again.Delete the
node_modules
folder in your local repo (don't worry - you can get it back by runningnpm install
)You will need to make sure git knows to remove the
node_modules
folder from the repo. Use the following command:git rm -r node_modules
Ensure that your .env file, (if you have one) is also NOT included in your Github repo.
Repeat steps to remove from git with the git rm command
Add this file to .gitignore so git doesn't find it again.
Commit and push these changes to your Github repo!
Last, let's run npm install to recreate that
node_modules
folder.Try running your app with nodemon.
Does it work? Great, you're all done!
Do you get an error that looks like "xyz module is not found"? This is because originally, we forgot to npm install a module. This might happen for things that you've globally installed when we originally installed it (with the -g flag). Run the following command for each module you're missing:
npm install xyz
TL;DR: Don't have node_modules
in your repo, you'll have a bad time.
Get a Heroku account!
Make sure you have an account with heroku: https://www.heroku.com/
Make sure you have installed the Heroku CLI
Install Heroku CLI
This is a command-line tool that allows us to use commands in the terminal, similar to the way that we use git.
Once it is installed, you need to login with your heroku credentials:
We'll have the ability to create free applications using Heroku, but with limitations. Most of those limitations are related to the size of the databases, as well as uptime for the dynos. For free applications, dynos will "go to sleep" when unused for a period of time. This will lead to slow start times when restarting the dynos.
DEPLOY!
To start:
Create a
Procfile
in the root of your Node applicationIn terminal, run
touch Procfile
. Must be called with a capitol Pmake sure it is named "Procfile" (no extention)
make sure your Procfile is in the same folder as your index.js file
in terminal type
echo "web: node index.js" >> Procfile
In your
index.js
file, where you get your server started, include the port number in your app.listen function. Example:
This ensures that when we set the PORT config variable, Heroku will run on it instead of the 3000 port (Heroku automatically includes a port that's public-facing).
Your package.json file is crucial - when you deploy your application, Heroku will check the package.json file for all dependencies. You can always check your package.json to see if you are missing anything.
To migrate our live database we need a local version of
sequelize-cli
module in our package json. Add it by runningnpm install sequelize-cli
Before you create your app in Heroku, be sure your project is being tracked via a git repository.
Create a Heroku app via the command line (or, if you prefer you can use the GUI to create it and follow its directions to connect it to your git repo)
In this case, sitename
is the name of your app. This will create a url like: http://sitename.herokuapp.com
- you'll find that you have to come up with a completely unique name.
Commit and push all your data at this point (
git push
).To push to Heroku, enter the following command
This should push all your code to Heroku and trigger a build.
Heroku Envionment variables
Next we want to make sure we have config variables. This is Heroku's version of a .env
file or environment variables. Any variable names that are found in your local .env
file should have a corresponding variable on Heroku.
In your javascript code, you might have something like process.env.GOOGLE_KEY
. In order to add environment variables to Heroku. We will run a Heroku command to set it per item in our .env file
Alternatively, you can set these fields in the Heroku GUI under the settings tab and then click "Reveal Config Vars".
Connect a DB with Sequelize
You may notice that while you have a valid URL and the site is deployed, your site likely does not work when you visit it. This is because Heroku is not yet aware of our database and model structure. Let's make it aware.
In terminal, install the add-on for postgres:
heroku addons:create heroku-postgresql:hobby-dev
Make sure your production variables in
config/config.json
are set like this (pay attention to the production setting).
config/config.json
Add and commit your changes to git, then push your changes to heroku using
git push heroku master
Now run your migrations by typing in terminal
heroku run sequelize db:migrate
and you should have all your tables set up in a heroku hosted databaseNOTE: If you have any seeder files to run, do that here as well! Simply type
heroku run
followed by the command you want to run on the production server.Try opening your app now, with the command
heroku open
or, simply visit the website in your browser.
NOTE: You may notice that the data on your local machine does not travel up to Heroku. This is by design! Generally you're not going to want your development data to affect your production data! That said, there may be times when you want to seed data. Investigate the db:seed command of the Sequelize CLI.
You can view your brand new database by executing the psql
command you know and love on Heroku. Do this by typing heroku pg:psql
DEBUGGING HELP
Something is broken?!?!?!?!
Don't panic! Type heroku logs
to see the error and info messages from the Heroku server! Find the error and Google it if the meaning isn't readily apparent! Some fixes to common errors are found below!
Migrate from Sequelize 3 to 4
If you used to use Sequelize 3, keep in mind that Sequelize 4 has breaking changes! If you need to upgrade your app, refer to these docs, which guide you in the update process.
Version Conflicts
WARNING (2017) Edited (2018, 2019): At one point, sequelize-cli, sequelize, and pg modules were not playing nicely with each other. It continues to be an intermittent issue that crops up every time one of these modules makes a new version with a breaking change. Be mindful that many modules you use are maintained by individual third parties and issues like this may come up!
This problem is unfortunately difficult to recognize since the error message is pretty much random each time. This time around it was:
Last time it was something along the lines of rows is undefined
. Regardless, after some Googling of the error it seems to be related to Sequelize or Postgres, this is probably the underlying issue.
So How to fix it?
The fix to this problem is a bit of an inconvenience. The gist is that we will ensure we have versions of those 3 modules we are sure will work together properly. Then we need to delete the Heroku app and recreate it from scratch (repeating the steps above regarding creating and migrating the database and setting all the config variables).
As of January 2019, here is a dependencies list (for a package.json) that worked together. This will need to be updated for every one or two new classes.
BCrypt Something Something...
Bcrypt is finicky. Try using bcryptjs
if you haven't switched already. Older computers sometimes also have issues with the BCrypt module, which may mean you will need to look up a work-around.
Can't Find Module XYZ
Look in your local package.json
and see if the module it says is missing is in the dependencies section. If not, run npm install XYZ
(replace XYZ with whatever your actual error message says). Git add, commit, and push to Heroku to see if the error is resolved.
Alternatively, another cause of this error is when you are trying to require a local file or folder (e.g., like your models
folder), and you have forgotten to put ./
in front of it. If you forget the ./
it thinks you mean a module rather than a local path, and it will go looking for a module called that and probably not find one (hence the error).
Overview
App deployment
Login to Heroku using the Heroku CLI (only do once)
Create a Procfile and fetch your port in your app
Create a Heroku app
Push application to Heroku
Sequelize setup
Install Heroku's postgres addon
Set all config variables on Heroku
Set the production database variable in
config/config.json
Install a local version of
sequelize-cli
to thepackage.json
filePush application to Heroku
Run migrations on Heroku
Resources
For all resources Heroku-related, check out the documentation on Heroku's website.
https://devcenter.heroku.com/articles/getting-started-with-nodejs
Some interesting (and free) addons you can add to your app:
Application monitoring
Logging management
Load testing for web applications
Send messages to Slack, Email, or an HTTP endpoint on deployment
Schedule tasks, similar to
cron
API for sending emails
API for image uploads and delivery
Last updated