Deploying Ember apps on the cheap with Dokku, Docker and Digital Ocean.
April 18, 2017
The rough idea
With Ember we are spoiled with an excellent `ember-cli-deploy` tool. Need to deploy somewhere, you can go shopping for many of the supported deploy plugins. One company that has made deployment dead simple is Heroku. When I was looking to show off some local Ember apps I wanted something cheap and easy to setup. Heroku would be nice but I think we could go cheaper.
Enter Dokku. It’s project aimed at providing Heroku support by wrapping a docker heroku-friendly project called Herokuish. Dokku gives you a PAAS by wrapping containers with an nginx proxy router. It has
great settings and plugins that help you extend it for a number of use cases. Because Dokku can detect buildpacks and leverage herokuish we can deploy via a git push, using heroku buildpacks, and get a deployed container. With buildpacks you don’t actually need to know Docker or setup the container.
The last piece of the puzzle is Digital Ocean. It provides affordable virtual machine hosting with an easy to understand interface and luckily for us a one-click install of Dokku on a droplet.
With this rough outline let’s get started.
Create your Ember project
Feel free to skip this step if you’ve already got an ember project.
We’ll use a stock ember project.
- Go into a fresh folder, and run ember init
- Let’s make sure we’re tracking this in a git repo, run git init
- Let’s commit the empty ember project:
git add . git commit -m "Init ember project"
Setup your digital ocean droplet
Now let’s get your Dokku digital ocean droplet going.
- Login to Digital Ocean.
- Click ‘create droplet’.
- Click the “One-click apps” tab.
- Choose Dokku 0.8.0 on 16.04
- Choose a size at $5/mo (let’s keep this cheap!)
- Pick your preferred region
- Add your ssh keys if you got them, it’ll make ssh’ing in easier.
- Pick 1 droplet, and pick a hostname if you like.
- That’s it! Click “Create”
Under Droplets, check that your droplet is being created.
You should get an IP address for your droplet, in my case it gave me 220.127.116.11. Go ahead and ssh into your newly created droplet.
Let’s make sure dokku is installed alright by running:
root@dokku-512mb-nyc2-01:~# dokku Usage: dokku [--quiet|--trace|--rm-container|--rm|--force] COMMAND
which should return with how to use dokku and available commands.
In your browser go to http://your.ip.address with “your.ip.address” being the IP address of your digital ocean droplet above.
You should see a screen similar to:
Paste your public key which may be the same public key you use for things like github, unless you’ve generated a different one. It might have already filled it in if you had supplied digital ocean with a public key for the droplet. Make sure you have pasted something into the public key. This page is only available once after clicking “Finish Setup”. If you are trying to keep this cheap and plan on only using an IP address make sure you leave “virtualhost naming” unchecked.
If you ever need to change any of this configuration you can do so while ssh’ed into your droplet from the dokku command and pouring over the decently written dokku documentation. Or ask me on twitter, I might be able to help, too.
Click “Finish Setup” when everything is configured.
Before we continue let’s take care of a few gotchas.
Your security concerns may differ but in order to not worry about the ports picked by dokku for the running applications I’m going to go ahead disable it.
root@dokku-512mb-nyc2-01:~# sudo ufw status Status: active To Action From -- ------ ---- 22 ALLOW Anywhere 80 ALLOW Anywhere 443 ALLOW Anywhere 2375/tcp ALLOW Anywhere 2376/tcp ALLOW Anywhere 22 (v6) ALLOW Anywhere (v6) 80 (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6) 2375/tcp (v6) ALLOW Anywhere (v6) 2376/tcp (v6) ALLOW Anywhere (v6) root@dokku-512mb-nyc2-01:~# sudo ufw disable Firewall stopped and disabled on system startup
It’s not hard to manage the ports on ufw , if you’re interested you can check up on managing Ubuntu’s firewall.
During your build you may run into memory issues which prevent it from finishing. Since we’re going the cheap route I’m going to add some swap, but if you wanted to you could use a droplet with more memory.
root@dokku-512mb-nyc2-01:~# cd /var root@dokku-512mb-nyc2-01:/var# touch swap.img root@dokku-512mb-nyc2-01:/var# chmod 600 swap.img root@dokku-512mb-nyc2-01:/var# dd if=/dev/zero of=/var/swap.img bs=1024k count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB, 1000 MiB) copied, 2.98223 s, 352 MB/s root@dokku-512mb-nyc2-01:/var# mkswap /var/swap.img Setting up swapspace version 1, size = 1000 MiB (1048571904 bytes) no label, UUID=469c4937-54d0-413c-a237-3bd7098c545b root@dokku-512mb-nyc2-01:/var# swapon /var/swap.img root@dokku-512mb-nyc2-01:/var# free total used free shared buff/cache available Mem: 500096 73912 8400 5108 417784 390492 Swap: 1023996 0 1023996 root@dokku-512mb-nyc2-01:/var# root@dokku-512mb-nyc2-01:/var# echo "/var/swap.img none swap sw 0 0" >> /etc/fstab
Creating your app on dokku
While we are still ssh’ed into our digital ocean box let’s go ahead and setup the application on dokku.
root@dokku-512mb-nyc2-01:/var# dokku apps:create ember Creating ember... done
Configure your Ember project for dokku
This is kind of the cool part. Because dokku can be treated like Heroku we can use the wonderful work the people at Heroku have done.
- First, let’s install ember-cli-deploy by running ember install ember-cli-deploy .
- Now install ember-cli-deploy-build by running ember install ember-cli-deploy-build . This is the basic build plugin that takes care of the build process upon deployment.
- package.json will have been modified and config/deploy.js added. Let’s commit these files.
git add . git commit -m “Add ember-cli-deploy and build plugin”
- Dokku tries to do its best to automatically determine the heroku buildpack for a given application but given ours is Ember it needs a bit more setup than a regular node app. There are many different ways to specify the buildpack for an app with Dokku but I prefer setting the .buildpacks file, because then it’s checked into git. In your project root run
echo ”https://codon-buildpacks.s3.amazonaws.com/buildpacks/heroku/emberjs.tgz” >> .buildpacks
which should create a <span class="lang:default decode:true crayon-inline ">.buildpacks</span> file with the buildpack URL inside. If the file already existed the buildpack URL should be added to the bottom.</li> * Commit your <span class="lang:default decode:true crayon-inline ">.buildpacks</span> file <pre class="lang:default decode:true">git add .
git commit -m “Add .buildpacks with ember buildpack”
* The last step is to tell our project where to deploy. Dokku follows the Heroku-easy model of just <span class="lang:default decode:true crayon-inline">git push</span> . So we will add our dokku digital ocean droplet by adding it to our git remotes by running <pre class="lang:default decode:true">git remote add dokku firstname.lastname@example.org:ember</pre> With "your.ip.address" being your digital ocean droplet's IP address. Note: The user for the push is dokku, not root. After the IP address is a ":project-name", in our case it is "ember". So if you're curious the breakdown is: <pre class="lang:default decode:true">git remote add [git-remote-name] dokku@[ip-address]:[dokku-app-name]</pre> * The last step is to deploy, run <pre class="lang:default decode:true">git push dokku master</pre> You should see lots of scrolling text and after a 3-4 minutes you should see one of the last lines say. <pre class="lang:default decode:true">=====> Application deployed: http://your.ip.address:16523</pre> Again, with "your.ip.address" being your droplet's IP address.
dokku config:set ember DOKKU_NGINX_PORT=80 dokku config:set ember DOKKU_PROXY_PORT_MAP=http:80:5000Each command will reconfigure the nginx, and after the second command you should be able to access the application at the given port. ## That's all folks And that's it. Hopefully you were able to get your Ember application deployed. There are probably some easier solutions, like just using Heroku itself, but it's nice to know that there are options if you're on a budget. Also, this can scale with you for other projects across other platforms and help introduce you to the world of Docker. You can access any of the running containers that Dokku sets up for you which is pretty neat and great if you absolutely need to tail some logs or access the environment directly for debugging. ## Thanks Thanks to the developers at dokku, herokuish, heroku, and ember-cli-deploy. This was made pretty easy thanks to the work done by people from these projects. ✌🏽❤️