Boost Your Shipping Velocity With Argo and Buildpacks
Learn how to use CNCF incubating project Buildpacks, an application definition, and image build to skip the Dockerfile step and increase developer productivity.
A recent Microsoft study looked into what drives developers’ productivity and found that the feedback loop had a strong impact. The findings recommend that feedback loops — the speed and quality of responses to actions performed — should be shortened to the maximum possible extent. One example they mention in their finding is the time it takes to push code to production.
CNCF graduated project Argo is one of the leading choices for continuous integration and delivery tools and generally makes developers’ lives easier. But before code can be pushed into Argo, developers typically need to write a Dockerfile to containerize it.
In this article, I will explore how to use CNCF incubating project Buildpacks, an application definition, and image build to skip the Dockerfile step and increase developer productivity.
How Can Buildpacks Increase Feedback Loop Speed?
Let’s first set the context for Buildpacks. Cloud native buildpacks transform your application source code into images running on any cloud. By looking at your code, Buildpacks auto-detect what is needed to build an OCI image with the best performance and security practices.
When using Buildpacks, writing a Dockerfile before pushing code so it can be pulled into Argo is no longer necessary. Developers can go from writing code to pushing it into the company CI/CD pipeline.
Integrates Buildpacks Within Argo
Buildpacks are specifications that define how source code is transformed into containerized applications. But to create an OCI image based on these specifications, you will use the pack command and specify a Buildpack (more on that later).
This step is used as part of an Argo workflow:
- name: build-image inputs: parameters: - name: passed-tag container: image: buildpacksio/pack command: ["pack", "build"] args: - "172.31.17.128:5000/my-python-app:{{inputs.parameters.passed-tag}} --path /mnt/vol/app --builder paketobuildpacks/builder-jammy-base --publish"
123456789 | - name: build-image inputs: parameters: - name: passed-tag container: image: buildpacksio/pack command: ["pack", "build"] args: - "172.31.17.128:5000/my-python-app:{{inputs.parameters.passed-tag}} --path /mnt/vol/app --builder paketobuildpacks/builder-jammy-base --publish"
---|---
Let’s go over each argument:
name: build-imageis the name of the Argo workflow step. My workflow has multiple steps (clone and build). For more info, refer to the entire configuration file on my Github repository.inputs: parameters: - name: passed-tagthis specifies which version of the code to use to build my image. This is optional, and I will explain it further in the next paragraph.image: buildpacksio/packwe are using the buildpacks/pack image to run this Argo step.command: ["pack", "build"]we tell the workflow to run thepack buildcommand.
Now let’s look at the pack build command arguments:
172.31.17.128:5000/my-python-app:{{inputs.parameters.passed-tag}}the IP is where my container registry is hosted. Here, I am using a self-hosted registry, but you can use anything from ECR to Dockerhub. The second part,my-python-app.is the name of my container image. In the next paragraph, I cover{{inputs.parameters.passed-tag}}.--path /mnt/vol/appis where my application code is.--builder paketobuildpacks/builder-jammy-basea builder is an image containing an ordered combination of buildpacks and a build-time base image, a lifecycle binary, and a reference to a runtime base image. I am using one from Paketo Buildpacks, but here are other providers, such as Google and Heroku.--publishpublishes the application image directly to the container registry specified in image name (see first argument), instead of the daemon.
That’s all you need to get Argo to containerize any application written in pretty much any language. There is no need for developers to write a Dockerfile, meaning that as soon as their application is written, they can push it to Argo and see it being deployed.
Image Immutability and Release Strategy
One important thing to know is that Buildpacks marks images with a fixed date (Jan. 1, 1980) for immutability and reproducibility. The reason for using a fixed timestamp is to ensure consistent image creation, which helps eliminate the differences caused by build times. This is a great security feature but can cause challenges for CI/CD deployment workflows. If your workflow is based on the latest tag, you will encounter issues because all images will have the same timestamp.
That’s why I am using a semver versioning strategy. In my Argo workflow, I leverage Argo parameter inputs to get the tag with which I want to build my image. I receive the tag with inputs: parameters: - name: passed-tag and pass it to my pack command with {{inputs.parameters.passed-tag}}.
Conclusion
Using Buildpacks as part of your Argo workflow will improve the developer experience and shipping velocity and ensure your container images are secure and optimized. Indeed, the open source implementation of the Buildpacks spec Paketo Buildpacks ensures that their images are always up-to-date with the latest CVE patches and tuned for every stack. Last but not least, if you want to dig deeper, I recorded a video showcasing this entire tutorial and going more in-depth on some of the concepts.
Topics