TL;DR: In this article, we're going to be creating a couple of very simple Node applications and hosting them on a DigitalOcean droplet using Dokku, an open-source PaaS. We'll also be looking at how to optimize the deployment using Docker.

Prerequisites

You do not strictly need any software other than Git and a text editor to follow along with this article, as most of the work is done on the Dokku server. As long as you have cloned the sample application, you can perform most of the steps in this tutorial.

However, installing Node and Docker is highly recommended as we're going to be doing some local testing before deployment to make sure that everything is working as it should.

If you would like to follow along, you should have the latest version of Node installed.

You should also install Docker for Developers for your operating system. Docker is a container platform that allows us to package up applications and services, distribute them and run them in a consistent environment. We're going to be using it in conjunction with Dokku to package up a Vue.js application and run it on a remote server.

As the process of deploying applications to a Dokku server revolves around Git, make sure you have Git installed on your system before you start.

"Learn how to easily set up a Dokku server and deploy applications to it using Git"

Introduction to Dokku

DokkuThe smallest PaaS implementation you've ever seen — is a piece of open-source software that "helps you build and manage the lifecycle of applications". It uses Docker under the hood to create and run applications inside containers. Dokku supports Ubuntu 14.04/16.04, Debian 8.2 and CentOS 7 platforms, and has a very small team of core maintainers. They have a variety of ways you can get in touch if you need help, including IRC and Slack.

They also have complete documentation available online.

How it works

In essence, it allows you as a developer to push applications to it using Git where it will build those applications for you, package them into a Docker container, and then manage the lifetime of that container on your behalf. It will also automatically configure Nginx so that your application can be reached, with its virtual hostname support.

When you push an application, it builds the app using the official Heroku Buildpacks, and so if your app already works on Heroku, it's probably going to work here.

If the buildpacks don't cater to your needs, you can customize the build process by providing your own Dockerfile, and Dokku will use that instead.

We're going to see both of these approaches to working with Dokku in this article.

Why use Dokku

Dokku provides a nice balance between cost (Dokku itself is open-source and free), features and control. With Dokku, you get a generously-featured platform on which to install your apps that supports Git deployment and lifetime management out-of-the-box. All of the configuration that enables those two things to work is taken care of for you. Dokku can be hosted on a $5 DigitalOcean droplet, and so the more apps you can host on this box, the more cost-effective it will be when compared to hosting them on other big-brand platforms.

To highlight some of the core features:

  • Git deployment
  • Customize the deployment with Dockerfiles
  • Tarball deployment support
  • Custom domain name support
  • Configurable zero-downtime checks
  • Rich command-line interface
  • Customizable proxy management and Nginx config
  • Nice abstraction over the Docker CLI
  • Rich set of plugins that add much more capability to the platform, including Let's Encrypt, Slack, and for various database platforms such as MongoDB and PostgreSQL

Bear in mind that you do not have to use DigitalOcean to host your Dokku server — if you have an existing compatible Linux server that's not doing much, you could put it to good use by installing Dokku on it!

Gotchas

For Dokku, there is no official web interface for managing through a browser - it's command-line only. For some people, that may be a turn-off. Community attempts have been made to establish a web front-end for Dokku but none have really broken through as being the application to use. That being said, the Dokku CLI is very simple to learn.

Also, the plugin system heavily uses Bash which may or may not be your cup of tea. For authoring plugins, it would be much nicer if they could be written in a more friendly scripting language.

But don't let those things put you off — let's get started!

Setting Up a DigitalOcean Droplet

Now that we have our app, let's create our platform. If you already have a DigitalOcean account, log in now. Otherwise, register for a free DigitalOcean account now. By registering using this link, you automatically get $10 worth of credit added to your account, meaning that you won't have to pay to complete this tutorial.

Once you are into your control panel, click the 'Create' button at the top of the screen and choose 'Droplets'.

On this screen, we need to select "One-click apps" and choose "Dokku 0.12.13 on 18.04" (the actual version numbers may vary).

