blog 5 image

Deploy multiple Docker containers using Github Actions and Heroku

8 min read

Prequisite:
DockerDocker ComposeHerokuGithub ActionsFullstack - Client Side RenderingCI/CD
  • Should have good knowledge of Docker and Docker-Compose
  • Installed Docker within your local device
  • Should be registered to Heroku and Github
  • Basic understanding of CSR and CI/CD

      It is very common to deploy apps using CI/CD (Continuous Integration / Continuous Delivery). Actually, depending on which cloud application platform provider you use, all you will need to do is git push your app and they will setup a pipeline and deploy the app online for you. But it starts to get a bit complicated when you want to configure the pipeline yourself to match your app needs, plus, not to mention, it could get expensive real fast too.

What if you have a fullstack app which is using client side rendering? It would mean that you will need to hook up the frontend and backend api together since they are considered as separate apps within the repo. Usually, that is not a problem in itself, but it gets tricky if you want to implement a pipeline to both the applications. To throw in another spanner in the works, let's say we are wrapping the frontend and backend in a Docker container. We are going to be doing exactly this, using Heroku as your cloud provider.

Now it is worth noting that Heroku already provides a container deployment service, but it is not ideal when you have a fullstack CSR app (containing both frontend and backend), since you will have to git push them individually. Plus, having full control of your Docker means you control all app version packages from breaking and testing.

Let's assume your frontend and backend is setup within your repo, we should first create a Dockerfile file for each app, which should look something like this:

# ./frontend/Dockerfile file

# Create a Node.js and Alpine container
# Use whatever is the latest version from Docker hub
FROM node:18.5.0-alpine3.16

# Create directory your app will be build in within the Alpine container
WORKDIR /frontend

# copy both your package.json and package-lock-json file within the /frontend directory 
COPY ./package.json .
COPY ./package.lock.json .

# Install packages
RUN npm ci

# After install, copy all files within ./frontend directory
COPY . .

# Build your app
RUN npm run build

# Expose frontend app port number
EXPOSE 3000

Run your frontend server
CMD npm run server

Do not forget to create a Dockerfile file for your backend app too. It should look very similar to the frontend Dockerfile file.

When both Dockerfile files are working, you can proceed with Docker Compose which infuses both containers together.

# ./docker-compose.yml file
version: "3.8"
services:
frontendApp:
build:
context./frontend
dockerfileDockerfile 
ports:
"3000:3000"

backendApp:
build:
context./backend
dockerfileDockerfile
ports:
"4000:4000"

Use the docker-compose up command in the terminal to ensure everything is running smoothly.

Now we can move onto the next step, which is to create the Github Actions CI/CD pipeline (be sure you have already been registered with Github and Heroku prior). The Github Actions file is quite straightforward but you will need a few things beforehand; your Heroku email address and your Heroku api key, which can be found in your Heroku account settings. Once you get that, go to your Github app repo, and you set your environment secrets variables (found in your repo settings). Be sure to set HEROKU_EMAIL and HEROKU_API_KEY keys exactly as shown because your Github Actions file will search for these two secrets in order to give you access to your Heroku account.

After you have set your repo secrets, we can now create the Github Actions file to deploy your fullstack docker containers.

./.github/workflows/main.yml
nameFullstack CSR app
# Setup trigger deployment when you git push in the master branch
on:
push:
branches:
master

jobs:
build:
runs-onubuntu-latest
steps:
# Looks at your repositoty
usesactions/checkout@v2
# Create and deploy your multiple containers
nameDeploy multiple Docker images to Heroku apps
usessnithyanantham/docker-compose-mulitple-apps-heroku-deploy@v1.0
idheroku
with:
# Your Heroku email address
email${{ secrets.HEROKU_EMAIL }}
# Your Heroku api key
api_key${{ secrets.HEROKU_API_KEY }}
# path to your docker-compose file
docker_compose_file"./docker-compose.yml"
# Set Docker images name, Heroku app name and Heroku app type
heroku_apps'[{"imagename":"fullstack_frontendApp", "appname":"frontend", "apptype";"web"}, {"imagename"fullstack_backendApp", "appname":"backend", "apptype":"web"}]' 

If all done correctly, everytime you git push your local repo, Github Actions will build your Docker images and deploy to Heroku.

It does require a bit of configuration on your behalf, but once completed, in the long run it will serve you well, saving you more time.