<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="feed.xslt.xml"?>
<?ignore comment="Overriding jekyll-feed plugin and using the implementation from href" href="https://raw.githubusercontent.com/jhvanderschee/jekyllcodex/gh-pages/feed.xml"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>ink</title>
    <description>materialization of random thoughts</description>
    <link>https://ink.insertcoin.dev/</link>
    <atom:link href="https://ink.insertcoin.dev/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 18 Sep 2024 12:49:28 +0000</pubDate>
    <lastBuildDate>Wed, 18 Sep 2024 12:49:28 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Mastering the Balance: Leading, Learning, and Growing in Tech Leadership</title>
        <description>&lt;p&gt;High-demand roles that combine deep technical skills with significant management responsibilities often seem like the pinnacle of professional achievement. But if you’re in one of these roles, you know the reality can be far more complex and taxing. The relentless commitment required can quickly become a double-edged sword, threatening your personal growth and satisfaction if left unchecked.&lt;/p&gt;

&lt;p&gt;These roles demand a unique mix of technical expertise and the ability to manage teams, projects, and expectations. While the challenge is exciting, it’s all too easy for your personal learning to take a backseat. Caught up in the whirlwind of daily operations, you might find yourself neglecting your own development, leading to a slow but steady decline in your skills and a sense of personal fulfillment.&lt;/p&gt;

&lt;h2 id=&quot;when-commitment-becomes-a-double-edged-sword&quot;&gt;When Commitment Becomes a Double-Edged Sword&lt;/h2&gt;

&lt;p&gt;One of the trickiest aspects of these roles is their self-organizing nature. You’re expected to deliver without much oversight, and this autonomy can make overcommitment and burnout feel almost invisible. Before you know it, weeks turn into months, and your focus is solely on work deliverables, not on your own growth or learning.&lt;/p&gt;

&lt;p&gt;The pressure to excel in both technical and managerial domains can leave you feeling:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A sense of stagnation and unfulfilled&lt;/li&gt;
  &lt;li&gt;Unsure about your long-term career direction&lt;/li&gt;
  &lt;li&gt;Constantly stressed and on the verge of burnout&lt;/li&gt;
  &lt;li&gt;Disconnected from personal relationships and hobbies&lt;/li&gt;
  &lt;li&gt;Struggling to manage time and constantly switching contexts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;choosing-between-management-and-technical-expertiseor-not&quot;&gt;Choosing Between Management and Technical Expertise—or Not&lt;/h2&gt;

&lt;p&gt;At some point, you might find yourself at a critical decision point: fully commit to a management path or double down on maintaining and expanding your technical expertise. Going all in on management can lead to a rewarding leadership career, with opportunities to shape the direction of teams and projects. However, this often means stepping away from the hands-on technical work that you might still love. On the other hand, doubling down on technical skills can make you a subject matter expert but may limit your climb into leadership roles.&lt;/p&gt;

&lt;p&gt;But here’s the thing: You don’t have to choose one path over the other. For many, it’s about thriving in the balance. Don’t view these roles as a zero-sum game—find ways to straddle both worlds. Maintaining a foot in both realms is not just possible; it’s incredibly fulfilling. The key is recognizing that you can balance these responsibilities and make it work for you.&lt;/p&gt;

&lt;h2 id=&quot;how-to-thrive-in-a-dual-role-practical-strategies&quot;&gt;How to Thrive in a Dual Role: Practical Strategies&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Set Clear Boundaries&lt;/strong&gt;: Establish boundaries between your technical and management responsibilities. Don’t be afraid to say no to tasks that don’t align with your goals, and set firm limits to protect your time for personal growth.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Prioritize Personal Growth&lt;/strong&gt;: Make time for your own learning and development. Whether it’s attending workshops, conferences, or diving into online courses, keep yourself up-to-date.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Delegate to Focus on High-Impact Work&lt;/strong&gt;: Empower your team by delegating tasks, allowing you to focus on strategic activities. Effective delegation not only frees up your time but also helps develop your team’s skills.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Seek Mentorship&lt;/strong&gt;: Find mentors who can guide and support you. Consider finding separate mentors for technical and managerial aspects of your role to get specialized advice in each area. Start with a mentor who excels in one specific skill you want to master, then seek out others as you grow. Mentors can fast-track your learning and keep you committed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Incorporate Reflection into Your Routine&lt;/strong&gt;: Make reflection a habit. Regular practices like journaling, feedback sessions, and self-assessments help you stay aligned with your goals and pinpoint areas that need attention. Engage more with your engennering manager.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Implement Effective Time Management&lt;/strong&gt;: Use time management techniques like the time-blocking or Pomodoro Technique to maintain a balance between technical work, management tasks, and personal growth. Once you’ve scheduled time in your calendar, stick to it—don’t shuffle things around. Keep your focus.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Build a Strong Support Network&lt;/strong&gt;: Connect with peers in similar roles. Schedule lunch with peers it’s optimal way to talk shop and build rapport; Join professional groups or online communities where you can share experiences, challenges, and solutions. A strong support network can provide insights and encouragement when you need it most.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Maintain Work-Life Balance&lt;/strong&gt;: Don’t let the demands of your role overshadow your personal life. Prioritizing work-life balance can actually boost your professional performance by reducing stress and enhancing satisfaction. Keep these tips in mind:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Set firm work hours and stick to them&lt;/li&gt;
      &lt;li&gt;Engage in hobbies and activities outside of work to recharge&lt;/li&gt;
      &lt;li&gt;Prioritize physical health through regular exercise and proper nutrition&lt;/li&gt;
      &lt;li&gt;Cultivate relationships outside of your professional circle&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;stay-on-course-the-power-of-self-reflection&quot;&gt;Stay on Course: The Power of Self-Reflection&lt;/h2&gt;

