<?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: Clemens Kaserer</title>
    <description>The latest articles on DEV Community by Clemens Kaserer (@ckaserer).</description>
    <link>https://dev.to/ckaserer</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%2F336142%2F972ca13e-6e02-46b8-8631-c2b51f0b4fcd.jpeg</url>
      <title>DEV Community: Clemens Kaserer</title>
      <link>https://dev.to/ckaserer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ckaserer"/>
    <language>en</language>
    <item>
      <title>Sticky session in Kubernetes - Hello World!</title>
      <dc:creator>Clemens Kaserer</dc:creator>
      <pubDate>Thu, 02 Apr 2020 19:43:05 +0000</pubDate>
      <link>https://dev.to/ckaserer/sticky-session-in-kubernetes-hello-world-2kmo</link>
      <guid>https://dev.to/ckaserer/sticky-session-in-kubernetes-hello-world-2kmo</guid>
      <description>&lt;p&gt;Common requirements for stateful applications include the ability to support sticky sessions. Let's take a look on how to implement this in Red Hat OpenShift or Kubernetes. The excercise can be done either on OpenShift or Kubernetes. With OpenShift we will use additional OpenShift resource types that are not available in Kubernetes (e.g Routes in OpenShift vs Ingress in Kubernetes).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Out of scope&lt;/strong&gt; - we will not cover application level session replication as this is application or middleware specific.&lt;/p&gt;

&lt;p&gt;In this excercise we will work with a helm chart to install a simple application to showcase sticky sessions. Hence our prerequirements are as follows&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenShift or Kubernetes&lt;/li&gt;
&lt;li&gt;helm&lt;/li&gt;
&lt;li&gt;git&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ckaserer/kubernetes-examples/tree/master/kubernetes-statefulset"&gt;excersice repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To start the excercise we need to check out the excersie repo and update our &lt;code&gt;values.yaml&lt;/code&gt; to allow access from outside th cluster to our application depending on which platform we are using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Kubernetes&lt;/strong&gt; we enable the ingress resource by setting &lt;code&gt;create&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and the &lt;code&gt;host&lt;/code&gt; to a hostname that resolve to an IP of our cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Kubernetes
ingress:
  create: true
  host: "hello-ckaserer.apps.p.aws.ocp.gepardec.com"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For OpenShift&lt;/strong&gt; we enable the route resource by setting &lt;code&gt;create&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# OpenShift
route:
  create: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Okay, now that we have customized our configuration we can continue to install the resources from the helm chart via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ helm install hello .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Helm installs based on the config specified in &lt;code&gt;values.yaml&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a statefulset running our example application with 3 replica&lt;/li&gt;
&lt;li&gt;a ServiceAccount to run our statefulset&lt;/li&gt;
&lt;li&gt;a service&lt;/li&gt;
&lt;li&gt;an ingress or a route to access our application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To verify that our application is working as expected we can open the newly created ingress/route in a browser. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Kubernetes&lt;/strong&gt; you can use the cli to get the ingress information via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get ingress hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With OpenShift&lt;/strong&gt; you can either find the correct URL in the OpenShift Console (Web) or via the cli&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ oc get route hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As long as you do not delete the cookies you are using to access the website from the browser and the pod that is serving your request is not terminated you will always end up on the same pod.&lt;/p&gt;

&lt;p&gt;Let's take a look on what makes the route in &lt;strong&gt;OpenShift&lt;/strong&gt; sticky. Through annotations we can add additional information to the router instance exposing the route. By adding the annotation &lt;code&gt;router.openshift.io/cookie_name&lt;/code&gt; we tell the router to set and track cookies with the name &lt;code&gt;hello-1&lt;/code&gt;. Cookies are automatically used for https routes, but for http routes we need to set the &lt;code&gt;cookie_name&lt;/code&gt; to enable cookies for http traffic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind: Route
apiVersion: route.openshift.io/v1
metadata:
  name: hello
  annotations:
    router.openshift.io/cookie_name: "hello-1"
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What happens when we manually kill the pod we are currently connected to? Let's find out! First we need to be quick here or Kubernetes/OpenShift will have already spun another replica up and you might end up on a pod with the same name.&lt;/p&gt;

&lt;p&gt;So be quick and terminate the pod that you are currently connect to (e.g. hello-0) by executing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl delete pod hello-0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OpenShift&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ oc delete pod hello-0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Quickly open your browser and refresh the page. You should get a response from another replica now.&lt;/p&gt;

