DEV Community

Thiago Rodrigues
Thiago Rodrigues

Posted on

Automating Deployments to Heroku with GitHub Actions and Docker: Streamlining the Deployment Process

Tutorial: Automating Heroku Deployments with GitHub Actions and Docker: Streamlining the Deployment Process

In this tutorial, we'll delve into the process of utilizing GitHub Actions to automate the deployment of Docker images to Heroku. By the end of this tutorial, you'll have the know-how to achieve continuous deployment for a Fastify + TypeScript application.

Dependencies

pnpm add -D typescript @types/node ts-node ts-node-dev
pnpm add fastify prisma @prisma/client
Enter fullscreen mode Exit fullscreen mode

Script Configuration

{
  "scripts": {
    "dev": "ts-node-dev --respawn --transpile-only --ignore-watch node_modules src/index.ts",
    "start": "ts-node src/index.ts",
    "build": "tsc"
  }
}
Enter fullscreen mode Exit fullscreen mode

Setting Up the Backend

We'll start by setting up a simple backend since our primary goal lies elsewhere.

import fastify from 'fastify';

const app = fastify();

app.get('/', async (request, reply) => {
  return { hello: 'world' };
});

export const createServer = async () => {
  const PORT: number = Number(process.env.PORT) || 3001;
  const HOST: string = process.env.HOST || '0.0.0.0';

  try {
    await app.listen(PORT, HOST);
    console.log(`Server is listening at ${HOST}:${PORT}`);
  } catch (error) {
    console.error('Error starting the server:', error);
    process.exit(1);
  }
};

createServer();
Enter fullscreen mode Exit fullscreen mode

Dockerfile Creation

Next, let's craft a Dockerfile for our application. We'll employ the Docker multi-stage build approach, which allows us to create a production image that's considerably smaller than the development one, as we don't require all the development dependencies.

FROM node:16

WORKDIR /app

COPY package.json ./
COPY pnpm-lock.yaml ./
COPY tsconfig.json ./

COPY . .

RUN npm install -g pnpm
RUN pnpm install

RUN npx prisma generate

CMD ["pnpm", "run", "start"]
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml Setup

Now, we'll create a docker-compose file to facilitate development.

version: "3.9"
services:
  server_api:
    stdin_open: true
    build:
      context: .
      dockerfile: Dockerfile
    ports:
        - "3001:3001"
    container_name: server_api
    restart: always
    volumes:
      - .:/app
Enter fullscreen mode Exit fullscreen mode

Understanding GitHub Actions

GitHub Actions is a powerful tool provided by GitHub that enables you to automate various workflows, including building, testing, and deploying applications. It allows you to define custom workflows using YAML files, which can be triggered by events such as pushes, pull requests, or even on a schedule.

Creating the Workflow

Let's proceed to establish the GitHub Actions workflow. For this, create a file named deploy.yml within the .github/workflows directory.

name: Deploy to Heroku

on:
  push:
    branches: [master]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Build, Push and Release a Docker container to Heroku
        uses: gonuit/heroku-docker-deploy@v1.3.3
        with:
          email: ${{ secrets.HEROKU_EMAIL }}
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
          dockerfile_directory: ./
          dockerfile_name: Dockerfile
          docker_options: "--no-cache"
          process_type: web
Enter fullscreen mode Exit fullscreen mode

In this workflow:

  1. We define the workflow's name and specify that it should trigger on pushes to the master branch.
  2. The workflow runs on an ubuntu-latest virtual environment.
  3. We set up Node.js using the actions/setup-node action.
  4. Dependencies are installed using pnpm.
  5. We build a Docker image for our Fastify app.
  6. We log in to the Heroku container registry.
  7. The Docker image is pushed to Heroku.
  8. Finally, the Docker image is released on Heroku.

Remember to replace your-heroku-app-name with your actual Heroku app name.

Finalizing

In this tutorial, we've covered a comprehensive process for automating the deployment of a Dockerized Fastify + TypeScript application to Heroku using GitHub Actions. We started by setting up the backend, creating a Dockerfile, and configuring the docker-compose.yml file for easier development. We introduced GitHub Actions, explaining its significance in automating workflows. Finally, we created a GitHub Actions workflow that builds, pushes, and releases a Docker container to Heroku upon pushing changes to the master branch.

By embracing this automated deployment process, you can significantly enhance the efficiency and reliability of your application deployments, saving valuable time and minimizing manual errors.

Top comments (0)