I was hosting this blog on a Vultr VPS that was running just nginx for these static files (generated by hugo) and it was fine, but I had other plans for the server, and it’s usually a pain to mix your projects with an existing nginx config, so I’ve moved on to dokku for serving this blog as well.
If you don’t know it, dokku is amazing. Spin up a new server, run the bootstrap commands:
$ wget https://raw.githubusercontent.com/dokku/dokku/v0.12.10/bootstrap.sh $ sudo DOKKU_TAG=v0.12.10 bash bootstrap.sh
Hit the server on a browser to upload your SSH pubkey, and that’s it! From then
on, you can just create new git remotes for your projects and do
git push dokku
to have a ready-to-serve-requests Docker image created for them. It uses Heroku
buildpacks, so most popular languages are supported, and you can always set your
For this website, I’m using dokku-static-site, and it was just a matter of creating a Dockerfile in my hugo folder root with
And change hugo’s output folder to match the expected
publishDir = "html/"
config.toml and that’s it. My workflow is now a) create a new hugo post/page,
hugo and then c) do a commit and push. The deployment takes less than a minute:
$> git push dokku Counting objects: 11, done. Delta compression using up to 16 threads. Compressing objects: 100% (9/9), done. Writing objects: 100% (11/11), 850 bytes | 850.00 KiB/s, done. Total 11 (delta 6), reused 0 (delta 0) remote: Preparing /tmp/dokku_git.NfRT (identifier dokku_git.NfRT) remote: ~/blog /tmp/dokku_git.NfRT ~/blog remote: /tmp/dokku_git.NfRT ~/blog -----> Cleaning up... -----> Building blog from dockerfile... remote: build context to Docker daemon 717.3kB Step 1/1 : FROM giorgos/dokku-static-site # Executing 1 build trigger ---> 04a3ab1b444c Successfully built 04a3ab1b444c Successfully tagged dokku/blog:latest -----> Releasing blog (dokku/blog:latest)... -----> Deploying blog (dokku/blog:latest)... -----> Attempting to run scripts.dokku.predeploy from app.json (if defined) -----> No Procfile found in app image -----> DOKKU_SCALE file found (/home/dokku/blog/DOKKU_SCALE) =====> web=1 -----> Attempting pre-flight checks -----> Attempt 1/5 Waiting for 5 seconds ... CHECKS expected result: http://localhost/ => "" -----> All checks successful! =====> blog web container output: 172.17.0.1 - - [17/Jun/201835:49 +0000] "GET / HTTP/1.1" 200 5936 "-" "curl/7.52.1" =====> end blog web container output -----> Running post-deploy -----> Configuring blog.dokku.nootch.net...(using built-in template) -----> Configuring blog.nootch.net...(using built-in template) -----> Creating https nginx.conf -----> Running nginx-pre-reload Reloading nginx -----> Setting config vars DOKKU_APP_RESTORE: 1 Reinitializing monit daemon -----> Found previous container(s) (0aee033b0ab5) named blog.web.1 =====> Renaming container (0aee033b0ab5) blog.web.1 to blog.web.1.1529220954 =====> Renaming container (1a347d42c126) priceless_brahmagupta to blog.web.1 -----> Attempting to run scripts.dokku.postdeploy from app.json (if defined) Trying to find token and chat_id for blog -----> Notifying Telegram chat ... -----> Shutting down old containers in 60 seconds =====> 0aee033b0ab52022514697fcdea4884a4c3edac7409bdead83b55fb70643615a =====> Application deployed: http://blog.dokku.nootch.net http://blog.nootch.net https://blog.dokku.nootch.net https://blog.nootch.net To dokku.nootch.net:blog 2296848..836bf6f master -> master
It’s quite easy to setup Let’s Encrypt, Telegram bot notifications, webhooks, extra domains and more with dokku plugins. This is my go-to setup for new deployments on servers, since Docker images are much more portable and self-contained than a bespoke nginx setup. Give dokku a try, it’ll amaze you!