Edit 02/07/2021: Thanks to all the Golang Reddit community. My post got featured and reached the top hot section 🔥.
Dokku is an easy and cost-effective approach to deploy your project in a language-agnostic way. It's an open-source and free alternative to Heroku on your own servers. Once set up, a simple
git push
command will update your app on your server.In this tutorial, we will use a simple Go HTTP server and deploy it from scratch on our Linux server. The Go HTTP server consists of a simple REST API which let user create, update, get and list Todos.
The code is available at: https://github.com/shellbear/dokku-go-example
Summary
- Choose a server
- Install dokku
- Web installation
- Create the app
- Install PostgreSQL
- Deploy your app
- Configure domain and HTTPS
- Manage environment variables
- Github auto deployment
- Final note
Choose a server
Since we will self-host our app, you need to have a server. Any provider or home server will be fine but if you're looking for a cheap one, you can check Digital Ocean or Vultr. They both provide VPS for a couple of euros or dollars.
Choose a Linux distribution and then you're done!
We will use a custom domain to deploy our app. So make sure you created a DNS record of the domain or subdomain of your choice to your Server IP.
Install dokku
Now that our server is running, we can connect to it via SSH and start installing dokku. I recommend you to refer to the main page to install it with the latest version and for your distribution (debian, apt, or arch).
On a Debian distribution, the command to install dokku is the following:
wget https://raw.githubusercontent.com/dokku/dokku/v0.24.10/bootstrap.sh; sudo DOKKU_TAG=v0.24.10 bash bootstrap.sh
The installation can take a couple of minutes, it will install all the decencies and start a web server for installation purposes.
Web installation
Then you have to open your browser and navigate enter your VPS IP. Here you can setup:
- Paste your Public Key, which can be a one you generate or an existing one
- Set the Hostname which can be your domain name if you have one (example.com)
- Enable the virtualhost option
Enabling these options will let you use custom subdomains when deploying your apps. For example, if your hostname is example.com deploying a web app will be publicly accessible at web.example.com instead of your VPS IP address.
Create the app
Now that your server is fully set up with dokku you have to create your first app. You should create an app for each app you want to deploy on your server.
Connect on your server and execute the following commands:
dokku apps:create go-example
Install PostgreSQL
Since our Go app requires a PostgreSQL instance, we will install it with dokku. To do so we just have to install the Postgres plugin:
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
And then create our PostgreSQL instance and link it to our Go app:
dokku postgres:create example dokku postgres:link example go-example
The
postgres:create
command will create a new PostgreSQL instance with the example
name and the postgres:link
will link the database to our app and add a DATABASE_URL
environment variable to it which contains all the information to connect the database.Deploy your app
Now that our app and database are ready we can start deploying our app for the first time. By default, dokku will detect your Go code base and build a custom Docker image for you, but in some cases, it will use an old Go version. To use the latest Go version there are two solutions.
- Adding a
// +heroku goVersion VERSION
annotation to thego.mod
file.
- Creating a
Dockerfile
at the root of your project and use the latest go version
Since it's the simplest solution, we will add the following comment to our
go.mod
:// +heroku goVersion 1.16 module github.com/shellbear/dokku-go-example ....
Then you can configure git to push your code to your dokku server. Just replace
YOUR_VPS_IP
with your VPS IP address:git remote add dokku dokku@YOUR_VPS_IP:go-example git push dokku main
Wait some minutes and tada! Your app should be deployed on your server. But wait, you can't yet access publicly your app, we have to make some further configuration to make it accessible.
Configure domain and HTTPS
Connect back to your VPS with SSH and install Let's Encrypt so we can have free HTTPS support for your custom domain:
sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git dokku config:set --global DOKKU_LETSENCRYPT_EMAIL=your-email@your.domain.com
Now that Let's Encrypt plugin is installed you can configure your domain and HTTPS for your app:
# set a custom domain that you own for your application dokku domains:set go-example go-example.example.com # enable letsencrypt dokku letsencrypt:enable go-example # enable auto-renewal dokku letsencrypt:cron-job --add
Note: if you have any error during this step such as
acme: error: 403 :: urn:ietf:params:acme:error:unauthorized
, make sure that your correctly configured your domain name so it points to your VPS IP.If everything worked, you should be able to access your Go app at the domain you defined, with HTTPS support out of the box.
From now, every time you will
git push dokku main
, your code will be automatically deployed, on your server.Manage environment variables
If you app need further environment variables, you can manually add ENV variables to your app with the
config:set
command:dokku config:set go-example VARIABLE_NAME=value SECOND_VARIABLE=other_value
You can also view the existing environment variables:
dokku config:show go-example =====> go-example env vars .... SECOND_VARIABLE: other_value VARIABLE_NAME: value
And you can easily remove environment variables with the
config:unset
command:dokku config:unset go-example VARIABLE_NAME SECOND_VARIABLE
Every change will trigger a deployment, so you don't have to do it manually after changes.
Github auto deployment
As you saw every deployment requires to manually execute
git push
command on your host machine. You certainly want to automate this process and automatically deploy your code on Git changes. Since we're using Github we can create a Github Action to automatically deploy our code on changes.
Create a
.github/workflows/deploy.yml
with the following content:--- name: 'deploy' on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Cloning repo uses: actions/checkout@v2 with: fetch-depth: 0 - name: Push to dokku uses: dokku/github-action@master with: git_remote_url: 'ssh://dokku@YOUR_VPS_IP:22/go-example' ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
This Github action will be executed when any change is made on the
main
branch. Then you have to create the SSH_PRIVATE_KEY
secret. Go in the Settings and then Secrets section of your repository and copy your SSH private key.A good practice is to create a new key only for this Github Deploy action. If someone steals your private key, you can just revoke the old one and generate a new one.
If you want to generate a new SSH key, execute the following command on your host machine:
ssh-keygen -f dokku_rsa
This will generate a
dokku_rsa
private key and dokku_rsa.pub
which is the public key. Copy the content of dokku_rsa
and paste it into the Github secret value.And then the newly create key to your dokku server:
cat dokku_rsa.pub | ssh cloud@YOUR_VPS_IP dokku ssh-keys:add github
This one-line command will pipe the content of your public key to the
ssh-keys:add
of your VPS.Now every time you push some code, it will automatically be deployed on your VPS.
Final note
As you saw, deploying a Go app with dokku is really fast and easy. Having auto-deployment and HTTPS in a few minutes is really a big plus.
Using dokku should be fine for low or moderate production workload. But dokku is not yet made for HA. There are some schedulers plugins to deploy on either Kubernetes or Nomad. This can be a solution if you have higher load needs.
Make sure to check the code at: https://github.com/shellbear/dokku-go-example
Thanks for reading 👋