Deploy multiple Docker containers using Github Actions and Heroku
8 min read
Prequisite:
- 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 hubFROM node:18.5.0-alpine3.16
# Create directory your app will be build in within the Alpine containerWORKDIR /frontend
# copy both your package.json and package-lock-json file within the /frontend directory COPY ./package.json .COPY ./package.lock.json .
# Install packagesRUN npm ci
# After install, copy all files within ./frontend directoryCOPY . .
# Build your appRUN npm run build
# Expose frontend app port numberEXPOSE 3000
Run your frontend serverCMD 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 fileversion: "3.8"services:frontendApp:build:context: ./frontenddockerfile: Dockerfile ports:- "3000:3000"
backendApp:build:context: ./backenddockerfile: Dockerfileports:- "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.ymlname: Fullstack CSR app# Setup trigger deployment when you git push in the master branchon:push:branches:- master
jobs:build:runs-on: ubuntu-lateststeps:# Looks at your repositoty- uses: actions/checkout@v2# Create and deploy your multiple containers- name: Deploy multiple Docker images to Heroku appsuses: snithyanantham/docker-compose-mulitple-apps-heroku-deploy@v1.0id: herokuwith:# Your Heroku email addressemail: ${{ secrets.HEROKU_EMAIL }}# Your Heroku api keyapi_key: ${{ secrets.HEROKU_API_KEY }}# path to your docker-compose filedocker_compose_file: "./docker-compose.yml"# Set Docker images name, Heroku app name and Heroku app typeheroku_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.