Strapi

Strapi CI with Dokku and Github Actions

Boaz Poolman

Published on 3 August 2024

The best way to deploy your Strapi applications is through an automated deployment pipeline, otherwise called "Continuous Integration" (CI).  I'll teach you how to build your Strapi app as a docker image using a Dockerfile, and how to deploy that image on a Dokku host. Once everything is setup all it takes to release a new version of your Strapi application is creating a new "Release" on Github and the Github Actions runner will take care of the rest!

Prerequisites

  • A Strapi v4 instance in a repository on Github
  • A Dokku server configured to run Strapi

To see how to configure a Dokku server to run Strapi please read my previous article about the topic:

[article-2]

Create a CI user

The first step is to create a user named `ci` on your Dokku host. You can do that by running the following command:

# on the Dokku host
sudo adduser ci

This command will prompt you to set a password for the user. Make sure to set a secure password and store it in a safe place.

Once you've created the user and saved the password you have to make sure it can fire sudo commands without a password. You can do that by adding the user to the `/etc/sudoers` file on your server. Edit the sudoers file and add the following line:

# on the Dokku host
ci	ALL=(ALL:ALL) NOPASSWD:ALL

Create a storage location

During our deployment workflow we'll transfer a docker image do the Dokku host. To make sure it'll arrive properly we'll have to configure it's destination.

On the Dokku host create a folder in the following location:

# on the Dokku host
/var/lib/dokku/data/storage/DOKKU_APP_NAME/docker-images

Once the folder is created, make sure to set the newly created `ci` user as it's owner. You can do that by running the following command

# on the Dokku host
chown ci /var/lib/dokku/data/storage/DOKKU_APP_NAME/docker-images

Create a Dockerfile

To build a docker image from our Strapi application we need a Dockerfile. The easiest way to create a Dockerfile for your Strapi application is by using the strapi-tool-dockerize from strapi-community: https://github.com/strapi-community/strapi-tool-dockerize 

To create the Dockerfile run:

npx @strapi-community/dockerize

The Dockerfile can then be committed and pushed to your Github repository.

Create a Github workflow

Below you'll find a Github Actions workflow YML which you can copy into your Github repository on the following location:

.github/workflows/deploy.yml

The deployment workflow will do the following things for you:

 

  1. Build the docker image
    1. It wil build the docker image based on your Dockerfile
  2. Transfer the image to your Dokku host
    1. It will use the `ci` user to `scp` the docker image into the storage location
  3. Deploy the app using git:from-image
    1. Once the docker image has arrived on the Dokku host it will use the `dokku git:from-image` to deploy your app using that image

 

name: Deploy

on:
  release:
    types: [published]

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment:
      name: Production
      url: ${{ secrets.PRODUCTION_URL }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Set up Docker
        uses: actions/setup-node@v3
        with:
          node-version: '14'

      - name: Build a Docker image
        run: |
          docker build -t strapi-docker-image:latest .
          docker save -o strapi-docker-image-latest.tar strapi-docker-image:latest

      - name: Transfer the Docker image to the Dokku server
        uses: appleboy/scp-action@v0.1.3
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_CI_USERNAME }}
          password: ${{ secrets.SSH_CI_PASSWORD }}
          source: strapi-docker-image-latest.tar
          target: /var/lib/dokku/data/storage/${{ secrets.DOKKU_APP_NAME }}/docker-images

      - name: Deploy the Dokku app based on the Docker image
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_CI_USERNAME }}
          password: ${{ secrets.SSH_CI_PASSWORD }}
          script_stop: true
          script: |
            sudo docker load -i /var/lib/dokku/data/storage/${{ secrets.DOKKU_APP_NAME }}/docker-images/strapi-docker-image-latest.tar
            STRAPI_LATEST_IMAGE=$(sudo docker images --format "{{.ID}}" strapi-docker-image:latest)
            sudo docker tag strapi-docker-image:latest strapi-docker-image:$STRAPI_LATEST_IMAGE
            dokku git:from-image ${{ secrets.DOKKU_APP_NAME }} strapi-docker-image:$STRAPI_LATEST_IMAGE
            sudo docker system prune --all --force

Github Actions secrets

The workflow file makes use of Github Action Secrets. You'll have to configure these in the settings section of your repository on Github. The following secrets need to be set:

PRODUCTION_URL: https://your-production-url.com
SSH_HOST: 127.0.0.1
SSH_CI_USERNAME: ci
SSH_CI_PASSWORD: YOUR_SECURE_CI_USER_PASSWORD
DOKKU_APP_NAME: strapi

Release your first version

And that's it! Make sure your Dockerfile and deploy.yml workflow file are both pushed to the repository on Github. Once that's done you can create a new release on Github by going to the following URL:

https://github.com/YOUR_USERNAME/YOUR_REPO_NAME/releases/new

Once you publish the release it will trigger the deployment pipeline automatically. Make sure it successfully finishes to guarantee a successfull deployment!

Boaz Poolman

Published on 3 August 2024

More of Strapi