Deploying Docker Image on Dokku with Ansible

Deploying Docker Image on Dokku with Ansible

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 tags 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 tag

I 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

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.example

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster