
Prologue
Recently, I learned about a "pocket" PaaS similar to Heroku with a rather obvious name — Dokku. I was particularly attracted by the ability to easily add a certificate to the application and vhost out of the box, so I decided to migrate my Docker images to Dokku. However, I was disappointed to find that Dokku lacks commands similar to those in Heroku.
dokku container:push
dokku container:release
// It would have been very convenient, but it’s not available yet :(There is a command that allows deploying images, but the image must already be on the host at that moment. In other words, to release a newly created local image, it needs to be copied to the host first.
tags:create # Add tag to latest running app image
tags:deploy # Deploy tagged app image
tags:destroy # Remove app image tagI am familiar with Ansible and even created simple pipelines for delivering the backend using it, so the choice was easy. Of course, I could have gone through the trouble of writing a plugin for Dokku, but no, not now.
Playbook
This playbook archives a certain local image, copies it to the host, restores it, and deploys it in Dokku. I've placed it in a GitLab repository. There’s still plenty of room for improvement.
push-image.dokku.yml
---
- name: "DEPLOY APP '{{ appname }}' TO DOKKU"
hosts: dokku_hosts
remote_user: root
gather_facts: false
vars:
tarname: "{{ appname }}__{{ image }}.tar"
upload_dir: "\/usr\/local\/src"
upload_path: "{{ upload_dir }}\/{{ tarname }}"
apptag: "{{ upload_tag | default('latest') }}"
dokku_image: "dokku\/{{ appname }}:{{ apptag }}"
tasks:
- name: "Archive '{{ image }}' to upload"
register: env
delegate_to: localhost
shell:
cmd: docker image save -o ".\/{{ tarname }}" {{ image }}
- name: "Upload image '{{ image }}' to dokku at '{{ inventory_hostname }}'"
register: upload
copy:
src: ".\/{{ tarname }}"
dest: "{{ upload_path }}"
- name: "Log - Upload result"
debug:
var: upload.dest
- name: "Restore uploaded docker image"
register: restore
shell:
cmd: docker image load -i "{{ upload_path }}"
- name: "Log - Restore image"
debug:
var: restore.stdout_lines
- name: "Retag image to '{{ dokku_image }}'"
shell:
cmd: docker tag "{{ image }}" "{{ dokku_image }}"
- name: "Create dokku tag for '{{ dokku_image }}'"
shell:
cmd: dokku tags:create "{{ appname }}" "{{ apptag }}"
- name: "Release '{{ appname }}'"
register: release
shell:
cmd: dokku tags:deploy "{{ appname }}" "{{ apptag }}"
- name: "Log - Release"
debug:
var: release.stdout_lines
It is assumed that Ansible is already installed on the local machine and Dokku on the host.
Use it like this
ansible-playbook push-image.dokku.yml -i some_inventory -e "appname=DOKKU_APP_NAME image=DOCKER_IMAGE"some_inventory
[dokku_hosts]
your.domain.exampleSource: habr.com