DigitalOcean One-click Apps

Next, scroll down a bit to the next section which asks for the size. A small, $5 per month instance is fine for this example. Later, if you decide to host more apps, you may need to increase the size of a droplet to accommodate them

Note: You may need to scroll to the left to see the $5 option. With this option, we get a machine that has a 1GB of memory and a 25GB SSD hard-drive, which is enough to host a few small apps. To put that into context, after deploying the basic Express application below, I still had 621MB of RAM and 21GB of disk space available. After deploying the Vue.js application, the available RAM reduced to 586MB, while the available disk space only reduced by a small amount. The amount of applications you can fit on a $5 DigitalOcean droplet will vary depending on the size and complexity of the applications you want to host. Fortunatly, in most cases you can upgrade a Droplet at any time should you need more resources!

DigitalOcean droplet size

The next thing you'll be asked when you scroll down is what region you want your droplet to be in. Select any region that makes sense for you.

Finally, we need to add an SSH key so that we can log in to the server. Scroll to "Add your SSH keys" and click the "New SSH key" button. Copy and paste your machine's public key into this box, give it a name and press "Add SSH key" to finish.

Note: Your public SSH key is usually available in the .ssh folder inside your home directory. On Linux and MacOS, this is usually ~/.ssh/id_rsa.pub. On Windows, try C:\Users\<username>\.ssh\id_rsa.pub. If you have not previously generated an SSH key pair, follow the instructions on GitHub.com to generate a new SSH key and add it to the ssh-agent. Once the public key has been created, try the previous step again.

Adding your public key to DigitalOcean

Finally, press the "Create" button at the bottom to create the droplet. It will take a few minutes for it to be available.

Logging in and setting up

Once the Droplet has been created, it will have an IP address. Copy the IP address into your clipboard, and open a terminal. We're going to use SSH to connect to our Droplet.

DigitalOcean Droplets panel

Inside the terminal:

ssh root@46.101.88.57

Note: Your IP address will be different to mine, so make sure you use the one that you copied from the DigitalOcean Droplets panel.

If the login is successful, you should see some output similar to this as part of Ubuntu's Message of the Day:

Welcome to DigitalOcean's One-Click Dokku Droplet.
To keep this Droplet secure, the UFW firewall is enabled.
All ports are BLOCKED except 22 (SSH), 80 (HTTP), 443 (HTTPS),
2375 (Docker) and 2376 (Docker).

In a web browser, you can view:
 * The Dokku One-Click Quickstart guide: http://do.co/dokku1804#start
 * Your Dokku setup page: http://46.101.88.57

For help and more information, visit http://do.co/dokku1804

Note: You may find that your SSH connection will drop with the message "Please wait while we get your droplet ready...". If that's the case, your Droplet may still be performing some initialization steps, even though the Droplets panel said it was ready. Just try again in a few minutes.

As instructed in the terminal, in order to complete the setup we need to access the Dokku setup page. Open a web browser and access your server using the http://<ip address>:

Dokku setup page

Here you are asked to provide your SSH key. Since we have already provided it in a previous step when we initially set up the droplet, this should be pre-filled.

The next thing you need to do is decide whether or not to use virtualhost naming for your apps.

  • If you have a domain that you want to use with this box (e.g. example.com), then you can turn on virtualhost naming so that your apps are accessed as subdomains. For example, creating an app called "Demo" will mean that you will be to access your application at http://demo.example.com
  • If you do not have a domain that you wish to use for your Dokku server, then you should leave this box unticked. This will mean that your apps would become available on a specific port number, e.g. http://46.101.88.57:3000. You will need to configure the firewall to open specific application ports

I have a domain I'm going to use for this example, so I will tick the box.

