<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jean-Nicolas Moal</title>
    <description>The latest articles on DEV Community by Jean-Nicolas Moal (@jnmoal).</description>
    <link>https://dev.to/jnmoal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F690098%2F9a8c2e53-2dc9-4548-b704-ec0289215466.png</url>
      <title>DEV Community: Jean-Nicolas Moal</title>
      <link>https://dev.to/jnmoal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jnmoal"/>
    <language>en</language>
    <item>
      <title>GitLab CI speeding up your pipeline with caching</title>
      <dc:creator>Jean-Nicolas Moal</dc:creator>
      <pubDate>Wed, 12 Apr 2023 13:12:59 +0000</pubDate>
      <link>https://dev.to/jnmoal/gitlab-ci-speeding-up-your-pipeline-with-caching-5400</link>
      <guid>https://dev.to/jnmoal/gitlab-ci-speeding-up-your-pipeline-with-caching-5400</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;GitLab CI comes with a &lt;a href="https://docs.gitlab.com/ee/ci/caching/:"&gt;cache system&lt;/a&gt; very useful when you want to speed up your pipeline.&lt;/p&gt;

&lt;p&gt;In this article, we’ll see how we can use the cache system to speed up our pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📌 NOTE&lt;/strong&gt;&lt;br&gt;
Don’t use cache to store build results, artifacts are made for this.&lt;/p&gt;
&lt;h2&gt;
  
  
  What you should know about GitLab CI cache
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.gitlab.com/ee/ci/caching/#where-the-caches-are-stored:"&gt;cache is stored where&lt;/a&gt; the gitlab runner is installed.&lt;br&gt;
It can be uploaded if the distributed cache is enabled.&lt;br&gt;
If you’re running your runners in Kubernetes, the distributed cache is a must-have.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://docs.gitlab.com/ee/ci/caching/#clearing-the-cache:"&gt;clear the cache&lt;/a&gt; when necessary.&lt;/p&gt;

&lt;p&gt;You can use a &lt;a href="https://docs.gitlab.com/ee/ci/caching/#use-a-fallback-cache-key:"&gt;fallback key&lt;/a&gt; when your cache doesn’t exist. Useful to share cache between branch, while still keeping some isolation.&lt;/p&gt;

&lt;p&gt;You can have up to 4 caches per pipeline.&lt;/p&gt;

&lt;p&gt;You can tell GitLab whether you want to pull-push (download and update) the cache, or if you just want to pull it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❗ IMPORTANT&lt;/strong&gt;&lt;br&gt;
For security reason, GitLab creates a different cache if the branch is protected or not. This feature is configurable, but active by default on your project. You can read more on this &lt;a href="https://docs.gitlab.com/ee/ci/caching/#cache-key-names:"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's play with the caching system
&lt;/h2&gt;

&lt;p&gt;Say that you have a python project, for which you need to run linters, tests suites... And finally, you want to package your application.&lt;br&gt;
And you have the following constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your final package shall only contain what’s necessary to run&lt;/li&gt;
&lt;li&gt;Only download dependencies when they’ve changed&lt;/li&gt;
&lt;li&gt;The cache from the main branch is the reference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this example, we’ll set up the cache so that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each branch will have its own cache&lt;/li&gt;
&lt;li&gt;When building on a new branch, the build will fall back to the main branch cache&lt;/li&gt;
&lt;li&gt;The dependencies will only be downloaded and updated when necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For clarity, we’ll only use fake jobs in this example.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defining rules to manage cache updates
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;.deps_update_rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_COMMIT_BRANCH != "main" ①&lt;/span&gt;
      &lt;span class="na"&gt;changes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;my-referent-file.lock ②&lt;/span&gt;
        &lt;span class="na"&gt;compare_to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;refs/heads/main ③&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_COMMIT_BRANCH == "main" ④&lt;/span&gt;
      &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_COMMIT_TAG != &lt;/span&gt;&lt;span class="no"&gt;null&lt;/span&gt;&lt;span class="s"&gt; ⑤&lt;/span&gt;
      &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;When not on the main branch, we only update dependency if necessary.&lt;/li&gt;
&lt;li&gt;Put all the relevant files here&lt;/li&gt;
&lt;li&gt;Compares changes with the main branch&lt;/li&gt;
&lt;li&gt;On the main branch, always update dependencies&lt;/li&gt;
&lt;li&gt;When tagging the repository, update the dependencies&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This hidden field defines rules that will be reused by our job.&lt;br&gt;
If you aren’t familiar with rule, &lt;a href="https://docs.gitlab.com/ee/ci/jobs/job_control.html:"&gt;check out this documentation&lt;/a&gt;.&lt;br&gt;
Feel free to adapt those rules to your workflow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the cache
&lt;/h3&gt;

