Continuous Deployment with AWS, Dokku & CircleCI
Dokku is awesome for hosting a bunch of small web apps on a single server. A simple git push dokku
will deploy your app and you also get LetsEncrypt SSL for all your domains for free. Nice! Dokku uses Docker under the hood so all your apps run in their own container which is pretty sweet.
But best of all, it’s really simple to get setup!
This is how I setup Continuous Deployment with AWS EC2, Dokku and CircleCI:
Get your Dokku server up and running in AWS
1. Create a new EC2 instance and attach an elastic IP.
I like to use Ubuntu. Make sure you open port 80 and you can ssh
to your new instance.
2. Add your new EC2 instance to your ~/.ssh/config
Host dokku
User ubuntu
HostName <the elastic ip>
port 22
IdentityFile ~/.ssh/example.pem
3. Create a CNAME that points to your server
For example, dokku.example.com
is easier to remember than the server’s IP.
4. Install Dokku on the server
Check the Dokku README for the latest version and installation instructions. But this worked for me:
ssh dokku
wget https://raw.githubusercontent.com/dokku/dokku/v0.7.2/bootstrap.sh;
sudo DOKKU_TAG=v0.7.2 bash bootstrap.sh
Then complete the web-based installation by visiting your server’s IP address in your browser (or the CNAME you setup in the previous step, i.e. http://dokku.example.com).
5. Add your ssh key to Dokku so you can deploy via git push
Run these commands on your local machine:
# If you don't already have a ssh keypair, you'll need to run this:
# ssh-keygen -t rsa -b 4096 -C "your_email@example.com"cat ~/.ssh/id_rsa.pub | ssh dokku sudo dokku ssh-keys:add ubuntu
6. Configure the default web app (optional)
When visiting a domain pointing to the server but not yet configured on the server, the first app in lexical order will be served. So it’s nice to have a default “Coming soon” app at the top of the list named 00-default
.
ssh dokku
dokku apps:create 00-default
7. Install the LetsEncrypt plugin
sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
dokku letsencrypt:cron-job --add
Your Dokku server is now up and running. That was easy!
Deploy a new app
These instructions should work for pretty much any kind of app but I can only attest to the simplicity of deploying Node.js apps. Dokku should detect the type of app and it should just work™.
- Register the app on the server
ssh dokku
dokku apps:create my-app
2. Ensure your app always restarts
By default, the app is stopped if it crashes more than 10 times. I prefer to disable this and always keep it running.
dokku ps:set-restart-policy my-app always
3. Make sure your app is Dokku-ready
This will vary by language, but for Node.js apps, just make sure:
- The
npm start
script is specified inpackage.json
- The server listens on
process.env.PORT
not a hardcoded port number
4. Add the dokku remote to your local repository & deploy the app
You can skip this step if you only want to deploy via CircleCI.
cd my-app
git remote add dokku dokku@dokku.example.com:my-app
git push dokku master
5. Configure domain names on the server
ssh dokku
dokku domains:add my-app my-app.com www.my-app.com
6. Configure DNS
Modify the A
record in your DNS zone file for my-app.com
and set it to your server’s IP address. You probably also want to add a CNAME record for www.my-app.com
.
7. Enable SSL
dokku config:set --no-restart my-app DOKKU_LETSENCRYPT_EMAIL=x@x.com
dokku letsencrypt my-app
Configure CircleCI
1. Enable CirlceCI builds for your app
- Sign in to circleci.com and click “Add Projects”
- Find the repo for your app and click “Build project”
2. Create a ssh key pair so CircleCI can deploy to Dokku
ssh dokku
cd ~/.ssh
ssh-keygen -t rsa # save as circleci.id_rsa
sudo dokku ssh-keys:add circleci ./circleci.id_rsa.pub
cat ~/.ssh/circleci.id_rsa
3. Copy & paste your private key into CircleCI
Project Settings > SSH Permissions > Add SSH Key
4. Add circle.yml
to the root folder of your repo
deployment:
production:
branch: master
commands:
- git remote add production dokku@dokku.example.com:my-app
- git push production master
5. Push a commit to your master
branch or merge a pull request.
In a few minutes, you should see your app has been deployed to Dokku!