Note: For this to work, you must configure your domain's DNS with an A record that points to your Dokku server. In my example, I'm using a domain simplicode.co.uk with an A record of * that points to my server at 46.101.88.57. This means that any traffic that goes to a subdomain e.g. http://my-app.simplicode.co.uk will be routed to my Dokku server and Nginx will route it to the correct place. Also, note that changing your DNS settings may require a bit of time for the changes to fully take effect.

With that done, click "Finish Setup" to proceed. Your Dokku server is now ready to go!

Deploying an Application

Let's try deploying a simple Express application and see if we can reach it on the internet.

To create this application, you can follow the steps below, or you can clone the demo repository to get a head start.

Creating a simple Express app

Using the terminal, find a location on your hard-drive to place a new project, and create a new folder. Then cd into it:

# Create a new folder for our app
mkdir express-dokku

# Move into it
cd express-dokku

Next, initialize the Node project using npm and initialize git:

# Initialize as a new Git repository
git init

# Initialize the npm project
npm init -y

Then, we want to exclude the node_modules folder so that we don't commit it along with the rest of our files. We can do this by creating a .gitignore file in the root of the project:

echo node_modules/ > .gitignore

Now install express as a dependency:

npm install express

Create a new file called server.js and populate it with the following content:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello, Dokku!');
});

// Port 5000 is the default Dokku application port
app.listen(5000, () => console.log('Listening on port 5000'));

Finally, modify package.json so that it includes a start script that runs our server:

{
  "name": "express-dokku-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node server.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/auth0-blog/express-dokku-sample.git"
  },
  "dependencies": {
    "express": "^4.16.4"
  }
}

To test it, run npm start from the terminal. Then, browse to http://localhost:3000 in the browser, and you should see the words "Hello, Dokku!" on the screen.

Using Git deployment

Now that we have our simple application, we'll create a new Git commit so that it can be pushed up to the Dokku server. Since Dokku uses Git to deploy applications, every change you make that you want to deploy to the server must exist in Git at some stage. Otherwise, the changes won't be pushed.

git add . && git commit -am "Initial commit"

The last thing we need to do is add a Git remote that points to our Dokku instance. You can do this with the following command in the terminal:

# With a domain name (replace example.com with your domain)
git remote add dokku dokku@example.com:express-demo

# Without a domain name (replace the IP address with that of your server)
git remote add dokku dokku@123.456.789.012:express-demo

The remote URL dokku@example.com:express-demo contains the application name we want to use (the express-demo) part. If you are using virtualhost naming, this name will form the subdomain part of the URL that you use to access the application. i.e. http://express-demo.example.com.

Finally, use git push to push your application to the server. This will kick off the build process using the Node buildpack and — if all goes well — deploy it!

git push dokku master

You will start to see a lot of logging information spill out into the terminal, telling you how the build process is going. After a couple of minutes, the build should finish and your site should be available. To test this, try to access the application in your browser. If you are using virtualhost naming and a domain, you should be able to reach it at http://express-demo.<your domain name>, or http://<your IP address> if not using a domain.

There are some useful Dokku commands we can use now that we have an application up and running. Log into your server using ssh:

ssh root@<your domain or IP address>

Once you're logged in, use the dokku command to show the available commands that Dokku has to offer.

For example, use the following to get a report of the application we've just deployed:

dokku apps:report express-demo

# Output
=====> demo app information
       App dir:                       /home/dokku/express-demo
       Git sha:                       205bd10
       Deploy source:                 git
       Locked:                        false

Or to see the port mapping for the Docker container:

dokku proxy:ports express-demo

# Output
-----> Port mappings for express-demo
-----> scheme             host port                 container port
http                      80                        5000

Or even run commands against the running container:

dokku run express-demo ls

# Output
Procfile  node_modules  package-lock.json  package.json  server.js

Using dokku enter express-demo, you can step into the running container and run commands that way too — give it a try!

Using Dockerfile deployment

What we did in the previous step was to deploy an application to the server using Git, which uses the Heroku Node buildpack to build our application using established Node conventions. This works great for a simple Node app like the one we created in the previous section, but what about a more complex application?