&lt;p&gt;Now let's do the same but with curl from our comandline&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ for I in $(seq 1 8); \
  do \
      curl -s \
      http://$(kubectl get ingress hello -o jsonpath='{.spec.rules[0].host}') | grep "Server name"; \
  done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OpenShift&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ for I in $(seq 1 8); \
  do \
      curl -s \
      http://$(oc get route hello -o jsonpath='{.spec.host}') | grep "Server name"; \
  done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you run curl multiple times as we do with the loop here you should realize that the backend pod varies. But why?! Well we curl the website without storing our cookie and therefore every request appears as a new client.&lt;/p&gt;

&lt;p&gt;In order to get the same behaviour as we have seen in the browser beforhand we need to store and use a cookie.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -s -o /dev/null \
    --cookie-jar cookies.txt \
    http://$(kubectl get ingress hello \
    -o jsonpath='{.spec.rules[0].host}')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OpenShift&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -s -o /dev/null \
    --cookie-jar cookies.txt \
    http://$(oc get route hello \
    -o=jsonpath='{.spec.host}')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Perfect, now we got our cookie file. Next we can use the cookie file for multiple curl commands and realize that every request is served by the same pod.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ for I in $(seq 1 8); \
  do \
      curl -s \
      --cookie cookies.txt \
      http://$(kubectl get ingress hello -o jsonpath='{.spec.rules[0].host}') | grep "Server name"; \
  done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OpenShift&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ for I in $(seq 1 8); \
  do \
      curl -s \
      --cookie cookies.txt \
      http://$(oc get route hello -o=jsonpath='{.spec.host}') | grep "Server name"; \
  done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wonderful, that's all for now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We installed a statefulset in OpenShift via helm and exposed it via a route. A web browser will automatically store cookies for us and our sticky session works out of the box. We always end up on the same pod unless the pod gets terminated or we delete our cookies.&lt;/p&gt;

&lt;p&gt;If we use curl from the commandline we did not get sticky sessions out of the box, since by default curl does not store cookies from one request to the next. We need to store our cookie manually and use it in our curl command in order to get the same behavior as with a web browser.&lt;/p&gt;

&lt;p&gt;What happens to the application state associated to my session if the pod is terminated? It's lost. In this example we did not cover application level session replication. If a pod is terminated all sessions of that pod are lost. E.g. if your app has a login functionality and are logged in before your pod terminates, you will be logged out after the pod terminated and another pod, unaware of your session, handles your request.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://livebook.manning.com/book/openshift-in-action"&gt;https://livebook.manning.com/book/openshift-in-action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/"&gt;https://kubernetes.io/docs/concepts/services-networking/service/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/documentation/en-us/openshift_container_platform/3.11/html/architecture/core-concepts"&gt;https://access.redhat.com/documentation/en-us/openshift_container_platform/3.11/html/architecture/core-concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openshift.com/container-platform/4.1/networking/routes/route-configuration.html#nw-annotating-a-route-with-a-cookie-name_route-configuration"&gt;https://docs.openshift.com/container-platform/4.1/networking/routes/route-configuration.html#nw-annotating-a-route-with-a-cookie-name_route-configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>stateful</category>
      <category>container</category>
      <category>openshift</category>
    </item>
    <item>
      <title>Containerized Travis CLI</title>
      <dc:creator>Clemens Kaserer</dc:creator>
      <pubDate>Sun, 15 Mar 2020 18:41:27 +0000</pubDate>
      <link>https://dev.to/ckaserer/containerized-travis-cli-1ipe</link>
      <guid>https://dev.to/ckaserer/containerized-travis-cli-1ipe</guid>
      <description>&lt;p&gt;&lt;a href="https://travis-ci.com"&gt;travis-ci.com&lt;/a&gt; describes itself as "The simplest way to test and deploy your projects."&lt;/p&gt;

&lt;p&gt;Travis offers a cli to interact with their services. That's great! We can use it to script functionality instead of manually executing and clicking in the UI every god damn time.&lt;/p&gt;

&lt;p&gt;I am no fan of installing various packages with different package managers all over my workstation. I am a big fan of container technology however and use travis-ci for most of my projects on github.&lt;/p&gt;

&lt;p&gt;Since I am an outspoken advocate of container technology and use travis-ci for most of my projects on github I put travis' cli in a ruby based container. This container is available in two flavors, either with a fixed version or with the latest and greatest travis cli release. The source code is available on &lt;a href="https://github.com/ckaserer/docker-travis-cli"&gt;github.com/ckaserer/docker-travis-cli&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you need to read up on what travis cli can do for you, here is the link you seek&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/travis-ci/travis.rb"&gt;https://github.com/travis-ci/travis.rb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Preflight
&lt;/h3&gt;

&lt;p&gt;Okay, the whole point is to avoid installing travis cli on our workstations. To avoid local installation we will use container technology as our abstraction layer.&lt;/p&gt;

