To package and deploy your application on Kubernetes Engine, we did the following:
- Packaged our app into a Docker image
- Ran the container locally to ensure all was well
- Created a container cluster
- Created a CI image for the CI-CD pipeline
- Created a CI-CD pipeline that uses the above image
- Deployed our app to the cluster
- Exposed our app to the Internet
- Concluded the setup
We shall go through this one after the other as we shed more light on what exactly was done under each phase.
If you intend to follow though but have no prior knowledge of deploying containerised applications to the Google Kubernetes Engine, I'd kindly suggest you go through their official tutorial first. If you have dabbled in the art of container orchestration and management, or just like living on the edge, let's continue.
In the root of this repository you will find the Dockerfile responsible for the creation of the image we run in our containers.
To set it up, just clone the repo, ensure you have Docker installed in your computer and run
docker build -t <dockerhub_username>/<app_name>:<tag_of_choice> .
After replacing the placeholder values with those of your choosing, you can build the app image as we did.
Well we are the pessimistic type and we did not want to leave anything to chance as far as the integrity of our image is concerned.
docker inspect <your_dockerhub_username>/<image_name>:<your_tag_of_choice>
This dumps some json content to standard output. You want to check the containerConfig
and the Config
sections ensuring the WorkingDir
value is the same for both. The other key point of interest should be the Cmd
sub-section whose value should be an array. The containerConfig
Cmd
array will have "CMD [\"yarn\" \"run\" \"start\"]"
as the last element of the array while the config
Cmd
array will just be the entries in the CMD
section of the Dockerfile
. If this is the case then the image did build successfully and the container will launch properly.
We used a command much similar to this one to run it locally.
docker run -p 3000:3000 <dockerhub_username>/<app_name>:<tag_of_choice>
You could also run the container in detached
mode using the following command. This will just dump the ID of the running container ro standard output but the application will be accessible since it's running in the background
docker run -p 3000:3000 -d <dockerhub_username>/<app_name>:<tag_of_choice>
The result was a running container that could be accessed over the browser on http://localhost:3000
If the above command errors with the error shown below, then the port 3000 is currently being used by another app or process, just change the first
3000
in the-p 3000:3000
port binding section to an available port, say3001
. To access the app use your new port number in the URL, in the case of port3001
the url should now be http://localhost:3001.
Following the Before you begin section of the resource recommended above. We set up a cluster on our Gcloud Project.
As you maybe wondering - if you are not let's just assume you were - we opted to create out own image bootstrapped with some tools that are key to the success of our CI/CD pipeline. For a better understanding of why and how we achieved this, head on over to the You are using a custom CI image... How? Why? section of the project wiki page on the whole containerisation endeavour.
If you the above explanation got you to read further down the Wiki, you might have read the section explaining the CI/CD pipeline setup. But if you're lazy as some people we know, head on over there and get your scoop of ice cream with the cherry on top. Don't be gone too long though, we just got to the good part.
PS Incase it's not so evident, the app is actually deployed to the cluster when the yummy-react.deployment.yml
file is applied by kubectl
on the cluster.
If the word play is getting a bit much, my apologies. Head on to the Okay... Makes sense. So how does the deployment happen? section of the wiki for a description on how this happens.
Be sure to not how we use the gcloud sdk, ReactiveOps Scripts, Docker and the kubectl tool to orchestrate a deployment to the cluster we created.
PS Incase it's not so evident, the app is actually deployed to the cluster when the yummy-react.service.yml
file is applied by kubectl
on the cluster.
The same section above does go into slightly more details on where exactly in the deployment script this happens though it does so implicitly since the same command that deploys the app to the pod on the cluster creates a service of type loadbalancer
to serve the application over http. In so doing the appication (after a few domain mappings that go beyond the scope of this document) is now accessible over this address http://app.yummy-react.indungu.ml.
The journey was a tough one seeing us we had never really done this before, not successfully at least. But what we learnt we invaluable and we hope this breakdown helped you get your feet wet with deploying containerised application to a kubernetes engine.
Your suggestion, questions, comments and especially corrections for the typos I may have missed are most welcome. Just fork and PR all of them, your input is highly appreciated. Until next time, LIVE LONG AND PROSPER!
PS: A place to start contribution-wise is improving this document by making the Table Of Contents part at the beginning have links that point to the actual breakdown of the work done. Thanks.