&lt;p&gt;In these high-demand roles, it’s easy to lose sight of the bigger picture. Regular self-reflection can help you understand what you’ve accomplished and what still needs attention. Here are a few ways to incorporate reflection into your routine:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Weekly Journaling&lt;/strong&gt;: Take time each week to document your accomplishments, challenges, and key learnings. This habit can help you track patterns, identify recurring issues, and celebrate your successes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Monthly Career Check-Ins&lt;/strong&gt;: Dedicate time each month to evaluate your progress toward your long-term goals. Review your career roadmap, assess your skill development, and make adjustments as needed. It may sound like a lot, but remember—you’re only doing this at most 12 times a year.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Quarterly Self-Assessments&lt;/strong&gt;: Conduct a deeper self-assessment every quarter to identify skill gaps, areas for improvement, and opportunities for growth. Seek feedback from colleagues, mentors, or direct reports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These reflective practices help you stay connected to your goals, ensuring you don’t drift away from the path you’ve set for yourself.&lt;/p&gt;

&lt;h2 id=&quot;finding-fulfillment-commit-to-yourself-not-just-the-work&quot;&gt;Finding Fulfillment: Commit to Yourself, Not Just the Work&lt;/h2&gt;

&lt;p&gt;Balancing high-level technical and management responsibilities isn’t just about meeting job demands—it’s about aligning this dual role with your long-term aspirations. But how often do you check in with yourself? Is this balance still what you want?&lt;/p&gt;

&lt;p&gt;If it is, now is the time to commit—not just to your work, but to yourself. Pause, reflect, and reassess how things are going. Have you been prioritizing your own growth, or have you slipped into a routine focused purely on delivery?&lt;/p&gt;

&lt;p&gt;Finding fulfillment in these demanding roles is absolutely possible, but it takes discipline, self-awareness, and, most importantly, a commitment to your own development. Remember, the better you take care of yourself, the better you can deliver in your role. Reflection isn’t just a break from work; it’s an investment in your professional journey. Success doesn’t come only from what you achieve at work, but from the processes and habits that keep you engaged, balanced, and continuously evolving.&lt;/p&gt;

&lt;p&gt;Now that you have this insight, it’s time to act. Take a moment to reflect on what’s been holding you back. Define your goals and set clear, achievable objectives that align with your personal growth. Talk with your engineering manager or direct report to ensure they understand your situation—take the opportunity to set these goals together, and use them as someone who will hold you accountable. If you don’t, you risk staying stuck—unfulfilled and with fewer options, as your technical skills fade over time.&lt;/p&gt;