&lt;p&gt;Before creating the jobs to update our caches, let’s first define some reusable stuff.&lt;br&gt;
We’ll leverage some &lt;a href="https://docs.gitlab.com/ee/ci/variables/predefined_variables.html:"&gt;predefined variables&lt;/a&gt; to make this work properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;DEFAULT_CACHE_KEY_PREFIX&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${CI_DEFAULT_BRANCH} ①&lt;/span&gt;
  &lt;span class="na"&gt;CACHE_KEY_PREFIX&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${CI_COMMIT_REF_SLUG} ②&lt;/span&gt;
  &lt;span class="na"&gt;DEPS_FOLDER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${CI_PROJECT_DIR}/.deps ③&lt;/span&gt;

&lt;span class="na"&gt;.deps_dev_cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;④&lt;/span&gt;
  &lt;span class="s"&gt;cache&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;deps_dev_cache&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${CACHE_KEY_PREFIX}-deps-dev ⑤&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${DEPS_FOLDER}&lt;/span&gt;
    &lt;span class="na"&gt;policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull ⑥&lt;/span&gt;

&lt;span class="na"&gt;.deps_run_cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;⑦&lt;/span&gt;
  &lt;span class="s"&gt;cache&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;deps_run_cache&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${CACHE_KEY_PREFIX}-deps-run&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${DEPS_FOLDER}&lt;/span&gt;
    &lt;span class="na"&gt;policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Use to define the fallback cache key in the job&lt;/li&gt;
&lt;li&gt;Use to define the cache key to be used by the job&lt;/li&gt;
&lt;li&gt;The location of the downloaded dependencies (the folder we want to keep)&lt;/li&gt;
&lt;li&gt;The cache configuration for jobs that needs the dev dependencies&lt;/li&gt;
&lt;li&gt;The key to use to find the cache with a suffix to identify dev dependencies&lt;/li&gt;
&lt;li&gt;The default policy we want to use, most jobs only need to download the cache, not to update it.&lt;/li&gt;
&lt;li&gt;The cache configuration for jobs that needs the run dependencies&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;📌 NOTE&lt;/strong&gt;&lt;br&gt;
The environment variables with the &lt;code&gt;CI_&lt;/code&gt; prefix are predefined variables.&lt;/p&gt;

&lt;p&gt;Now that we have our predefined cache configuration, let’s use them in the jobs that need to update the dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dev-dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;①&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prepare&lt;/span&gt;
  &lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "I am a dependency" &amp;gt; ./deps.txt&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "I am a dev dependency" &amp;gt;&amp;gt; ./deps.txt&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*deps_dev_cache&lt;/span&gt;
    &lt;span class="na"&gt;policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull-push&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!reference&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;.deps_update_rules&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;run-dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;②&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prepare&lt;/span&gt;
  &lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "I am a dependency" &amp;gt; ./deps.txt&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*deps_run_cache&lt;/span&gt;
    &lt;span class="na"&gt;policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull-push&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!reference&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;.deps_update_rules&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;This job can download all dependency groups as its cache will be used for linting, testing...&lt;/li&gt;