&lt;p&gt;Therefore we will need to install a container runtime. Please install &lt;code&gt;docker&lt;/code&gt; on your workstation if you haven't done so already.&lt;/p&gt;

&lt;p&gt;In order to make it easier to use travis as a container a few bash functions are available in the &lt;code&gt;bashrc&lt;/code&gt; of the git &lt;a href="https://github.com/ckaserer/docker-travis-cli"&gt;repository&lt;/a&gt;. I really recommend that you source the &lt;a href="https://raw.githubusercontent.com/ckaserer/docker-travis-cli/master/bashrc"&gt;bashrc&lt;/a&gt; - it abstracts away all the options and parameter used in the docker command for you. In the next section you will see why.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;However it is not just black magic - all commands that are available via the bashrc in this repository will be printed before execution to increase transparency.&lt;/p&gt;




&lt;h3&gt;
  
  
  Run your travis cli command in a container
&lt;/h3&gt;

&lt;p&gt;Just like you would run your travis cli command locally you can do so with the &lt;code&gt;bashrc&lt;/code&gt; function &lt;code&gt;docker-travis&lt;/code&gt;. e.g. to get the cli version of the &lt;code&gt;travis-cli&lt;/code&gt; image you are using simply run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-travis travis version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which wraps following command for ease of use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -it -e TZ=Europe/Vienna -v /home/myuser/.travis:/root/.travis -v /home/myuser/path/to/your/current/directory:/root ckaserer/travis-cli travis version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see the container you are using is deleted after it ran with &lt;code&gt;--rm&lt;/code&gt;, set the timezone to Europe/Vienna, mount your current directory into the container to inject updates into files in your git repository. e.g. you want to add a slack token to your &lt;code&gt;.travis.yml&lt;/code&gt;. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>travis</category>
      <category>cicd</category>
    </item>
    <item>
      <title>cookiecutter for container images</title>
      <dc:creator>Clemens Kaserer</dc:creator>
      <pubDate>Sun, 01 Mar 2020 08:28:45 +0000</pubDate>
      <link>https://dev.to/ckaserer/cookiecutter-for-container-images-g4i</link>
      <guid>https://dev.to/ckaserer/cookiecutter-for-container-images-g4i</guid>
      <description>&lt;h2&gt;
  
  
  What is cookiecutter?!
&lt;/h2&gt;

&lt;p&gt;Cookiecutter is a command-line utility that creates projects from &lt;strong&gt;cookiecutters&lt;/strong&gt; (project templates), e.g. creating a Python package project from a Python package project template.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation: &lt;a href="https://cookiecutter.readthedocs.io"&gt;https://cookiecutter.readthedocs.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/cookiecutter/cookiecutter"&gt;https://github.com/cookiecutter/cookiecutter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.python.org/pypi/cookiecutter"&gt;https://pypi.python.org/pypi/cookiecutter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free and open source software: &lt;a href="https://github.com/cookiecutter/cookiecutter/blob/master/LICENSE"&gt;BSD license&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sidenote
&lt;/h3&gt;

&lt;p&gt;I maintain a containerized version of all cookiecutter releases starting with &lt;code&gt;1.7.0&lt;/code&gt; at &lt;a href="https://hub.docker.com/r/ckaserer/cookiecutter"&gt;dockerhub&lt;/a&gt;.&lt;br&gt;
If you want to know more check out the associated repository at &lt;a href="https://github.com/ckaserer/cookiecutter"&gt;github.com/ckaserer/cookiecutter&lt;/a&gt; or my blog post &lt;a href="https://ckaserer.dev/docker/2020/02/15/cookiecutter.html"&gt;containerized cookiecutter&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Cookiecutter for container images
&lt;/h2&gt;

&lt;p&gt;The goal of today is to standardize and automate your container image build process. From folder structure, to CICD, to publishing to a container registry, to build notifications via slack with cookiecutter templates.&lt;/p&gt;
&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;cookiecutter or its &lt;a href="https://ckaserer.dev/docker/2020/02/15/cookiecutter.html"&gt;containerized cookiecutter&lt;/a&gt; version&lt;/li&gt;
&lt;li&gt;travis&lt;/li&gt;
&lt;li&gt;container registry&lt;/li&gt;
&lt;li&gt;slack&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Getting stared
&lt;/h3&gt;

