{"id":1169,"date":"2022-01-04T16:48:38","date_gmt":"2022-01-04T23:48:38","guid":{"rendered":"https:\/\/bullyrooks.com\/?p=1169"},"modified":"2022-01-25T07:10:25","modified_gmt":"2022-01-25T14:10:25","slug":"cloud-kube-docker-build-and-registry","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2022\/01\/04\/cloud-kube-docker-build-and-registry\/","title":{"rendered":"Cloud Kube | Docker Build and Registry"},"content":{"rendered":"\n<p>Now that we&#8217;ve got a pipeline, we&#8217;re going to start working on deploying our service into the cloud.  The first step is to create a docker image and store it somewhere that our pipeline as well as our cloud provider can access.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create a Docker Image Registry<\/h2>\n\n\n\n<p><a href=\"https:\/\/www.canister.io\/\">Canister.io<\/a> provides a convenient and free (for small needs) docker container registry.<\/p>\n\n\n\n<p>Create an account there you should get a default namespace (mine&#8217;s bullyrooks).  Once you&#8217;re in create a new repo<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"70\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-18.png?resize=694%2C70&#038;ssl=1\" alt=\"\" class=\"wp-image-1170\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-18.png?w=694&amp;ssl=1 694w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-18.png?resize=300%2C30&amp;ssl=1 300w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Name it <code>cloud_application<\/code> and submit the repo creation form<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"549\" height=\"600\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-19.png?resize=549%2C600&#038;ssl=1\" alt=\"\" class=\"wp-image-1171\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-19.png?w=549&amp;ssl=1 549w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-19.png?resize=275%2C300&amp;ssl=1 275w\" sizes=\"auto, (max-width: 549px) 100vw, 549px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Now we need to add the registry credentials to our github repo.  Navigate to your github repo and click on the settings tab.  Find secrets in the nav bar.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"314\" height=\"153\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-20.png?resize=314%2C153&#038;ssl=1\" alt=\"\" class=\"wp-image-1172\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-20.png?w=314&amp;ssl=1 314w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-20.png?resize=300%2C146&amp;ssl=1 300w\" sizes=\"auto, (max-width: 314px) 100vw, 314px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>We&#8217;re going to make two secrets <code>CANISTER_USERNAME <\/code>and <code>CANISTER_PASSWORD<\/code> populating those values with the credentials we just created for canister.io<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"333\" height=\"424\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-21.png?resize=333%2C424&#038;ssl=1\" alt=\"\" class=\"wp-image-1173\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-21.png?w=333&amp;ssl=1 333w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-21.png?resize=236%2C300&amp;ssl=1 236w\" sizes=\"auto, (max-width: 333px) 100vw, 333px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"706\" height=\"177\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-22.png?resize=706%2C177&#038;ssl=1\" alt=\"\" class=\"wp-image-1174\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-22.png?w=706&amp;ssl=1 706w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-22.png?resize=300%2C75&amp;ssl=1 300w\" sizes=\"auto, (max-width: 706px) 100vw, 706px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Create a Dockerfile<\/h2>\n\n\n\n<p>Create a new file in the root of the project directory called <code>Dockerfile<\/code>.  Add this code<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># syntax=docker\/dockerfile:experimental\nFROM openjdk:11-slim-buster as build\n\nCOPY .mvn .mvn\nCOPY mvnw .\nCOPY pom.xml .\nCOPY src src\n\n# Setup the maven cache\nRUN --mount=type=cache,target=\/root\/.m2,rw .\/mvnw -B package -DskipTests\n\nFROM openjdk:11-jre-slim-buster\nCOPY --from=build target\/*.jar app.jar\nENTRYPOINT &#91;\"java\", \"-jar\", \"app.jar\"]\n<\/code><\/pre>\n\n\n\n<p>Here&#8217;s what we&#8217;re doing<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>download a build image that has java 11 already installed on it<\/li><li>copy over our build files one by one<\/li><li>build the jar using a cache of the maven .m2 directory<\/li><li>download a clean build image<\/li><li>copy the .jar we just created into that image<\/li><li>tell docker to start our jar on startup<\/li><\/ul>\n\n\n\n<p>Docker has pretty advanced caching techniques built in.  By defining our build in this way we&#8217;re limiting the number of things that need to be rebuild for small changes (like a code change).  Larger changes (like adding a dependency) can&#8217;t use previously cached stages, so they&#8217;ll have to rebuild from an earlier stage (but not from the earliest phases such as downloading the build image).  <\/p>\n\n\n\n<p>you can build locally to test it out<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ docker build .<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Add Docker Build to our Pipeline.<\/h2>\n\n\n\n<p>Add the following lines to our <code>feature.yaml<\/code> github actions file (you&#8217;ll have to change out the image name for your registry name)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n      - name: Set up Docker Buildx\n        uses: docker\/setup-buildx-action@v1\n\n      - name: Login to canister.io\n        uses: docker\/login-action@v1\n        with:\n          registry: cloud.canister.io:5000\n          username: ${{ secrets.CANISTER_USERNAME }}\n          password: ${{ secrets.CANISTER_PASSWORD }}\n\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker\/metadata-action@v3\n        with:\n          images: cloud.canister.io:5000\/bullyrooks\/cloud_application\n\n      - name: Cache Docker layers\n        uses: actions\/cache@v2\n        with:\n          path: \/tmp\/.buildx-cache\n          # Key is named differently to avoid collision\n          key: ${{ runner.os }}-multi-buildx-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-multi-buildx\n\n      - name: Build and push\n        id: docker_build\n        uses: docker\/build-push-action@v2\n        with:\n          context: .\n          push: true\n          tags: ${{ steps.meta.outputs.tags }}\n          labels: ${{ steps.meta.outputs.labels }}\n          cache-from: type=local,src=\/tmp\/.buildx-cache\n          cache-to: type=local,mode=max,dest=\/tmp\/.buildx-cache-new\n        # This ugly bit is necessary if you don't want your cache to grow forever\n        # till it hits GitHub's limit of 5GB.\n        # Temp fix\n        # https:\/\/github.com\/docker\/build-push-action\/issues\/252\n        # https:\/\/github.com\/moby\/buildkit\/issues\/1896\n      - name: Move cache\n        run: |\n          rm -rf \/tmp\/.buildx-cache\n          mv \/tmp\/.buildx-cache-new \/tmp\/.buildx-cache<\/code><\/pre>\n\n\n\n<p>Here&#8217;s what we&#8217;re doing with this pipeline:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Configure docker build to use buildx.  This has enhanced features such as caching which we&#8217;ll utilize.<\/li><li>Login to our container registry<\/li><li>Connect to our registry to access our image metadata (such as tags and labels).  This allows us to access them in the build\/push action.<\/li><li>Restore a cache of our previous docker build so that we can leverage it in this build<\/li><li>Build and push our docker image using our previous login.<\/li><li>Move the build cache as a workaround for a github action bug.  (via Documentation)<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Git Commit and Push<\/h2>\n\n\n\n<p>Lets push this up on a feature branch to see if it builds:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git checkout -b docker_build\nSwitched to a new branch 'docker_build'\n\n$ git add .\n\n$ git commit -m \"docker build on feature\"\n&#91;docker_build e1cfbec] docker build on feature\n 2 files changed, 48 insertions(+), 1 deletion(-)\n create mode 100644 Dockerfile\n\n$ git push --set-upstream origin docker_build\nEnumerating objects: 10, done.\nCounting objects: 100% (10\/10), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (5\/5), done.\nWriting objects: 100% (6\/6), 1.30 KiB | 1.30 MiB\/s, done.\nTotal 6 (delta 1), reused 0 (delta 0), pack-reused 0\nremote: Resolving deltas: 100% (1\/1), completed with 1 local object.\nremote: \nremote: Create a pull request for 'docker_build' on GitHub by visiting:\nremote:      https:\/\/github.com\/bullyrooks\/cloud_application\/pull\/new\/docker_build\nremote:\nTo github.com-bullyrook:bullyrooks\/cloud_application.git\n * &#91;new branch]      docker_build -&gt; docker_build\nBranch 'docker_build' set up to track remote branch 'docker_build' from 'origin'.\n<\/code><\/pre>\n\n\n\n<p>Its going to take a long time the first time because <strong>EVERYTHING<\/strong> has to be pulled down, cached and built the first time.  Subsequent builds shouldn&#8217;t take as long.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create the Main Build Pipeline<\/h2>\n\n\n\n<p>We&#8217;re going to merge this to main, but we have to add the docker build to the main pipeline as well.  I&#8217;m going to do something a little different here though.  When we build on a feature branch we&#8217;re tagging the image with a build tag by default.  When we build off of main we&#8217;re going to want a semantic version.  There&#8217;s a bunch of ways to do this, but I want it to be automated and as hands off as possible.<\/p>\n\n\n\n<p>Add this code to the <code>main.yaml<\/code> github action file.  Again, make sure to change out your image name for your registry name.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      <span class=\"has-inline-color has-vivid-red-color\">- name: Bump version\n        run: |\n          git config --global user.email \"github+actions@gmail.com\"\n          git config --global user.name \"Actions\"\n          git fetch --tags\n          wget -O - https:\/\/raw.githubusercontent.com\/treeder\/bump\/master\/gitbump.sh | bash\n          echo \"VERSION=$(git tag --sort=-v:refname --list \"v&#91;0-9]*\" | head -n 1 | cut -c 2-)\" >> $GITHUB_ENV<\/span>\n\n      - name: Set up Docker Buildx\n        uses: docker\/setup-buildx-action@v1\n\n      - name: Login to canister.io\n        uses: docker\/login-action@v1\n        with:\n          registry: cloud.canister.io:5000\n          username: ${{ secrets.CANISTER_USERNAME }}\n          password: ${{ secrets.CANISTER_PASSWORD }}\n\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker\/metadata-action@v3\n        with:\n          images: cloud.canister.io:5000\/bullyrooks\/cloud_application\n          #setting value manually, but could come from git tag\n          tags: |\n            type=ref,event=tag\n\n      - name: Cache Docker layers\n        uses: actions\/cache@v2\n        with:\n          path: \/tmp\/.buildx-cache\n          # Key is named differently to avoid collision\n          key: ${{ runner.os }}-multi-buildx-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-multi-buildx\n\n      - name: Build and push\n        id: docker_build\n        uses: docker\/build-push-action@v2\n        with:\n          context: .\n          push: true\n          <span class=\"has-inline-color has-vivid-red-color\">tags: |\n            cloud.canister.io:5000\/bullyrooks\/cloud_application:${{ env.VERSION }}<\/span>\n          cache-from: type=local,src=\/tmp\/.buildx-cache\n          cache-to: type=local,mode=max,dest=\/tmp\/.buildx-cache-new\n        # This ugly bit is necessary if you don't want your cache to grow forever\n        # till it hits GitHub's limit of 5GB.\n        # Temp fix\n        # https:\/\/github.com\/docker\/build-push-action\/issues\/252\n        # https:\/\/github.com\/moby\/buildkit\/issues\/1896\n      - name: Move cache\n        run: |\n          rm -rf \/tmp\/.buildx-cache\n          mv \/tmp\/.buildx-cache-new \/tmp\/.buildx-cache\n<\/code><\/pre>\n\n\n\n<p>You can see that we&#8217;re pulling in a script from a github repo, setting an environment variable and then using that as our tag when we push up the image.  This script automatically revs the version (based on a git tag) and then pushes that tag back onto the git commit.  I am pretty sure that it only revs patch version though, if you want to rev major or minor version, you&#8217;ll have to push up a git tag onto the main branch that reflects your desired version.<\/p>\n\n\n\n<p>Lets try it out.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git add .\n\n$ git commit -m \"main pipeline docker update\"\n&#91;docker_build 350e053] main pipeline docker update\n 1 file changed, 37 insertions(+), 1 deletion(-)\n\n$ git push\nEnumerating objects: 9, done.\nCounting objects: 100% (9\/9), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (4\/4), done.\nWriting objects: 100% (5\/5), 1.16 KiB | 1.17 MiB\/s, done.\nTotal 5 (delta 1), reused 0 (delta 0), pack-reused 0\nremote: Resolving deltas: 100% (1\/1), completed with 1 local object.\nTo github.com-bullyrook:bullyrooks\/cloud_application.git\n   fd00054..350e053  docker_build -&gt; docker_build\n\n$ git merge --squash docker_build\nUpdating cf0e328..350e053\nFast-forward\nSquash commit -- not updating HEAD\n .github\/workflows\/features.yaml                    | 27 ++++++++++++++-\n .github\/workflows\/main.yaml                        | 38 +++++++++++++++++++++-\n Dockerfile                                         | 22 +++++++++++++\n ...\/controller\/HelloWorldController.java           |  1 -\n 4 files changed, 85 insertions(+), 3 deletions(-)\n create mode 100644 Dockerfile\n\n$ git commit -m \"docker build pipeline\"\n&#91;main f4e91b4] docker build pipeline\n 4 files changed, 85 insertions(+), 3 deletions(-)\n create mode 100644 Dockerfile\n\n$ git push\nEnumerating objects: 28, done.\nCounting objects: 100% (28\/28), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (11\/11), done.\nWriting objects: 100% (15\/15), 2.19 KiB | 2.19 MiB\/s, done.\nTotal 15 (delta 3), reused 0 (delta 0), pack-reused 0\nremote: Resolving deltas: 100% (3\/3), completed with 2 local objects.\nTo github.com-bullyrook:bullyrooks\/cloud_application.git\n   cf0e328..f4e91b4  main -&gt; main\n\n\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Versioning<\/h2>\n\n\n\n<p>Switch back over to your github actions and watch the main pipeline build.  You should see something like this in your build logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#18 DONE 15.8s\nSetting outputs\n  digest=sha256:d75d79c29e3975afec55478aa44f34f3c986da53d18d3afda4671c953699ef6c\n  metadata={\n    \"containerimage.config.digest\": \"sha256:773003bc0ecd2b1fce4174b048664c06c4a942aa0ca2ff639aebad5978ecf823\",\n    \"containerimage.digest\": \"sha256:d75d79c29e3975afec55478aa44f34f3c986da53d18d3afda4671c953699ef6c\",\n    \"image.name\": \"cloud.canister.io:5000\/***\/cloud_application:0.0.1\"\n  }<\/code><\/pre>\n\n\n\n<p>And you can see that the version was calculated (defaults to <code>0.0.1<\/code> when no previous version is available) and pushed up an image tagged with that version.<\/p>\n\n\n\n<p>You can confirm this in git<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git pull\nremote: Enumerating objects: 1, done.\nremote: Counting objects: 100% (1\/1), done.\nremote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0\nUnpacking objects: 100% (1\/1), 142 bytes | 47.00 KiB\/s, done.\nFrom github.com-bullyrook:bullyrooks\/cloud_application\n * &#91;new tag]         v0.0.1     -&gt; v0.0.1\nAlready up to date.\n\n$ git tag \nv0.0.1\n<\/code><\/pre>\n\n\n\n<p>And you can push up a new major version<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git tag -a v1.0.0 -m \"pushing major version\"\n\n$ git push origin v1.0.0\nEnumerating objects: 1, done.\nCounting objects: 100% (1\/1), done.\nWriting objects: 100% (1\/1), 164 bytes | 164.00 KiB\/s, done.\nTotal 1 (delta 0), reused 0 (delta 0), pack-reused 0\nTo github.com-bullyrook:bullyrooks\/cloud_application.git\n * &#91;new tag]         v1.0.0 -&gt; v1.0.0\n<\/code><\/pre>\n\n\n\n<p>make a minor change (a newline will work) and push that up as well<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git add .\n\n$ git commit -m \"no op change\"\n&#91;main a060e27] no op change\n 1 file changed, 1 insertion(+)\n\n$ git push\nEnumerating objects: 19, done.\nCounting objects: 100% (19\/19), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (7\/7), done.\nWriting objects: 100% (10\/10), 749 bytes | 749.00 KiB\/s, done.\nTotal 10 (delta 2), reused 0 (delta 0), pack-reused 0\nremote: Resolving deltas: 100% (2\/2), completed with 2 local objects.\nTo github.com-bullyrook:bullyrooks\/cloud_application.git\n   f4e91b4..a060e27  main -&gt; main\n<\/code><\/pre>\n\n\n\n<p>And you&#8217;ll see that the version change was picked up and incorporated<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Setting outputs\n  digest=sha256:f69dc33471f047f3f60b7ecb0d1ab561dba3e95ef30e7be655777e9d507079f1\n  metadata={\n    \"containerimage.config.digest\": \"sha256:d77cb98a1e750d2a6a8aa3cad1858ab04eb1c37e6dfb19ed327fdaa34c0c7dea\",\n    \"containerimage.digest\": \"sha256:f69dc33471f047f3f60b7ecb0d1ab561dba3e95ef30e7be655777e9d507079f1\",\n    \"image.name\": \"cloud.canister.io:5000\/***\/cloud_application:1.0.1\"\n  }<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nNow that we&#8217;ve got a pipeline, we&#8217;re going to start working on&hellip;\n<\/div>\n<div class=\"link-more\"><a href=\"https:\/\/bullyrooks.com\/index.php\/2022\/01\/04\/cloud-kube-docker-build-and-registry\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Cloud Kube | Docker Build and Registry&rdquo;<\/span>&hellip;<\/a><\/div>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[5,75,74],"course":[149],"class_list":["post-1169","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-docker","tag-docker-registry","tag-dockerfile","course-kubernetes-application-hosted-in-the-cloud","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":826,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-9-55fd26c1dffb\/","url_meta":{"origin":1169,"position":0},"title":"Docker Registry","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"In the previous article we created a docker image as part of our build process and stored it into our local repository. In order to deploy it in an automated fashion we should create a remote image repository in the cloud. This will expand the types of tools that we\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":824,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-10-e1a3a8e865bb\/","url_meta":{"origin":1169,"position":1},"title":"Automated Build Pipeline","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"Lets set up automated build so that we can generate a docker image when a change hits master. Build the\u00a0Pipeline Go in to codefresh and choose Projects. Create a new project in the top right. Call it medium. Click on create pipeline. Call the pipeline medium-customer and choose our git\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":833,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-18-9dff659cd334\/","url_meta":{"origin":1169,"position":2},"title":"UI Build Pipeline","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"Simple Spring Boot Service to Kubernetes Application: Step\u00a018 Lets quickly update our build pipeline to push an image for our front end application into our repo. This opens the path to using helm to package and deploy our chart. Create a New\u00a0Pipeline Log into codefresh and go into pipelines. Choose\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1188,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/01\/04\/cloud-kube-setup-cloud-hosting\/","url_meta":{"origin":1169,"position":3},"title":"Cloud Kube | Setup Cloud Hosting","author":"Bullyrook","date":"January 4, 2022","format":false,"excerpt":"We've got a helm chart and associated docker image. Now we're going to setup a cloud kubernetes provider to deploy our application to. Okteto offers a very generous kubernetes hosting platform that's free for small developer projects. Setup Okteto First register on okteto by creating an account via your github\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-31.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-31.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-31.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":549,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/01\/25\/installing-portainer-in-docker-on-synology\/","url_meta":{"origin":1169,"position":4},"title":"Installing Portainer in Docker on Synology","author":"Bullyrook","date":"January 25, 2021","format":false,"excerpt":"Although we can install and run docker containers directly in the synology docker package, I recommend installing portainer as a docker management tool. Portainer has a nice web based user interface, which means that you can access it directly via the browser instead of logging into the synology DSM and\u2026","rel":"","context":"In &quot;Home Networking&quot;","block_context":{"text":"Home Networking","link":"https:\/\/bullyrooks.com\/index.php\/category\/technology\/home-networking\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/01\/Screen-Shot-2021-01-23-at-6.00.11-PM.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":816,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-12-c6423261a93a\/","url_meta":{"origin":1169,"position":5},"title":"Setting up a Kubernetes Cluster","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"Finally, we\u2019re going to be able to deploy our application. We need to get access to a cluster first. Install Tooling We\u2019re going to need more tools in order to get started. Use your OS package management tool to install these tools: Kubectl (Interact with a k8s instance)Minikube (Run a\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1169","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/comments?post=1169"}],"version-history":[{"count":9,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1169\/revisions"}],"predecessor-version":[{"id":1255,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1169\/revisions\/1255"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=1169"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=1169"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=1169"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=1169"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}