&lt;li&gt;This job shall download only the run dependency (for example &lt;code&gt;poetry install --only main&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using the cache
&lt;/h3&gt;

&lt;p&gt;Now, we can use those caches to test or package our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;test-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cat ./deps.txt&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*deps_dev_cache&lt;/span&gt;

&lt;span class="na"&gt;package-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cat ./deps.txt&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*deps_run_cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;📌 NOTE&lt;/strong&gt;&lt;br&gt;
Using this method, the pipeline must run at least once on the main branch before the other branches.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building OCI images with Buildah: Take control on how you build your container</title>
      <dc:creator>Jean-Nicolas Moal</dc:creator>
      <pubDate>Wed, 20 Oct 2021 07:35:43 +0000</pubDate>
      <link>https://dev.to/stack-labs/building-oci-images-with-buildah-take-control-on-how-you-build-your-container-45ec</link>
      <guid>https://dev.to/stack-labs/building-oci-images-with-buildah-take-control-on-how-you-build-your-container-45ec</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@carrier_lost?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Ian Taylor&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/shipping-container?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the Linux world, container technology has evolved in a way that we can consider them as a standard way to package and run an application.&lt;br&gt;
Because Docker is the most known tools to play with containers, Dockerfile is the most common way to build them.&lt;/p&gt;

&lt;p&gt;But today I want to share with you my preferred tool: &lt;a href="https://buildah.io/" rel="noopener noreferrer"&gt;Buildah&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
It's a powerful tool for building container image in a simple but yet efficient way.  &lt;/p&gt;

&lt;p&gt;In this article, we'll see how to build a basic image, how to optimize build time using cache, and how to install OS packages without having the OS installed within the container.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow this article, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/containers/buildah/blob/main/install.md" rel="noopener noreferrer"&gt;buildah&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://taskfile.dev/#/installation" rel="noopener noreferrer"&gt;task&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a &lt;a href="https://getfedora.org/fr/workstation/" rel="noopener noreferrer"&gt;Fedora&lt;/a&gt; based machine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building an image
&lt;/h2&gt;

&lt;p&gt;First, we'll create a basic container image and install Ansible in it.&lt;br&gt;&lt;br&gt;
Create a file called &lt;code&gt;build-unoptimized.sh&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; errexit

&lt;span class="c"&gt;# Creates a new container instance, and stores its name in CONTAINER_ID.&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;buildah from docker.io/fedora:34&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Runs commands within the created container.&lt;/span&gt;
buildah run &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"dnf install -y ansible-&lt;/span&gt;&lt;span class="nv"&gt;$ANSIBLE_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Save the container into an image.&lt;/span&gt;
buildah commit &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before running this script, let's add a &lt;code&gt;Taskfile.yaml&lt;/code&gt; to easily configure and build the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git log -n 1 --format=%h&lt;/span&gt;
  &lt;span class="na"&gt;ANSIBLE_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.9.25"&lt;/span&gt;

&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-unoptimized&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buildah-demo-unoptimized"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;without&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;optimization"&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;time -p ./build-unoptimized.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you run &lt;code&gt;task build-unoptimized&lt;/code&gt;, Buildah will create a container image based on &lt;code&gt;docker.io/fedora:34&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
It will install &lt;code&gt;ansible&lt;/code&gt; using &lt;code&gt;dnf&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
On my computer, running this task took 123 seconds and the image size is 614 MB.&lt;br&gt;
We could optimize the size of the image by cleaning up all the DNF cache, but there is a better alternative.&lt;/p&gt;
&lt;h2&gt;
  
  
  Optimizing by caching
&lt;/h2&gt;

&lt;p&gt;We can kill two birds with one stone with caching, this will help on building time and on the image size.&lt;br&gt;&lt;br&gt;
Let's create a file called &lt;code&gt;build-with-cache.sh&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; errexit

&lt;span class="nv"&gt;DNF_CACHE_FOLDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/.dnfcache/
&lt;span class="nv"&gt;RUN_OPTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-v &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DNF_CACHE_FOLDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:/var/cache/dnf:Z"&lt;/span&gt;

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DNF_CACHE_FOLDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Creates a new container instance, and stores its name in CONTAINER_ID.&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;buildah from docker.io/fedora:34&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Runs commands within the created container.&lt;/span&gt;
&lt;span class="c"&gt;# The keepcache=true in the dnf.conf file tells dnf not to delete successfully installed packages.&lt;/span&gt;
buildah run &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RUN_OPTION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"echo 'keepcache=True' &amp;gt;&amp;gt; /etc/dnf/dnf.conf &amp;amp;&amp;amp; dnf install -y --nodocs ansible-&lt;/span&gt;&lt;span class="nv"&gt;$ANSIBLE_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Save the container into an image.&lt;/span&gt;
buildah commit &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This new script does the exact same installation as the previous one, but this time it shares a specific local folder with the container,&lt;br&gt;&lt;br&gt;
so that all files downloaded with dnf are kept locally for next runs.&lt;br&gt;&lt;br&gt;
Let's add the corresponding task within the &lt;code&gt;Taskfile.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;build-with-cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buildah-demo-with-cache"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;caching"&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;time -p ./build-with-cache.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to test this new script, we need to run it twice.&lt;br&gt;&lt;br&gt;
The first time to create the cache, and the second one to see the improvements.  &lt;/p&gt;

&lt;p&gt;On my computer this build took 35 seconds, and the image size is 365 MB.&lt;br&gt;&lt;br&gt;
That's a huge improvement, we reduced the time by almost 4, and the size by almost 2.&lt;br&gt;&lt;br&gt;
The size is reduced because with this new script the cache is outside the container, so it doesn't end within the container.&lt;/p&gt;

&lt;p&gt;We could call it a day, but, in my opinion, containers shall only contains what is necessary to run.&lt;br&gt;&lt;br&gt;
So I don't want all the extra pre-installed packages that comes from the base image.&lt;/p&gt;

&lt;p&gt;Let's try to install Ansible from a scratch container.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing OS package, without the OS
&lt;/h2&gt;

&lt;p&gt;The idea is simple, we'll tell DNF to install all the package in a specific location.&lt;br&gt;&lt;br&gt;
If the package properly declares all its dependencies, then this should work fine.&lt;br&gt;&lt;br&gt;
But if it doesn't, then we'll need to find the missing packages and install them too.&lt;/p&gt;

&lt;p&gt;Let's create a file called &lt;code&gt;build-without-os.sh&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; errexit
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;buildah from scratch&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;MOUNT_POINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;buildah mount &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;DNF_CACHE_FOLDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/.dnfcache

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DNF_CACHE_FOLDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

dnf &lt;span class="nt"&gt;--installroot&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MOUNT_POINT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--releasever&lt;/span&gt; 34 &lt;span class="nt"&gt;--nodocs&lt;/span&gt; &lt;span class="nt"&gt;--setopt&lt;/span&gt; &lt;span class="nv"&gt;install_weak_deps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;--setopt&lt;/span&gt; &lt;span class="nv"&gt;cachedir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DNF_CACHE_FOLDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ansible-&lt;span class="nv"&gt;$ANSIBLE_VERSION&lt;/span&gt;

&lt;span class="c"&gt;# Save the container into an image.&lt;/span&gt;
buildah commit &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this script, I added the &lt;code&gt;--installroot&lt;/code&gt; option, which tells &lt;code&gt;dnf&lt;/code&gt; to install package in a specific location.&lt;br&gt;&lt;br&gt;
I also configured DNF with the &lt;code&gt;keepcache=True&lt;/code&gt; on my workstation.&lt;/p&gt;

&lt;p&gt;With this new script, we do not use command inside the container, but command available from the host.&lt;br&gt;&lt;br&gt;
This way, no need to have an OS installed or any other package manager inside the container.  &lt;/p&gt;

&lt;p&gt;Let's add the corresponding task in the &lt;code&gt;Taskfile.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;build-without-os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buildah-demo-without-os"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch"&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;time -p buildah unshare ./build-without-os.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;task build-without-os&lt;/code&gt; took 115 seconds on my computer, and the image size is 284 MB.&lt;br&gt;&lt;br&gt;
We've lost the build time improvement, but won on the size.&lt;br&gt;&lt;br&gt;
Since we started from scratch, &lt;code&gt;dnf&lt;/code&gt; needs to install more packages.  &lt;/p&gt;

&lt;p&gt;IMHO, it's an acceptable tradeoff since this new image only contains what's necessary.  &lt;/p&gt;

&lt;p&gt;But from now we only built images, but never tested it, and I can't say it's working if I don't test it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing the image
&lt;/h2&gt;

&lt;p&gt;I won't use a container registry just to test the image, so we're going to export the image and reload it from a container runtime.&lt;br&gt;&lt;br&gt;
Note that buildah builds OCI images, which might not work as-is for &lt;code&gt;docker&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Don't worry, there is an option &lt;code&gt;--format&lt;/code&gt; that you can use to build &lt;code&gt;docker&lt;/code&gt; compliant images.&lt;/p&gt;

&lt;p&gt;In my case, I'm going to use &lt;code&gt;podman&lt;/code&gt; to test the image, hereunder a generic task to test images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.IMAGE_NAME&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;IMAGE_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;sh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;buildah images --filter=reference={{ .IMAGE_NAME }} --format='{{ printf "{{ .ID }}" }}'&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test"&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;buildah push $IMAGE_ID oci-archive:${PWD}/{{ .IMAGE_NAME }}.tar.gz&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;podman import ./{{ .IMAGE_NAME }}.tar.gz&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;podman run -ti --rm localhost/{{ .IMAGE_NAME }}:$IMAGE_TAG /bin/ansible --version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now the task to test the image built from scratch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;test-without-os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buildah-demo-without-os"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Load&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;podman&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it"&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
        &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.IMAGE_NAME&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run &lt;code&gt;task test-without-os&lt;/code&gt; ansible version shall be printed.  &lt;/p&gt;

&lt;p&gt;This is it for now, thank you for reading this post.&lt;br&gt;
Feel free to share it, and see you later for more tech.&lt;/p&gt;

&lt;p&gt;Have a nice day!&lt;/p&gt;

</description>
      <category>container</category>
      <category>buildah</category>
    </item>
  </channel>
</rss>
