Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?

From zero to microservice with 𝚫 now

The following guide will show you how to deploy a simple microservice written in JavaScript using 𝚫 now.

It uses Open Source tools that are widely available, tested and understood:

  • Node.JS
  • NPM
  • Express

Prerequisites

Make sure Node.JS is installed in your machine. If not, head to https://nodejs.org/en/ and download it and install it.

To execute the commands described in this guide, launch your preferred Terminal. On Mac OS X, you can locate "Terminal.app" under "Applications" > "Utilities".

To make sure Node.JS (which comes with npm) is properly installed, try running the command:

npm --version

It should look similar to this:

Installing now

now is a tool that will immediately deploy any Node.JS HTTP service with all its files and dependencies to the cloud.

Install it with NPM as follows:

npm install -g now

To verify it's installed and it works run:

now --version

It should look similar to this:

Creating your service

Create a fresh directory for it and go to it:

mkdir ~/my-service
cd ~/my-service

Every Node.JS project needs a package.json file. Create it with some basic information by copying and pasting this entire command:

cat <<EOF > package.json
{
  "name": "my-service",
  "version": "0.1.0",
  "dependencies": {}
}
EOF

To introduce a dependency, let's install express and save it to package.json:

npm install express@4.13.4 --save
npm install body-parser@1.15.0 --save

If you then look at the contents of package.json, it will look as follows:

Writing your service

We'll first write a basic HTTP endpoint that accepts POST requests.

cat <<EOF > index.js
var app = require('express')();
var srv = require('http').createServer(app);
var bodyParser = require('body-parser');

app.post('/', function (req, res, next) {
  res.send('You POSTed to the micro-service!');
});

srv.listen(3000, function () {
  console.log('Listening on 3000');
});
EOF

If you run

node index

you should see that it's listening on port 3000:

In another instance of the terminal, try POSTing some data with the curl utility (you can also learn more about curl).

This service is ready to be deployed! Let's say that instead of localhost, which only works on your computer, you wanted to share your micro-service with co-workers or the world.

Simply run now! The first time you run it, it'll prompt you to log in or register. Just enter your email and watch your inbox.

After you click the link it emails you, notice that it will try to deploy:

now has only one simple requirement: a start script must be defined in package.json. We can add it as follows:

cat <<EOF > package.json
{
  "name": "my-service",
  "version": "0.1.0",
  "dependencies": {
    "body-parser": "^1.15.0",
    "express": "^4.13.4"
  },
  "scripts": {
    "start": "node index"
  }
}
EOF

In this case, the start script will run the command we manually ran earlier, to make the HTTP service start.

Notice that now doesn't need to know about ports. Any port will work (including ephemeral ones!) as long as your service allows HTTP traffic.

When you enter now, it will give you a unique URL for that deployment. Normally, you get this URL even before the deployment is complete.

If you open it in a browser, you can see the progress of the build: the upload, the installation of dependencies and npm start.

In this case, the deployment happens in under a second!

Making changes

Let's say you want to make some changes to the code you just wrote. In this example, I made it so a name field is expected as JSON input.

To deploy it, I simply type now again and I'll get a new URL.

And voila! I can now send parameters. Both my URLs still work. now never overwrites or throws away your work.

If you have any questions about this tutorial, please comment below!

Is there any way to set up environment variables or other private stuff (api keys)?

3 things:

  • Scoped module names? I'm told it's coming but any timeframe?
  • Environment variables (as above)?
  • How to make the URL "permanent", i.e the same URL for every deploy.

jaydson commented Apr 14, 2016

Is database support planned?

fdaciuk commented Apr 15, 2016

Can I use some module that depends on phantomjs?

Perfect, thanks.

okbel commented Apr 16, 2016

It's amazing. How can I destroy one or deactivate one if i dont want my info to be available anymore?

kehers commented Apr 21, 2016

Yeah, I'd love to be able to destroy my deployment. Or maintain same URL for deployments.

michaelrambeau commented May 10, 2016

As mentioned before, there are still 2 issues that prevent me from building a real service using the free plan (unless I miss something)

  • How can you overwrite a previous URL (when you maintain a given app) ?
  • With the free plan, how do you pass secrets (like db credentials) if anyone can check your .env file just by accessing the .../_src?f=.env URL ? Could be really nice if .env file were excluded, for example. An other way to deal with this point would be to pass environment variables from the command line, when you deploy (as https://webtask.io/ service does)

@michaelrambeau I deployed this:

index.js
require('http').createServer((q, s) => s.end(JSON.stringify(process.env))).listen(3000);

.env
export HELLO=ALOHA

package.json

{
  "name": "env",
  "version": "0.0.1",
  "scripts": {
    "start": "node index"
  },
  "dependencies": {}
}

and _src/?f=.env is valid but HELLO is not found in the response body:

{ 
  SHLVL: '6',
  HOME: '/home/nowuser',
  NOW: '1',
  TEMP: '/tmp',
  PATH: '/home/nowuser/src/node_modules/.bin:/home/nowuser/bin://usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/node_modules/ace/build/node_modules/.bin',
  DEPLOYMENT_ID: 'aaa',
  AUTH_TOKEN: 'aaa',
  PWD: '/home/nowuser/src',
  NOW_URL: 'https://aaa.now.sh' 
}

Hello @jasonmendes

I did the same thing, but if I enter /_src/?f=.env url in the browser, I can see the content of the .env file... that I want to hide from users.

image

So I still don't know how you can prevent the users from browsing your secret files.

onbjerg commented Jun 2, 2016

@michaelrambeau by paying.

millette commented Jun 4, 2016

It's still a development need. I plan to use the paying service eventually, but since I'm using github for logins (as an example), I still need to keep a few things secret. Something like docker's -e to pass environment variables.

UPDATE

Good news

https://twitter.com/rauchg/status/739185836994920449
for now:

  • premium accounts make /_src private
  • now secret coming soon to all accounts!

great tool, used it myself (hook to listen to NPM package updates and push release notes to Slack, described https://glebbahmutov.com/blog/immutable-deploys-with-data-and-testing/) but really really want private scoped package support!
As far as environment variables are concerned I make a separate private repo that just imports the desired module + as-a tool and has single .as-a.ini file with settings. I use paid zeit account so the source file .as-a.ini is not exposed to the public.

Really trying to get the public scoped projects working though, trying to get the limitation by grabbing the source for everything, but this feels very awkward.

September 3rd 2016 update: it's now possible to set environment variables when deploying a micro-microservice.

...without paying!

My problem is solved, thank you guys from the Zeit team!

Read more on their official blog: https://zeit.co/blog/environment-variables-secrets

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment