Deploying a Node.js app to Dokku on a Digital Ocean droplet

I thought that I would share my experience in pushing up a Node.js application to a Digital Ocean droplet via the amazing Dokku PaaS. Dokku is like an ideal mashup of the powers of Docker and the ease of use the of Heroku's Git deployment workflow that everyone knows and loves.

Initial setup

First off, you're going to want to sign up to Digital Ocean if you haven't already. Once that's all done and dusted, create a new droplet choosing the Dokku image from their marketplace of prebuilt images:

The dokku droplet

I would choose the lowest specs although this varies dependent on your use case. I went for the $5 a month option.

The Dokku web UI

Dokku has a web setup UI that can be accessed by visiting your Droplet IP address in a web browser (e.g. entering http://0.0.0.0 into the address bar). In the setup process for the droplet you will need to setup these options:

1.) Virtual hosts enabled, meaning that you can push multiple apps to a different subdomain on your dokku droplet. 2.) SSH key configuration, you will need to copy your SSH key from your local dev rig to the clipboard using pbcopy like pbcopy < ~/.ssh/id_rsa.pub

Setting up a Dokku app on the Droplet

Once the droplet has been created and has finished provisioning, you can login to the droplet via SSH (0.0.0.0 is just a placeholder, substitute with the droplet's IP address as it is shown on the Droplet's dashboard page on Digital Ocean):

ssh [email protected]

Once you are in the console, you need to create the Dokku app on your droplet which is going to manage deployments for your local git repo on the server. You can name the app anything you want (I chose myapp below) - just keep a note of it as you will use this in later steps:

Last login: Tue Apr  2 14:48:10 2019 from 1.1.1.1
[email protected]:~# dokku apps:create myapp
-----> Creating myapp... done

Configuring the Dokku git remote locally

Back in your local command line environment, you now need to navigate to the git repository of the app you want to deploy and add the Dokku droplet as a git remote so you can push to it:

git remote add dokku [email protected]:myapp

Be sure to replace 0.0.0.0 with your Droplet's IP address and myapp with the app name you choose when running dokku apps:create myapp above.

Once this is done, you should see the Dokku remote in your list of git remotes:

➜  ajb-next git:(master) git remote -v
dokku    [email protected]:myapp (fetch)
dokku    [email protected]:myapp (push)

Dockerfile or Buildpack?

Once this step has been completed, you need to decide on whether to go down the Dockerfile route or whether to rely on Dokku's Heroku interoperability to make use of standard Heroku buildpacks like Heroku Node and Heroku Rails. If you don't specify a Dockerfile then Dokku will attempt to build your app with a buildpack it judges your application to need. I have chosen the Dockerfile approach. My app is a simple Node.js app so it's not too complex:

FROM node:8

ENV appdir /src

WORKDIR $appdir

COPY package.json yarn.lock ./

RUN yarn --pure-lockfile

COPY . .

EXPOSE 80

CMD ["yarn", "start"]

Pushing to your Dokku git remote

If you haven't yet committed anything, then just run git add . or similar and commit the changes using git commit -m "My message" and then push to the Dokku git remote as below:

➜  ajb-next git:(master) git push dokku master
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
    LANGUAGE = (unset),
    LC_ALL = (unset),
    LC_CTYPE = "en_GB.UTF-8",
    LANG = "C.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("C.UTF-8").
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 342 bytes | 342.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
-----> Cleaning up...
-----> etc

Dokku will attempt to deploy your application either via the Dockerfile you have specified or the automatic buildpack detection process.

Custom domains

I use Cloudflare as a DNS provider, so getting my new Digital Ocean droplet to exist on a subdomain was as easy as adding an A record for the subdomain of my choosing to point to the Droplet IP.

Addendum

You can always check which ports are exposed publicly and which Docker containers they relate to by running:

dokku proxy:ports myapp

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

About

⚑ I like to code, simple as that.
πŸŽ‰ React, Node and Ruby etc.
🧸️ Toying with TypeScript

Elsewhere