&lt;p&gt;Investing in yourself is the key to growth. Without it, you may look back and realize you haven’t moved forward, losing the chance to grow in the direction that truly matters.&lt;/p&gt;
</description>
        <pubDate>Thu, 12 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://ink.insertcoin.dev/posts/tech-leadership-mastering-the-balance</link>
        <guid isPermaLink="true">https://ink.insertcoin.dev/posts/tech-leadership-mastering-the-balance</guid>
        
        <category>leadership</category>
        
        <category>management</category>
        
        <category>growth</category>
        
        
        <category>leadership</category>
        
      </item>
    
      <item>
        <title>home.arpa the TLD for home usage</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.home.arp&lt;/code&gt; is the special-use TLD that you should be using inside your private network according to &lt;a href=&quot;https://tools.ietf.org/html/rfc8375&quot;&gt;RFC 8375&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;With my latest homelab rebuild I tried to make my network address more sane, and with that I needed to replace the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.local&lt;/code&gt; TLD that I have been using for the last couple of years with one that had none of the gotchas that I sometimes found myself getting into.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.local&lt;/code&gt; is defined as a special-use TLD (see &lt;a href=&quot;https://tools.ietf.org/html/rfc6761&quot;&gt;RFC 6761&lt;/a&gt;) in the &lt;a href=&quot;https://tools.ietf.org/html/rfc2606&quot;&gt;RFC 2606&lt;/a&gt; suitable to be used for internal network usage but states that was designated to be used with Multicast DNS (mDNS), this means that each device in the network can grab and define its prefered hostname, making me loose control regarding the names that are registered in the network, and in the other side of things, while using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.local&lt;/code&gt; TLD some DNS resolvers would defer the resolution the their mDNS resolver instead of the DNS causing resolution conflits.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc8375&quot;&gt;RFC 8375&lt;/a&gt; solves this by defining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;home.arpa&lt;/code&gt; has the de facto TLD for home usage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This document registers the domain ‘home.arpa.’ as a special-use
   domain name &lt;a href=&quot;https://tools.ietf.org/html/rfc6761&quot;&gt;RFC 6761&lt;/a&gt; and specifies the behavior that is expected
   from the Domain Name System with regard to DNS queries for names
   whose rightmost non-terminal labels are ‘home.arpa.’.  Queries for
   names ending with ‘.home.arpa.’ are of local significance within the
   scope of a homenet, meaning that identical queries will result in
   different results from one homenet to another.  In other words, a
   name ending in ‘.home.arpa.’ is not globally unique.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Long story short, DNS resolutions for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.home.arpa&lt;/code&gt; hosts will not be send to public Internet, hence not leeking any kind of information about your internal network outside, and using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.home.arpa&lt;/code&gt; will also ensure you don’t have issues with possible mDNS resolution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sidenote&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I would suggest not using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.home&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;homenet&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;workgroup&lt;/code&gt; or other “fake” domain name that comes to mind because of two possible issues:
    &lt;ul&gt;
      &lt;li&gt;a) If the DNS query can’t be solved inside your network, the request will be forwared to a root DNS server leeking information of your internal network outside, while also adding a delay penalty for the resolution.&lt;/li&gt;
      &lt;li&gt;b) &lt;a href=&quot;https://newgtlds.icann.org/en/&quot;&gt;ICANN decided to delegate new TLDs&lt;/a&gt; to anyone who was willing to apply and pay the required fees,  this means that in the future anyone can register your internal domain and start using it has a root TLD, see what happend with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.dev&lt;/code&gt; domain that got bought by Google a couple years ago.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;I would suggest avoiding using a public registered domain or subdomain inside your home network, just to keep the overhead low, because this would mean that you need to update the public DNS server each time you had a device to your network (eg: Cloudflare or DynDNS), and this would also be leeking information about your home network.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc6761&quot;&gt;RFC 6761&lt;/a&gt;: Special-Use Domain Names&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc6762&quot;&gt;RFC 6762&lt;/a&gt;: Multicast DNS&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc8375&quot;&gt;RFC 8375&lt;/a&gt;: Special-Use Domain ‘home.arpa.’&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 14 Sep 2021 00:00:00 +0000</pubDate>
        <link>https://ink.insertcoin.dev/posts/home-arpa-tldr-for-home</link>
        <guid isPermaLink="true">https://ink.insertcoin.dev/posts/home-arpa-tldr-for-home</guid>
        
        <category>homelab</category>
        
        <category>networking</category>
        
        <category>tld</category>
        
        
        <category>homelab</category>
        
        <category>networking</category>
        
        <category>tld</category>
        
      </item>
    
      <item>
        <title>Deprecation of Dockershim</title>
        <description>
&lt;p&gt;A couple of days ago I found a news in &lt;a href=&quot;https://news.ycombinator.com/item?id=25279924&quot;&gt;Hacker News&lt;/a&gt; with the title &lt;a href=&quot;https://news.ycombinator.com/item?id=25279924&quot;&gt;Kubernetes is deprecating Docker runtime support&lt;/a&gt; that made me think a bit about the impact of this news, both in terms to Kubernetes and for Docker, since Docker popularized the container technology, could this be the end of Docker?&lt;/p&gt;

&lt;p&gt;Let’s talk a bit about Docker and the container eco-system evolution to understand how we got here.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;understanding-docker&quot;&gt;Understanding Docker&lt;/h2&gt;

&lt;p&gt;Docker is not just a container runtime, it’s a entire platform to build, publish and run containers that as a lot of features built on-top like networking, volume management, etc.&lt;/p&gt;

