Deploying Shiny Apps to Heroku with Docker and GitHub Actions
Tags: heroku, shiny, rstats, docker
Published: 2021-07-15 14:39:05

*By: [Peter Solymos](https://hosting.analythium.io/author/peter/)*

I introduced the Heroku cloud platform for Shiny apps on the Hosting
Data Apps website. We saw [how to use the command line tools to have a
git-based
workflow](https://hosting.analythium.io/deploying-shiny-apps-to-heroku-with-docker-from-the-command-line/).
In this post, we take this one step further. You will learn how to set
up continuous integration/continuous delivery (CICD) with GitHub actions
to build and deploy the Shiny app to Heroku.

## Example application

You can find an example of this tutorial on GitHub in the
[analythium/heroku-shiny](https://github.com/analythium/heroku-shiny)
repository.

In this post, we will concentrate on how to deploy a single app from the
root of the application. But the example repository has some
instructions for hosting and deploying multiple apps from the same
repository.

The workflow described here works with **public and private
repositories**. It requires some setup in the Heroku dashboard and
GitHub settings. Once set up, you just keep pushing commits and the rest
is taken care of by the pipeline.

## Setup on Heroku

Log into Heroku, in the dashboard, click on 'New' then select 'Create
new App'.

![](https://lh5.googleusercontent.com/5DI16X9-knEAdanLx3KVOW058N-OA3N8IViOktS8ipViXb6om26mxsEtYw4owmjX4RDFnrDUO-KfqOz-0dKsUsuejohccdsrUgjrFTId62oF2PCKb1PxQINBESz3rhd48oEi8WF3)

Give a name (e.g. `shiny-example`, if available, this will create the
app at <https://shiny-example.herokuapp.com/>) to the app and create the
app.

![](https://lh3.googleusercontent.com/kzm8zW2PZC4YHqy341FdV5qpHW3kBr6JI8OSETH09vcuA8SFLsWiDJLnYfHKLB4yR1i97mTZWv5yhiey9pHq1fUExz4pAAH_wrpoCyTSSGmxvBpRTp1F77nlHitmKAHi1x9JX68Q)

In your Heroku dashboard, go to your personal settings.

![](https://hosting.analythium.io/content/images/2021/07/heroku-dashb.png)

Find your API key, click on reveal and copy it, you'll need it later.

![](https://lh3.googleusercontent.com/70FvxcRGLs7au_kt81huZhrOvX6CJuaIlYqjTr2z0TInbJfeEm4VQWBrfBRQ5JVwhBCg1FPbZ8DgasUddHPpGHsEL7UZyjgSn44HnRIfzhkmvSuN1ldIvYZbE8C4iSYSIf5WUgBz)

## Setup on GitHub

Go to the Settings tab of the GitHub repository, scroll down to Secrets
and add your `HEROKU_EMAIL` and `HEROKU_API_KEY` as repository secrets:

![](https://hosting.analythium.io/content/images/2021/07/Screen-Shot-2021-07-10-at-6.27.35-PM.png)

## GitHub Action

See the `.github/workflows/deploy.yml` file in the example repository
for options (see comments in the YAML file):

  - add the **Heroku app name** (e.g. `shiny-example`) that was set up
    in the Heroku dashboard previously,
  - optionally, set the `appdir` variable to e.g. `app1`, this is the
    directory the script will use to find the Shiny files relative to
    the `Dockerfile` in the root of this directory.

Here is the YAML file for the GitHub action:

```yaml
name: Build Shiny Docker Image and Deploy to Heroku

on:
  push:
    branches:
      - main

jobs:
  app1:
    name: Build and deploy Shiny app
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Build and push Docker to Heroku
        uses: akhileshns/heroku-deploy@v3.12.12
        with:
          heroku_app_name: shiny-example
          appdir: "."
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_email: ${{ secrets.HEROKU_EMAIL }}
          usedocker: true
```

What do we have here? First, the app name. Then the `on` section
determines the events that trigger the workflow, here git push to the
`main` branch. Next, you have the description of the jobs, including the
steps. Job names must be unique in the YAML file to avoid parsing
errors.

The steps in the `app1` job are:

  - checkout: pull the main branch with the latest changes to the app
  - build and push the Docker image to the Heroku container registry:
    this is based on the `akhileshns/heroku-deploy` GitHub action.

The Docker build/push-piece can be achieved using shell commands. The
following alternative is more verbose than the ready-made action. I
include the shell version here as a reference. It shows the power of
shell scripts in GitHub actions and how to use secrets and environment
variables:

```yaml
name: Build Shiny Docker Image and Deploy to Heroku

on:
  push:
    branches:
      - main

jobs:
  app1:
    name: Build and deploy Shiny app
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Build and push Docker to Heroku
        env:
          HEROKU_APP_NAME: shiny-example
          DOCKERFILE_DIRECTORY: "."
          HEROKU_EMAIL: ${{ secrets.HEROKU_EMAIL }}
          HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
          DOCKERFILE_NAME: "Dockerfile"
          DOCKER_OPTIONS: "--no-cache"
        run: |
          cd ${DOCKERFILE_DIRECTORY}
          echo ${HEROKU_API_KEY} | docker login \
            --username=${HEROKU_EMAIL} \
            registry.heroku.com \
            --password-stdin
          docker build \
            --file ${DOCKERFILE_NAME} \
            ${DOCKER_OPTIONS} \
            --tag registry.heroku.com/${HEROKU_APP_NAME}/web .
          heroku container:push web --app ${HEROKU_APP_NAME}
          heroku container:release web --app ${HEROKU_APP_NAME}
```

Trigger the GitHub action by a new commit to the repo. When all goes
well, you should see logs like this:

![](https://hosting.analythium.io/content/images/2021/07/Screen-Shot-2021-07-11-at-12.00.16-AM.png)

If you now go to the Heroku dashboard, on the application's page click
on the 'Activity' tab and you will see the note about the new
deployment.

## Conclusions

You created a continuous integration/continuous delivery (CICD) pipeline
for a dockerized Shiny application. The CICD pipeline uses GitHub
actions to build and deploy the Docker image to the versatile
application platform called Heroku.

## Further reading

  - [Heroku
    reference](https://devcenter.heroku.com/categories/reference)
  - [Heroku container registry and
    runtime](https://devcenter.heroku.com/articles/container-registry-and-runtime)
  - [Heroku deployment with
    Git](https://devcenter.heroku.com/articles/git)
  - [Deploy to Heroku GitHub
    action](https://github.com/marketplace/actions/deploy-to-heroku)
  - [Deploying multiple Shiny apps from the same
    repository](https://github.com/mayamathur/evalue_website#deploying-shiny-apps-to-heroku)
  - [Example with health check and
    rollback](https://medium.com/analytics-vidhya/deploying-an-r-shiny-app-on-heroku-free-tier-b31003858b68)