Vue.js applications created using Vue CLI 3 pose a couple of special problems:

  • There is no npm start script available out-of-the-box, so the buildpack doesn't know how to run it
  • Most of the dependencies live in the devDependencies node inside package.json. This means that when the buildpack tries to install the dependencies using npm install --production, it misses out on the important ones we need to run the application
  • We would have to have some configuration to disable Webpack Dev Server's host check once the application has been deployed. This is a good measure to help prevent DNS rebinding attacks but doesn't work for us if we want to deploy the application
  • Last but not least, if we just deployed the Vue.js app as-is, we'd be packaging up all the source files and node modules that we don't really need to, which will bloat the size of the Docker image with unnecessary files

To get around these issues, let's use a Dockerfile to customize our own build steps and cast aside the Heroku buildpack entirely!

Again, you can either follow the following steps to create the Vue.js application and add the Dockerfile, or you can clone the example repository with all of this stuff in it.

Creating the Vue.js application

First of all, find a new place on your hard-drive to create a new project. Next, run the following command to create a new boilerplate Vue.js project. When it asks you questions about how the project is to be created, just accept all the defaults:

# Create the project
npx @vue/cli create vue-demo

# Move into the project folder
cd vue-demo

Adding the Dockerfile script

Then, add a new file in the root of the project called Dockerfile and populate it with the following content:

# Use Node 10
FROM node:10-slim AS build

# Create a folder for our app
RUN mkdir /app

# Set up the working directory
WORKDIR /app

# Copy our package.json file first, then run `npm install`.
# This is an optimization we can make, as this layer will be
# cached, meaning that if we don't change the package.json file,
# this step doesn't need to be performed again
COPY package.json .

# Note that we're installing all dependencies, unlike the buildpack
RUN npm install

# Copy the rest of the application
COPY . .

# Build the Vue.js application. It will output static files
# Into the /dist folder
RUN npm run build

# ---------------

# Create a second-stage which copies the /dist folder
# and uses http-server to host the application
FROM node:10-slim

# Create an app folder
RUN mkdir /app

# Set /app as the working directory
WORKDIR /app

# Initialize a new node app and
# install http-server
RUN npm init -y && \
  npm install http-server

# Copy the built artifacts from the build stage
COPY --from=build /app/dist /app

# Expose port
EXPOSE 8080

# Set the startup command
CMD ["./node_modules/.bin/http-server"]

This is basically the "script" that Docker will use in order to build our application image. This particular Dockerfile is based on the Node 10 (Slim) image and already contains the tools we need to build Node apps. It first builds the Node application using npm run build, which creates the HTML, JavaScript and CSS files, and puts them into the /dist folder.

The Dockerfile contains a second stage which takes these static assets and copied them into a new container. The app is then served using http-server, which is a Node application that can serve static assets from a folder using sensible defaults. The reason we use these two stages is so that the resulting Docker image is much smaller and efficient. There's no point in including all of the source files and Node packages in the image when they're not going to be used!

We should also add a .dockerignore file so that it doesn't try to copy in the node_modules folder when the whole application is copied. For this simple example, it probably won't matter too much, but it's a good habit to get into:

echo node_modules/ > .dockerignore

Note: .dockerignore files work in a very similar fashion to .gitignore files. Docker ignores files that match items in this file when performing COPY operations.

Finally — as long as you have Docker installed — you can test the build locally using the following terminal command:

docker build -t vue-demo .

This will create a new Docker image from the Dockerfile in the current directory. Docker will execute all the steps inside the Dockerfile, including downloading the Node 10 image, copying the files and running npm install. Do not forget the period on the end, as that is a pointer to the current directory.

Once the image has been built, we can ask Docker to create a new container from this image and run your application, using the following command. Note that this can be done from any directory where the docker command is available:

docker run -p 8080:8080 vue-demo

Note: The -p switch specifies the port mapping. Even though the application starts up on port 8080, it can be mapped to another port when the container is started. Without this though, the application won't be visible in the browser, as Docker will not forward the port.