&lt;p&gt;Looking at Docker from 10.000 feet, you can find two components, &lt;strong&gt;docker&lt;/strong&gt; and &lt;strong&gt;dockerd&lt;/strong&gt;. The &lt;strong&gt;docker&lt;/strong&gt; client (is a CLI tool) allows you to issue commands to &lt;strong&gt;dockerd&lt;/strong&gt; to pull, build or run a image among other things, and the &lt;strong&gt;dockerd&lt;/strong&gt; is the Docker daemon process that receives client requests and performs the requested actions.&lt;/p&gt;

&lt;h3 id=&quot;evolution-of-container-runtimes-oci-and-cri&quot;&gt;Evolution of container runtimes: OCI and CRI&lt;/h3&gt;

&lt;p&gt;Since it’s first release in 2014, docker and the entire container ecosystem have been evolving, and a set of standards emerged from it &lt;a href=&quot;https://www.opencontainers.org&quot;&gt;Open Container Initiative (OCI)&lt;/a&gt; and &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/242a97307b34076d5d8f5bbeb154fa4d97c9ef1d/docs/devel/container-runtime-interface.md&quot;&gt;Container Runtime Interface (CRI)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;a href=&quot;https://www.opencontainers.org&quot;&gt;OCI&lt;/a&gt; docker broke down the monolith and separated their code for low level interaction with the Linux kernel that allowed them to run containers to a library called &lt;a href=&quot;https://github.com/opencontainers/runc/tree/master/libcontainer&quot;&gt;libcontainer&lt;/a&gt; and a tool called &lt;a href=&quot;https://github.com/opencontainers/runc&quot;&gt;runc&lt;/a&gt; that became the reference implementation of the &lt;a href=&quot;https://github.com/opencontainers/runtime-spec&quot;&gt;OCI runtime specification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So in it’s core the &lt;a href=&quot;https://github.com/opencontainers/runtime-spec&quot;&gt;OCI runtime specification&lt;/a&gt; specifies the format of a Docker image, called bundle and how the resources from the Linux kernel (cgroups, namespaces) are allocated and how to run a image. There is no network management, not image pulling specified at this level, just how to run containers.&lt;/p&gt;

&lt;p&gt;So in December 2015 &lt;a href=&quot;https://www.docker.com/blog/docker-engine-1-11-runc/&quot;&gt;Docker Engine 1.11&lt;/a&gt; got released, this was the first version of Docker supporting &lt;a href=&quot;https://github.com/opencontainers/runc&quot;&gt;runc&lt;/a&gt; and &lt;a href=&quot;https://github.com/containerd/containerd&quot;&gt;containerd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/containerd/containerd&quot;&gt;containerd&lt;/a&gt; is a high level container runtime that is available as a daemon and can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.&lt;/p&gt;

&lt;p&gt;Underneath &lt;a href=&quot;https://github.com/containerd/containerd&quot;&gt;containered&lt;/a&gt; calls &lt;a href=&quot;https://github.com/opencontainers/runc&quot;&gt;runc&lt;/a&gt; to create the containers.&lt;/p&gt;

&lt;center&gt;
  &lt;figure&gt;
    &lt;img src=&quot;/assets/images/deprecation-dockershim-docker-engine.png&quot; alt=&quot;python&quot; /&gt;
    &lt;figcaption&gt;Evolution of the Docker engine Monolith&lt;br /&gt;&lt;small&gt;image credit &lt;a href=&quot;https://github.com/darshanime/notes/blob/master/kubernetes.org#notes&quot; target=&quot;_blank&quot;&gt;darshanime/notes&lt;/a&gt;&lt;/small&gt;
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/center&gt;

