cloud, heroku, docker

Running your own Heroku-clone using CapRover

The Problem

I have to admit I have always been a big fan of heroku. Fantastic interface, great CLI tools, lots of add-ons & plugins, and it just works.

The downside of course is pricing, Heroku is one hell of an expensive PaaS and it has other limitations like not being able to runner Docker containers, etc ..

So I have always been testing Heroku-like PaaS solutions out there, like Dokku for example, but its has never been simple (in my opinion) to get up and running.

The Solution

But here comes CapRover (formerly CaptainDuckDuck)

I don't even remember how I came across this one, but I decided I would give it a try.

My expectations are simple

  • Web UI
  • CLI
  • Docker support
  • Web Hook based Github deploy
  • One click Let's Encrypt SSL certificate management
  • One click DNS management
  • One click install of standard resources (SQL Database, Redis, etc ..)

Let's go

As always, there are 2 prerequisites to running the "10 minute test"

  1. Read the tool’s documentation. Someone spent time writing it, so read it !
  2. Know your basics, know your tools

Here we go for CapRover

CapRover : The 30 minute test (*)

Yes we will give this one 30 minutes as there a lots of moving pieces.


Automatically deploy a docker container (containing a demo web application) on a custom domain through https.

Preparation (5 min)

Read the docs here


We will need :

  • an instance to run CapRover. In this post I will use a Digital Ocean cloud instance.
CapRover also has a one click digital ocean installation button, but I always prefer to learn how to install myself first.
  • A base domain name that will be used for our default DNS setup for all CapRover instance. Ex: *
  • Access to your DNS zone file for the chosen domain.

Installation (5 min)

Here is the droplet I used - 10 USD / month.

Let's now install Docker on Ubuntu as explained here

If you follow the instructions, you should be able see this :

A CapRover instance needs a couple of ports open to function. The details are explained here :

As root,

ufw allow 80,443,3000,996,7946,4789,2377/tcp
ufw allow 7946,4789,2377/udp;

To allow CapRover to always have a valid hostname for all the application you configure, we have to configure a "wildcard" DNS that points back to our new instance. Like this for example if you are using CloudFlare

We are now ready to run caprover itself. Log in to your instance and as root :

docker run -p 80:80 -p 443:443 -p 3000:3000 -v /var/run/docker.sock:/var/run/docker.sock -v /captain:/captain caprover/caprover

CapRover Configuration (10 min)

You should now be able to access your CapRover web UI on :

http://{IP of your instance}:3000

And see this

The default password is captain42 as mentioned in the documentation.

As recommended, we are going to use the command line client to configure CapRover.

On your local machine, install the CapRover CLI client (you must have npm installed):

npm i -g caprover

and then

caprover serversetup

And answer the questions as follows

Once that is done you can login the CapRover instance using

caprover login 

The CapRover CLI references your different servers using "local machine" names, this is what the "captain-01" stands for.

You can now login the Web UI again using :

https://captain.{your-base-domain}/ and use the password you chose just above.

That's it, your CapRover installation is finished. You can now disallow external connections on port 3000 since it won't be needed anymore.

ufw deny 3000/tcp

Installing our first application (15 min)

We can now do two things :

  • Install "one-click" apps such as WordPress, Ghost, MySQL, etc ...
  • Install your own app

The list of one click apps can be found here and it's also a good starting to create your own scripts (which are basically docker-compose like)

But let's focus on our objective which was to install a Docker based application that would redeploy using a git web hook.

The application we will use can be found here

it's a fork of 👏 with some minor changes

Just fork the project and clone it on your local machine

We can now create the application on CapRover. Call it hello-world and and click on Create New App.

It will appear in the list of application just below, and you can click on it to edit it.

An application configuration is divided into 3 parts

  • HTTP Settings - how you access the app from the outside world
  • App Configs - Environment variables, Persistent Volumes, etc ..
  • Deployment - How should CapRover deploy your app 👈

There are many different methods to deploy an app, but since we want automatic deploy from GitHub we'll use Method 3

Just fill in the required information and CapRover will generate a webhook url that you can then use in your GitHub project settings.

Now go to your GitHub project page => Settings => Webhooks => Add Webhook

Just paste the url you got from CapRover as Payload URL, and set the Content type to json, and leave all other options as-is.

That's it, now everytime you push something in your repo, GitHub will call that URL and CapRover will in turn rebuild your application.

But hey, wait, how does CapRover know how to "build" an application. That's where the "captain-definition" file comes in. This file lives in the root of your source tree and just tells CapRover where the docker file is.  

  "schemaVersion": 2,
  "dockerfilePath": "./Dockerfile"

That's it we are all set. Now to trigger a build, let's update a file in the project and push our changes on the repository.

Just update index.html and commit & push the changes

If everything went well, in your application's page on the CapRover UI, in the Deployment tab, you should see the deployment logs

If you now go to the HTTP Settings, you should see how to access your application

Click on the link and ... 🥁🥁

Want HTTPS for you app ?

CapRover will generate a Let's Encrypt certificate for that domain but you can also add your own domain by configure a CNAME to the CapRover generate hostname. CNAME

Then CapRover will also allow you to enable HTTPS for that new domain.


Let's re-edit index.html again, and push our changes. Wait a few seconds and you can reload the page in your browser

But let's imagine we quickly want to roll back to the previous version ! Just go to the deployment tab of your application and you will see the list of builds and click on the "rollback" icon.

And CapRover will just redeploy that version.


Here is a quick recap of what we were expecting and achieved.

  • Web UI  ✅
  • CLI ✅
  • Docker support  ✅
  • Web Hook based Github deploy  ✅
  • One click Let's Encrypt SSL certificate management  ✅
  • One click DNS management  ✅
  • One click install of standard resources (SQL Database, Redis, etc ..) ✅

If you have questions, or if some aspects are not clear feel free to shoot in the comments section.