The application will spin up in the same way as if it had been started using npm run serve. Test this in the browser by browsing to http://localhost:8080 — you should see your application running!

Vue.js boilerplate app

Deploying the application

If all is well, we can now deploy this to our Dokku server. First, create a new commit with the Docker file in it, then push it to the server:

# Commit the change
git add . && git commit -m "Added a Dockerfile"

# Add in our remote Dokku repository
git remote add dokku@<domain or IP address>:vue-demo

# Push the changes
git push dokku master

This time, Dokku will detect that a Dockerfile is present and use that to build the image containing your application.

Note that when using Dockerfile deployment, Dokku will try and set up the proxy with the same port that has been exposed in the Dockerfile (port 8080 in our case). Unfortunately, this means that by default, the application will only be available on port 8080 when it is deployed. We may find that when we try to access the application now, that we won't be able to see it. Or, we will see "Hello, Dokku!" being displayed from the Express application we created earlier.

To change the port mapping so that it maps to port 80, ssh into the Dokku server once again and run the following commands:

dokku proxy:ports-add vue-demo http:80:8080

This will add a mapping on the http scheme from host port 80 to container port 8080.

Now we should be able to see the application when we browse to http://vue-demo.<your domain>, or http://<your IP address> if not using virtualhost names.

Adding SSL Support with Let's Encrypt

To demonstrate how easy it is to get up an running with SSL and make your Dokku apps more secure (free of charge!), let's add the Let's Encrypt plugin and set our application up with an SSL certificate.

Note: If you are not using virtualhost naming with your Dokku server, you will not be able to complete this step, as Let's Encrypt do not offer SSL certificates for IP addresses.

Log into your Dokku server using ssh, and install the plugin using the following command:

sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

Next, we need to add in an email address to the application's configuration so that the Let's Encrypt plugin can use it to request a certificate from the Let's Encrypt server. This can be done with the following command:

dokku config:set --no-restart DOKKU_LETSENCRYPT_EMAIL=<your email address>

Here you should swap <your email address> for your own email address. This is used by Let's Encrypt to notify you when the certificate is about to expire.

Note: Normally when you add in configuration, Dokku will automatically restart the application for you. We don't need that in this case, so the no-restart flag prevents that from happening.

Finally, to install an SSL certificate into our application, we can run this command:

dokku letsencrypt vue-demo

The plugin will request and retrieve the SSL certificate from Let's Encrypt, store it on the server and then configure the SSL port for your application. It will then reconfigure Nginx to automatically use SSL when accessing your app.

As a result, you should now have an SSL-enabled app!

Vue app with SSL

"Add Let's Encrypt support to your Dokku applications using the official plugin"

Aside: Authenticate a Vue App and Node API with Auth0

We can protect our applications and APIs so that only authenticated users can access them. Let's explore how to do this with a Vue application and a Node API using Auth0. You can clone this sample app and API from the vue-auth0-aside repo on GitHub.

Auth0 login screen

Features

The sample Vue application and API has the following features:

  • Vue application generated with Vue CLI and served at http://localhost:4200
  • Authentication with auth0.js using the Auth0 login page
  • Node server protected API route http://localhost:3001/api/meetups/private returns JSON data for authenticated GET requests
  • Vue app fetches data from API once user is authenticated with Auth0
  • Authentication service uses a subject to propagate authentication status events to the entire app.
  • Access token and token expiration are stored in local storage and removed upon logout.

Sign Up for Auth0

You'll need an Auth0 account to manage authentication. You can sign up for a free account here. Next, set up an Auth0 application and API so Auth0 can interface with a Vue.js app and Node API.