&lt;p&gt;The release of &lt;a href=&quot;https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes&quot;&gt;Kubernetes 1.5&lt;/a&gt; introduced the &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/242a97307b34076d5d8f5bbeb154fa4d97c9ef1d/docs/devel/container-runtime-interface.md&quot;&gt;Container Runtime Interface (CRI)&lt;/a&gt;, a plugin interface which enables &lt;a href=&quot;https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet&quot;&gt;kubelet&lt;/a&gt; to use a wide variety of container runtimes (&lt;a href=&quot;https://github.com/containerd/containerd&quot;&gt;containered&lt;/a&gt;, &lt;a href=&quot;https://github.com/cri-o/cri-o&quot;&gt;cri-o&lt;/a&gt;, etc), without the need to recompile. &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/242a97307b34076d5d8f5bbeb154fa4d97c9ef1d/docs/devel/container-runtime-interface.md&quot;&gt;CRI&lt;/a&gt; consists of a protocol buffers and &lt;a href=&quot;http://www.grpc.io&quot;&gt;gRPC API&lt;/a&gt;, and libraries, with additional specifications and tools under active development.&lt;/p&gt;

&lt;h2 id=&quot;why-the-deprecation-of-dockershim&quot;&gt;Why the deprecation of Dockershim?&lt;/h2&gt;

&lt;p&gt;Long story short, Docker engine daemon (dockerd) doesn’t support &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/242a97307b34076d5d8f5bbeb154fa4d97c9ef1d/docs/devel/container-runtime-interface.md&quot;&gt;CRI&lt;/a&gt; meaning that in order for Kubernetes to support Docker to run images they need to use a shim and maintain it at their own cost.&lt;/p&gt;

&lt;h3 id=&quot;the-dockershim-flow&quot;&gt;The Dockershim flow&lt;/h3&gt;

&lt;center&gt;
  &lt;figure&gt;
    &lt;img src=&quot;/assets/images/deprecation-dockershim-dockershim.png&quot; alt=&quot;python&quot; /&gt;
    &lt;figcaption&gt;
      Create container flow via dockershim
      &lt;br /&gt;
      &lt;small&gt;
        &lt;a href=&quot;https://blog.csdn.net/u011563903/article/details/90743853&quot;&gt;image&lt;/a&gt; based on &lt;a href=&quot;https://blog.csdn.net/u011563903&quot; target=&quot;_blank&quot;&gt;Frank范 blog&lt;/a&gt;
      &lt;/small&gt;
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/center&gt;

&lt;p&gt;When the kubelet wants to create a container the following steps are required:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Kubelet calls dockershim through the CRI interface (gRPC) to request the creation of the container. The dockershim is embed directly in the kubelet and acts like a CRI server, and receives the creating request.&lt;/li&gt;
  &lt;li&gt;The dockershim gets the kubelet request and translates it to something that the Docker daemon (dockerd) can understand.&lt;/li&gt;
  &lt;li&gt;As we saw in Docker 1.11, the Docker externalized the container creation to containerd, meaning that dockerd then requests containerd to create the container.&lt;/li&gt;
  &lt;li&gt;One containerd gets the request, it created a process called containerd-shim to let containerd-shim operate the container. This happens because the container process needs a parent process to attach to in order to collect stats, state, etc; and if the containerd process is the parent, if containerd hands or gets upgraded all child container processes on the host will have to exit; containerd and shim are not parent-child processes.&lt;/li&gt;
  &lt;li&gt;The containerd-shim just calls runc a command line tool that handles all the low level container operations and implements the OCI interface standard.&lt;/li&gt;
  &lt;li&gt;After runc starts the container, it will exit directly and the containerd-shim will become the container parent process, responsible for collecting the status of the container process, reporting it to containerd and taking over the of the child process of the container after the process with pid 1 in the container exists, cleaning up and ensuring that there are no zombie processes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;the-containerd-via-cri-plugin&quot;&gt;The containerd via cri-plugin&lt;/h3&gt;

&lt;center&gt;
  &lt;figure&gt;
    &lt;img src=&quot;/assets/images/deprecation-dockershim-containerd-cri-plugin.png&quot; alt=&quot;containerd cri plugin&quot; /&gt;
    &lt;figcaption&gt;
      Create container flow via containerd and cri
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/center&gt;

&lt;p&gt;When we look at the kubelet flow when using containerd 1.1+ we can see that the list of dependencies and complexity gets reduced:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The kubelet calls containerd directly via the CRI interface (gRPC) to request the creation of the container.&lt;/li&gt;
  &lt;li&gt;Before containerd 1.1 there was cri-containerd daemon process that implemented the CRI interface received the requests from the kubelet and forward them containerd. Now containerd implements directly the CRI plugin interface receiving the requests directly, it created a process called containerd-shim to let containerd-shim operate the container. This happens because the container process needs a parent process to attach to in order to collect stats, state, etc; and if the containerd process is the parent, if containerd hands or gets upgraded all child container processes on the host will have to exit; containerd and shim are not parent-child processes.&lt;/li&gt;
  &lt;li&gt;The containerd-shim just calls runc a command line tool that handles all the low level container operations and implements the OCI interface standard.&lt;/li&gt;
  &lt;li&gt;After runc starts the container, it will exit directly and the containerd-shim will become the container parent process, responsible for collecting the status of the container process, reporting it to containerd and taking over the of the child process of the container after the process with pid 1 in the container exists, cleaning up and ensuring that there are no zombie processes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see maintaining the dockershim brings a lot of pain to the Kubenetes team, they need to manage another component just to keep supporting Docker (tracking deprecations, api changes, etc) and at the end of the day Docker is not special and it should expose a CRI interface just like other container runtimes (&lt;a href=&quot;https://github.com/containerd/containerd&quot;&gt;containerd&lt;/a&gt;, &lt;a href=&quot;https://github.com/cri-o/cri-o&quot;&gt;cri-o&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So in order to continue using Docker for Kubernetes deployments in the future, the Docker client or daemon will need to become CRI compliant meanwhile everyone should start planning to transition to a CRI compatible runtime like containerd for example.&lt;/p&gt;

&lt;p&gt;Some managed Kubernetes services like &lt;a href=&quot;https://github.com/Azure/AKS/releases/tag/2020-11-16&quot;&gt;AKS&lt;/a&gt; or &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd&quot;&gt;GKE&lt;/a&gt; already are supporting CRI runtimes others like &lt;a href=&quot;https://github.com/aws/containers-roadmap/issues/313&quot;&gt;EKS&lt;/a&gt; are still working supporting it.&lt;/p&gt;

&lt;p&gt;Don’t forget to check if the container tools that you are using also support CRI runtimes and don’t just expect to find Docker.&lt;/p&gt;

&lt;p&gt;In a last note this doesn’t mean that you for local development should stop using Docker, right now the docker platform in my understanding still gives to developers the best user experience and a huge step to tools that simply make our life easier (eg: docker-compose).&lt;/p&gt;

&lt;p&gt;Here are some articles that try to explain a bit more in detail the reasons under the what will this entail for Kubernetes and it’s users:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/&quot;&gt;Don’t Panic: Kubernetes and Docker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/1985-remove-dockershim&quot;&gt;KEP-1985: Removing dockershim from kubelet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/assets/images/deprecation-dockershim.drawio&quot;&gt;Draw.io diagram used for this article&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.csdn.net/u011563903/article/details/90743853&quot;&gt;K8S Runtime CRI OCI contained dockershim understanding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 04 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://ink.insertcoin.dev/posts/dockershim-deprecation</link>
        <guid isPermaLink="true">https://ink.insertcoin.dev/posts/dockershim-deprecation</guid>
        
        <category>docker</category>
        
        <category>kubernetes</category>
        
        
        <category>kubernetes</category>
        
      </item>
    
      <item>
        <title>asdf a runtime manager to rule them all</title>
        <description>
&lt;p&gt;Currently I’m running multiple versions of multiple runtimes on my machine, eg: OpenJDK 8, 14 then ruby 2.7.0 and NodeJS versions 8 and 12.&lt;/p&gt;

&lt;p&gt;Normally for each one of them I would use a specific runtime version manager, for example for Java I would use &lt;a href=&quot;https://sdkman.io/&quot;&gt;sdkman&lt;/a&gt;, for ruby a couple years ago I replaced &lt;a href=&quot;https://rvm.io/&quot;&gt;rvm&lt;/a&gt; with &lt;a href=&quot;https://github.com/rbenv/rbenv&quot;&gt;rbenv&lt;/a&gt; and for NodeJS I simply went with &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main pain of using 3 runtime managers is the need to learn their different CLIs and nuances; With &lt;a href=&quot;https://rvm.io/&quot;&gt;rvm&lt;/a&gt; and &lt;a href=&quot;https://github.com/rbenv/rbenv&quot;&gt;rbenv&lt;/a&gt; you can choose a version of ruby per project by placing in the root of the folder a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ruby-version&lt;/code&gt; file stating the version to use, &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt; also allowed this using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.nvmrc&lt;/code&gt; and so on, but now this is water under the bridge.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;installing-asdf-vm&quot;&gt;Installing asdf-vm&lt;/h2&gt;

&lt;p&gt;Simply clone the &lt;strong&gt;asdf&lt;/strong&gt; repository to your home has shown bellow&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Clone the latest branch&lt;/span&gt;
git clone https://github.com/asdf-vm/asdf.git ~/.asdf
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/.asdf
git checkout &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git describe &lt;span class=&quot;nt&quot;&gt;--abbrev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 &lt;span class=&quot;nt&quot;&gt;--tags&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;shell-integration&quot;&gt;Shell integration&lt;/h3&gt;

&lt;p&gt;On a MacOS or *nix using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt; edit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.asdf/asdf.sh
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.asdf/completions/asdf.bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you are using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zshell&lt;/code&gt; edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt; and add the following to the end of the file&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# append completions to fpath&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;fpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ASDF_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/completions &lt;span class=&quot;nv&quot;&gt;$fpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# initialise completions with ZSH&apos;s compinit&lt;/span&gt;
autoload &lt;span class=&quot;nt&quot;&gt;-Uz&lt;/span&gt; compinit
compinit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;update&quot;&gt;Update&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;plugins&quot;&gt;Plugins&lt;/h2&gt;

&lt;p&gt;Plugins are how adsf understands how to handle different packages, meaning that if you wish to add to adsf the ability to handle java, python, mysql or even minikube you just need to install a plugin.&lt;/p&gt;

&lt;p&gt;See the following page to view &lt;a href=&quot;https://github.com/asdf-vm/asdf-plugins&quot;&gt;all available plugins&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;add&quot;&gt;Add&lt;/h3&gt;

&lt;p&gt;If the plugin exists in the &lt;a href=&quot;https://github.com/asdf-vm/asdf-plugins&quot;&gt;plugin repository&lt;/a&gt; you can just add it by name, otherwise you need to add it providing it’s git repository url.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# asdf plugin add &amp;lt;name&amp;gt;
asdf plugin add java

# asdf plugin add &amp;lt;name&amp;gt; &amp;lt;git url&amp;gt;
asdf plugin-add kotlin https://github.com/asdf-community/asdf-kotlin.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;list-installed&quot;&gt;List installed&lt;/h1&gt;

&lt;p&gt;Listing installed plugins&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf plugin list
# java
# maven
# nodejs
# python
# rust
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Listing installed plugins with their repository url’s&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf plugin list --urls
# java    https://github.com/halcyon/asdf-java.git
# maven   https://github.com/halcyon/asdf-maven.git
# nodejs  https://github.com/asdf-vm/asdf-nodejs.git
# python  https://github.com/danhper/asdf-python.git
# rust    https://github.com/code-lever/asdf-rust.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;updating-installed&quot;&gt;Updating installed&lt;/h3&gt;

&lt;p&gt;You can update a specific plugin by name&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf plugin update java
# Updating java...
# remote: Enumerating objects: 108, done.
# remote: Counting objects: 100% (108/108), done.
# remote: Compressing objects: 100% (64/64), done.
# remote: Total 289 (delta 67), reused 82 (delta 44), pack-reused 181
# Receiving objects: 100% (289/289), 192.46 KiB | 1.17 MiB/s, done.
# Resolving deltas: 100% (161/161), completed with 5 local objects.
# From https://github.com/halcyon/asdf-java
#   b050643..eedd04e  master     -&amp;gt; master
#   b050643..eedd04e  master     -&amp;gt; origin/master
# Already on &apos;master&apos;
# Your branch is up to date with &apos;origin/master&apos;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or update all plugins in one go&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf plugin update --all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;remove&quot;&gt;Remove&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# asdf plugin remove &amp;lt;name&amp;gt;
asdf plugin remove kotlin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;versions&quot;&gt;Versions&lt;/h2&gt;

&lt;h3 id=&quot;list-all-available-versions&quot;&gt;List all available versions&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf list all &amp;lt;name&amp;gt;
# asdf list all java
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;install&quot;&gt;Install&lt;/h3&gt;

&lt;p&gt;Installing a version is as simple as installing a plugin.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf install &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;
# asdf install java adopt-openjdk-11.0.6+10_openj9-0.18.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install the lasted version of a stable version&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf install &amp;lt;name&amp;gt; latest:&amp;lt;version&amp;gt;
asdf install java latest:11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;list-installed-versions&quot;&gt;List installed versions&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf list &amp;lt;name&amp;gt;
# asdf list java
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Filtering displayed versions&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf list all &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;
# asdf list all java openjdk-11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;set-current-version&quot;&gt;Set current version&lt;/h3&gt;

&lt;p&gt;You can set a specific plugin version globally, just in the current shell or per folder.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf global &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;
asdf shell &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;
asdf local &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;scope&lt;/th&gt;
      &lt;th&gt;description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;global&lt;/td&gt;
      &lt;td&gt;writes the version to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.tools_versions&lt;/code&gt;, making the version global all shells&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;shell&lt;/td&gt;
      &lt;td&gt;sets the version just for this shell, but setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_${LANG}_VERSION&lt;/code&gt; environment variable&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;local&lt;/td&gt;
      &lt;td&gt;writes the version to the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tools_versions&lt;/code&gt; on the current working directory&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;You can read more about the &lt;a href=&quot;https://asdf-vm.com/#/core-configuration&quot;&gt;.tool-versions&lt;/a&gt; file &lt;a href=&quot;https://asdf-vm.com/#/core-configuration&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;view-current-version&quot;&gt;View current version&lt;/h3&gt;

&lt;p&gt;To view whats the current version of the installed plugins&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf current
# java           adopt-openjdk-11.0.6+10_openj9-0.18.1 (set by /Users/lmm/.tool-versions)
# maven          3.5.4    (set by /Users/lmm/.tool-versions)
# nodejs         8.17.0 12.18.2 (set by /lmm/mendelui/.tool-versions)
# python         3.8.4    (set by /Users/lmm/.tool-versions)
# rust           1.45.0   (set by /Users/lmm/.tool-versions)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also view the version of a specific version&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf current java
# adopt-openjdk-11.0.6+10_openj9-0.18.1 (set by /Users/mendelui/.tool-versions)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;uninstall&quot;&gt;Uninstall&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# asdf uninstall &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;

asdf uninstall rust 1.45.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 30 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://ink.insertcoin.dev/posts/asdf-a-runtime-to-rule-them-all</link>
        <guid isPermaLink="true">https://ink.insertcoin.dev/posts/asdf-a-runtime-to-rule-them-all</guid>
        
        
        <category>version manager</category>
        
        <category>runtime manager</category>
        
        <category>asdf</category>
        
      </item>
    
      <item>
        <title>HTML5 video, ogv, firefox and nginx</title>
        <description>&lt;p&gt;If you are having problems serving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ogv&lt;/code&gt; video content on Firefox there are some steps that you should follow.&lt;/p&gt;

&lt;h2 id=&quot;serving-ogg-files-with-the-correct-mime-type&quot;&gt;Serving ogg files with the correct MIME type&lt;/h2&gt;

&lt;p&gt;First you have to ensure that you are serving the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mime type&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ogv&lt;/code&gt; files, it should be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;video/ogg&lt;/code&gt; you can test it using &lt;a href=&quot;http://web-sniffer.net/&quot;&gt;web sniffer&lt;/a&gt; (see the return value in the &lt;strong&gt;Content-Type:&lt;/strong&gt; tag, you should see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;video/ogg&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;If not try adding the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mime types&lt;/code&gt; to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt; (eg: /etc/nginx/mime.types`) and restart it.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;video/ogg   ogm&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
video/ogg   ogv&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
video/ogg   ogg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;handle-http-11-byte-range-requests-and-serving-x-content-duration-headers&quot;&gt;Handle HTTP 1.1 byte range requests and serving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Content-Duration&lt;/code&gt; headers&lt;/h2&gt;

&lt;p&gt;Firefox or better yet the Gecko engine that powers Firefox / Thunderbird / SeaMonkey and others uses a sequence of HTTP 1.1 byte-range requests to retrieve the media from the seek target position in order to determine the duration of the media, it does this because ogv files don&apos;t contain the duration of the animation, so in order to determinate the duration of the file it retrieves a 8k chuck in the beginning of the file to determinate if the file is a valid ogg file, than based on the &lt;i&gt;Content-Length&lt;/i&gt; header sent from the server it asks for the last chuck as you can see here, and finally it resumes the download from the first chuck as you can see in this image.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;print screen partial content&quot; src=&quot;/assets/images/firefox_partial_content_ogv.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In order to reduce the amount of requests made to your web server you can send the &lt;code&gt;X-Content-Duration&lt;/code&gt; header with the duration in seconds of the media. If your video has a duration of 1 minute and 32.6 seconds you should server the value as 92.6&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Content-Duration: 92.6&lt;/code&gt; Here is example how you can serve a media file using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location /media/video.ogv &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  add_header X-Content-Duration &lt;span class=&quot;s2&quot;&gt;&quot;92.6&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you&apos;re curious to see in greater detail why Gecko makes some of the HTTP requests it does, read &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=502894#c1&quot; target=&quot;_blank&quot;&gt;comment 1 of bug 502894&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;consider-using-preload-attribute&quot;&gt;Consider using &lt;code&gt;preload&lt;/code&gt; attribute&lt;/h2&gt;

&lt;p&gt;The HTML5 &lt;code&gt;video&lt;/code&gt; and &lt;code&gt;audio&lt;/code&gt; tags provide the &lt;code&gt;preload&lt;/code&gt; attribute which tell Gecko to attempt to download the entire media when the page loads. Without the &lt;code&gt;preload&lt;/code&gt; attribute Gecko only downloads enough of the media to display the first video frame and determinate the media&apos;s duration.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preload&lt;/code&gt; if &lt;i&gt;off&lt;/i&gt; by default so to enable just add the attribute to the video tag and set it&apos;s value to &lt;i&gt;auto&lt;/i&gt;.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;video&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;preload=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;source&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;media/video.ogv&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;video/ogg&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 25 Nov 2012 16:50:10 +0000</pubDate>
        <link>https://ink.insertcoin.dev/posts/html5-video-ogv-firefox-and-nginx</link>
        <guid isPermaLink="true">https://ink.insertcoin.dev/posts/html5-video-ogv-firefox-and-nginx</guid>
        
        <category>nginx</category>
        
        <category>html video</category>
        
        <category>ogv</category>
        
        
        <category>nginx</category>
        
        <category>html video</category>
        
        <category>ogv</category>
        
      </item>
    
  </channel>
</rss>
