DEV Community

Murphy Randle for Bloom Built

Posted on • Updated on

Deploying Reason on AWS Elastic Beanstalk with RDS

This isn’t a step-by-step guide. It’s more like a selection of points that the author has just spent too much time getting all flamboozled over, that have been written down now in hopes that some poor kindred spirit (including that same author) won’t have to re-experience the pain necessary just to get a Reason service running on AWS EBS.

The first thing to do is get the eb utility installed (eb standing for “Elastic Beanstalk”, of course). You can get it on either homebrew or pip. The details you can figure out all on your own (good luck!).

Run these commands and follow the prompts. Mostly the default values are okay.

  • eb init
  • eb create

That’s all normal stuff. Buckle up for the juicy details:

Bundling

Compiled reason code depends on javascript that’s included in the bs-platform NPM package. The problem is that said package also will build an entire OCaml compiler, and if you’re trying to deploy code on anything smaller than a not-small server, you’re going to have a prohibitively hard time.

A relatively simple solution is to do a little bit of bundling before shipping your code. You’ll use webpack to bundle up your compiled Reason code into a little neat package before deploying to EBS.

On reading the mention of Webpack, you might be wiping sweat from your brow, anxiously telling yourself that you don’t feel an aching throb at the back of your skull at the thought of having to dig into yet another Webpack config. But don’t worry. It’s a tiny file that’s simple to understand:

webpack.config.js ->

var nodeExternals = require('webpack-node-externals');


module.exports = {
  entry: './src/index.js',
  target: "node",
  output: {
    filename: 'bundle.js',
    libraryTarget: 'commonjs2',
    path: __dirname
  },
  externals: [nodeExternals({
    whitelist: [/^bs-platform/, /\.bs\.js$/]
  })],
  mode: "development",
  devtool: "sourcemap"
};
Enter fullscreen mode Exit fullscreen mode

You’ve included a Webpack plugin that automatically tells Webpack not to bundle anything at all that’s found in the node_modules folder. Which is good! Because most of that stuff will be provided when the deploy process runs npm install, and also good because some of the things in there won’t be happily bundled.

You’ll want to add that plugin to your project with the following command (assuming you’re using Yarn. If you’re using NPM you’re straight outta luck. Just kidding. You know what to do):

yarn add -D webpack-node-externals
Enter fullscreen mode Exit fullscreen mode

but you’ll see that you’ve passed a config object when calling nodeExternals(..) with the key whitelist. This is an array of things that you do want to be bundled.

So, to repeat in simpler words, you set up Webpack, and used a plugin to say “don’t bundle anything in node_modules except this list of things.

That list of things looks like this:

[/^bs-platform/, /\.bs\.js$/]

Those are two regular expressions. The first includes any JS used from the bs-platform module, and the second is any file referenced inside of node_modules that uses the extension .bs.js.

That second entry is important, because when you run the bsb compiler while developing, the compiled JS artifacts get dropped inside of the node_modules folder (like node_modules/bs-foo/lib/js/foo.bs.js for example).

Now just :

yarn add -D webpack-command
#^ this is smaller and faster than webpack-cli AFAIK
Enter fullscreen mode Exit fullscreen mode

Then yarn webpack, and you should get a generated bundle.js in the root of your project.

You can then add node bundle.js to your start command in your package json, and EBS should do what’s expected when you deploy. BTW, you’ll want to have your server code listen on 8081, or whatever the PORT ENV var is set to.

Cleaning up your deps

Now, open up your package.json, and move every package that isn’t a strict runtime dependency from dependencies to devDependencies. Including all the Bucklescript packages you’ve installed (because you bundled them already), and especially including bs-platform.

Deploying

When I first tried a deploy, EBS was trying to zip up my whole code folder, including node modules, and ship it off for deployment. That’s obviously huge and unwieldy and not what we want at all for deployment. So do this instead:

Create a file called .ebignore and put inside:


node_modules/

Make sure the trailing slash is there!

After that, you should be able to eb deploy, and have a relatively quick deployment.

RDS

The author of this post would still be trying to keep himself from bursting small blood vessels in his face if it weren’t for this Front-end Master’s course on Node and AWS EBS: https://frontendmasters.com/courses/production-node-aws. The information following is taken from that course. So if you have money and want to learn, consider giving some to those peeps.

First step, add an RDS database. That should be pretty simple to figure out on your own.

Here’s the more detailed stuff.

  • When you deployed your EB application, a new security group was created for it, and you can find the name of that security group in the config console for your EB application.
  • You need to add your RDS instance to that same security group in its configuration console.

Here’s the part that might seem surprising. It might seem that if the RDS instance and the EB instance are in the same security group, they should be intimate security buddies and open to all kinds of communication. But, nope.

  • You need to edit the incoming permissions for that security group, and open up the port your database is listening on to incoming traffic from the selfsame security group. You need to tell it that it can access itself!

You’ll see in the snap above that security group sg-9... now specifies that it should allow traffic on port 5432 from security group sg-9... (the same group).

After you’ve done this, EB and RDS should be able to talk.

S3

If your application uses S3, you might be worried that you’d have to do silly shenanigans to allow that connection, but it should “just work”(tm).

Little tips for troubleshooting

  • You can SSH into a running EB instance by typing eb ssh
  • The process runs under the user nodejs, but you can’t su to that user. Don’t try. Someone did, and they got rejected. And rejection hurts.
  • The logs for the node process live in /var/logs/nodejs/nodejs.log
  • You can tail those logs with this command tail -f /var/logs/nodejs/nodejs.log
  • Trying to run things like npm start by hand is a pain.
  • You can run npm install by first changing to the root user with sudo su and then running this command: /opt/elasticbeanstalk/containerfiles/ebnode.py --action npm-install
  • While deploying, you can find your application code in /tmp/deploy/...
  • After deploy, you can find your application code in /var/app
  • If you’re having a hard time connecting to some other box and port from your instance, you can run nc -vf <host> <port> from your EB box to see if it can reach that port or not. This helped a lot when figuring out the connection between EB and RDS.

Latest comments (0)