Set Up an Auth0 Application

  1. Go to your Auth0 Dashboard and click the "create a new application" button.
  2. Name your new app and select "Single Page Web Applications".
  3. In the Settings for your new Auth0 application, add http://localhost:8080/callback to the Allowed Callback URLs.
  4. Scroll down to the bottom of the Settings section and click "Show Advanced Settings". Choose the OAuth tab and verify that the JsonWebToken Signature Algorithm is set to RS256.
  5. If you'd like, you can set up some social connections. You can then enable them for your app in the Application options under the Connections tab. The example shown in the screenshot above utilizes username/password database, Facebook, Google, and Twitter. For production, make sure you set up your own social keys and do not leave social connections set to use Auth0 dev keys.

Set Up an API

  1. Go to APIs in your Auth0 dashboard and click on the "Create API" button. Enter a name for the API. Set the Identifier to a URL. In this example, this is http://meetupapi.com/. The Signing Algorithm should be RS256.
  2. You can consult the Node.js example under the Quick Start tab in your new API's settings. We'll implement our Node API in this fashion, using Express, express-jwt, and jwks-rsa.

We're now ready to implement Auth0 authentication on both our Vue client and Node backend API.

Dependencies and Setup

The Vue app utilizes the Vue.js CLI. Make sure you have the CLI installed globally:

$ npm install -g vue-cli

Once you've cloned the project, install the Node dependencies for both the Vue app and the Node server by running the following commands in the root of your project folder:

$ npm install
$ cd server
$ npm install

The Node API is located in the /server folder at the root of our sample application.

Find the config.js.example file and remove the .example extension from the filename. Then open the file:

// server/config.js
// (formerly config.js.example)
module.exports = {
  CLIENT_DOMAIN: '[CLIENT_DOMAIN]', // e.g. 'you.auth0.com'
  AUTH0_AUDIENCE: 'http://meetupapi.com'
};

Change the CLIENT_DOMAIN variable to your Auth0 application domain and set the AUTH0_AUDIENCE to your audience (in this example, this is http://meetupapi.com). The /api/examples/private route will be protected with express-jwt and jwks-rsa.

Note: To learn more about RS256 and JSON Web Key Set, read Navigating RS256 and JWKS.

Our app and API are now set up. They can be served by running npm run dev from the root folder and node server.js from the /server folder.

With the Node API and the Vue.js app running, let's take a look at how authentication is implemented.

Authentication Service

Authentication logic on the front end is handled with an Auth authentication service: src/auth/Auth.js file.

// src/auth/Auth.js
/* eslint-disable */
import auth0 from 'auth0-js';
import router from '../router';

export default class Auth {

  auth0 = new auth0.WebAuth({
    domain: AUTH0_DOMAIN, // e.g., you.auth0.com
    clientID: AUTH0_CLIENT_ID, // e.g., i473732832832cfgajHYEUqiqwq
    redirectUri: CALLBACK_URL, // e.g., http://localhost:8080/callback
    audience: AUTH0_API_AUDIENCE, // e.g., https://meetupapi.com
    responseType: 'token',
    scope: 'openid'
  });

  constructor() {
    this.login = this.login.bind(this);
    this.handleAuthentication = this.handleAuthentication.bind(this);
    this.logout = this.logout.bind(this);
  }

  handleAuthentication() {
    this.auth0.parseHash((err, authResult) => {
      if (authResult && authResult.accessToken) {
        this.setSession(authResult);
        router.replace('/');
      } else if (err) {
        router.replace('/');
      }
    })
  }

  setSession(authResult) {
    // Set the time that the access token will expire at
    const expiresAt = JSON.stringify(authResult.expiresIn * 1000 + new Date().getTime());
    localStorage.setItem('access_token', authResult.accessToken);
    localStorage.setItem('expires_at', expiresAt);
  }

  requireAuth(to, from, next) {
    if (! (new Auth).isAuthenticated()) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      });
    } else {
      next();
    }
  } 


  login() {
    this.auth0.authorize();
  }

  logout() {
    // Clear access token and expiration from local storage
    localStorage.removeItem('access_token');
    localStorage.removeItem('expires_at');
    // navigate to the landing page route
    router.go('/');
  }

  isAuthenticated() {
    // Check whether the current time is past the
    // access token's expiry time
    const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
    return new Date().getTime() < expiresAt;
  }
}