&lt;p&gt;To process the &lt;code&gt;docker-cookiecutter&lt;/code&gt; template execute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cookiecutter https://github.com/ckaserer/docker-cookiecutter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here a quick look at the resulting target folder structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-{{cookiecutter.image_name}}
├── .ci
│   └── test.sh                     &amp;lt;- put your tests here
├── .dockerignore                   &amp;lt;- ignore files when building
├── .github                         &amp;lt;- github issue templates
│   └── ISSUE_TEMPLATE
│       ├── bug_report.md
│       └── feature_request.md
├── .gitignore
├── .travis.yml                     &amp;lt;- slack notifications for our tests
├── CODE_OF_CONDUCT.md
├── Dockerfile                      &amp;lt;- what we actually want
├── LICENSE
├── README.md                       &amp;lt;- badges and quickstart info
└── bashrc                          &amp;lt;- bash functions for easy of use
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we need to add our registry credentials to be able to push our images to a container registry and our slack integration for build notifications.&lt;br&gt;
You can find a how-to for those steps in the README.md of your processed docker-cookiecutter template or directly via this &lt;a href="https://github.com/ckaserer/docker-travis-cli"&gt;link&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Source
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cookiecutter.readthedocs.io/en/latest/README.html"&gt;cookiecutter.readthedocs.io/en/latest/README.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ckaserer/cookiecutter"&gt;github.com/ckaserer/cookiecutter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ckaserer/docker-cookiecutter"&gt;github.com/ckaserer/docker-cookiecutter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/ckaserer/cookiecutter"&gt;hub.docker.com/r/ckaserer/cookiecutter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>cookiecutter</category>
      <category>devops</category>
      <category>template</category>
    </item>
    <item>
      <title>Containerized Cookiecutter</title>
      <dc:creator>Clemens Kaserer</dc:creator>
      <pubDate>Sat, 15 Feb 2020 14:30:59 +0000</pubDate>
      <link>https://dev.to/ckaserer/containerized-cookiecutter-1d5p</link>
      <guid>https://dev.to/ckaserer/containerized-cookiecutter-1d5p</guid>
      <description>&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://travis-ci.com/ckaserer/cookiecutter"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FAu5MRQY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://travis-ci.com/ckaserer/cookiecutter.svg%3Fbranch%3Dmaster"&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uTCwJG5q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://img.shields.io/docker/pulls/ckaserer/cookiecutter"&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sYMArEJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://img.shields.io/github/license/ckaserer/cookiecutter"&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--alcOInF---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://img.shields.io/maintenance/yes/2020"&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What is cookiecutter?!
&lt;/h2&gt;

&lt;p&gt;A command-line utility that creates projects from &lt;strong&gt;cookiecutters&lt;/strong&gt; (project templates), e.g. creating a Python package project from a Python package project template.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation: &lt;a href="https://cookiecutter.readthedocs.io"&gt;https://cookiecutter.readthedocs.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/cookiecutter/cookiecutter"&gt;https://github.com/cookiecutter/cookiecutter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.python.org/pypi/cookiecutter"&gt;https://pypi.python.org/pypi/cookiecutter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free and open source software: &lt;a href="https://github.com/cookiecutter/cookiecutter/blob/master/LICENSE"&gt;BSD license&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cookiecutter as a Container
&lt;/h2&gt;

&lt;p&gt;Wonderful, now let's use cookiecutter from a container instead of installing it on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base image
&lt;/h3&gt;

&lt;p&gt;The image is based on &lt;a href="https://hub.docker.com/_/python"&gt;python:3&lt;/a&gt; and can be build for any architecture supported by python:3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flavors
&lt;/h3&gt;

&lt;p&gt;The cookiecutter container image is available in 2 flavors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;latest&lt;/strong&gt; is build daily via travis and if the base images changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;version&lt;/strong&gt; during each travis build the current cookiecutter version is validated and the image is tagged accordingly starting with &lt;code&gt;1.7.0&lt;/code&gt;. More versions can be found on &lt;a href="https://hub.docker.com/r/ckaserer/cookiecutter"&gt;hub.docker.com/r/ckaserer/cookiecutter&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bash&lt;/li&gt;
&lt;li&gt;docker&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To process any cookiecutter template you can execute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/cookiecutter ckaserer/cookiecutter TEMPLATE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or if you like the a more convinient approach you can put following lines in your bashrc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# cookiecutter&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;cookiecutter &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"docker run --rm -it -v &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:/cookiecutter ckaserer/cookiecutter"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"+ &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; cookiecutter
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and after sourcing your bashrc again to load the newly added function into our shell via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;you can process your template just like you would when installing cookiecutter on your machine via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cookiecutter TEMPLATE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h3&gt;
  
  
  Source
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cookiecutter.readthedocs.io/en/latest/README.html"&gt;cookiecutter.readthedocs.io/en/latest/README.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ckaserer/cookiecutter"&gt;github.com/ckaserer/cookiecutter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/ckaserer/cookiecutter"&gt;hub.docker.com/r/ckaserer/cookiecutter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>cookiecutter</category>
      <category>python</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
