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
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"
}
}
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();
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"]
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
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
In this workflow:
- We define the workflow's name and specify that it should trigger on pushes to the
masterbranch. - The workflow runs on an
ubuntu-latestvirtual environment. - We set up Node.js using the
actions/setup-nodeaction. - Dependencies are installed using
pnpm. - We build a Docker image for our Fastify app.
- We log in to the Heroku container registry.
- The Docker image is pushed to Heroku.
- 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)