Replace the constants, AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_API_AUDIENCE with values from your Auth0 dashboard. Replace CALLBACK_URL with http://localhost:8080/callback.

The login() method authorizes the authentication request with Auth0. An Auth0 login page will be shown to the user and they can then log in.

Note: If it's the user's first visit to our app and our callback is on localhost, they'll also be presented with a consent screen where they can grant access to our API. A first party application on a non-localhost domain would be highly trusted, so the consent dialog would not be presented in this case. You can modify this by editing your Auth0 Dashboard API Settings. Look for the "Allow Skipping User Consent" toggle.

We'll receive accessToken and expiresIn in the hash from Auth0 when returning to our app. The handleAuthentication() method uses Auth0's parseHash() method callback to set the session (setSession()) by saving the tokens, and token expiration to local storage. The isAuthenticated method informs the components in the app about the user's authentication status via checking the access token's expiry time.

Finally, we have a logout() method that clears data from local storage.

Callback Component

The callback component is where the app is redirected after authentication. This component simply shows a loading message until the login process is completed. It executes the handleAuthentication() method to parse the hash and extract authentication information.

// src/components/Callback.vue
<template>
  <div>
      <h3>Loading....</h3>
  </div>
</template>
<script>

import Auth from '../auth/Auth.js';

const auth = new Auth();

export default {
  name: '',
  mounted() {
    this.$nextTick(() => {
      auth.handleAuthentication();
    });
  },
};
</script>

Making Authenticated API Requests

In order to make authenticated HTTP requests, we need to add an Authorization header with the access token in our meetup-api.js file.

// utils/meetup-api.js
/* eslint-disable */
import axios from 'axios';
import Auth from '../src/auth/Auth.js';

const auth = new Auth();
const BASE_URL = 'http://localhost:3333';

export function getPublicMeetups() {
  const url = `${BASE_URL}/api/meetups/public`;
  return axios.get(url).then(response => response.data).catch(err =>  err || 'Unable to retrieve data');
}

export function getPrivateMeetups() {
  const url = `${BASE_URL}/api/meetups/private`;
  return axios.get(url, { headers: { Authorization: `Bearer ${localStorage.getItem('access_token')}` }}).then(response => response.data).catch(err => err || 'Unable to retrieve data');
}

Final Touches: Route Guard and Private Meetups Page

A Private meetup page component can show information about private meetups. However, we only want this component to be accessible if the user is logged in.

The route guard is implemented on specific routes of our choosing in the router/index.js file like so:

// src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import PublicMeetups from '@/components/PublicMeetups';
import PrivateMeetups from '@/components/PrivateMeetups';
import Callback from '@/components/Callback';
import Auth from '../auth/Auth';

const auth = new Auth();

Vue.use(Router);

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'PublicMeetups',
      component: PublicMeetups,
    },
    {
      path: '/private-meetups',
      name: 'PrivateMeetups',
      beforeEnter: auth.requireAuth,
      component: PrivateMeetups,
    },
    {
      path: '/callback',
      component: Callback,
    },
  ],
});

More Resources

That's it! We have an authenticated Node API and Vue.js application with login, logout, and protected routes. To learn more, check out the following resources:

Summary

In this article, we saw how to set up a new Dokku server using a DigitalOcean Droplet, and then deploy a simple Express application to it using Git Deployment. We then added a Dockerfile to customize the build process for a Vue.js application, creating a multi-stage build that used Vue's built static assets to create a small, optimized Docker image.

We also learned some of the basic Dokku commands, such as dokku apps, dokku proxy and ran the ls command from inside the app container.

Finally, we used the Let's Encrypt dokku plugin to SSL-enable our Vue app.


Comments / Discussion

Powered by the Auth0 Community. Sign up now to join the discussion. Community links will open in a new window.