<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Containers on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/containers/</link><description>Recent content in Containers on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 04 Nov 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/containers/index.xml" rel="self" type="application/rss+xml"/><item><title>Using the GitHub Container Registry</title><link>https://blog.iankulin.com/using-the-github-container-registry/</link><pubDate>Mon, 04 Nov 2024 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/using-the-github-container-registry/</guid><description>&lt;p&gt;As the number of little projects I&amp;rsquo;m running on VPSs grows, I need to have a regimented system for managing all that. I could be using something like &lt;a href="https://coolify.io/"&gt;Coolify&lt;/a&gt;, but, at least for the moment, I&amp;rsquo;d rather build my own system.&lt;/p&gt;
&lt;p&gt;Currently my system is Nginx Proxy Manager (dockerised) in front of each app. If it&amp;rsquo;s a static website, that&amp;rsquo;s another dockerised Nginx, started with a compose file and with &lt;code&gt;www&lt;/code&gt; and &lt;code&gt;conf&lt;/code&gt; sub-directories that I&amp;rsquo;ve &lt;code&gt;git pull&lt;/code&gt;ed from the project. It&amp;rsquo;s not pretty.&lt;/p&gt;
&lt;p&gt;It occurs to me that I could just be bundling each static website &lt;em&gt;inside&lt;/em&gt; a Docker image, then the only content for each website on the VPS would be a compose file. This has the extra appeal that eventually I could use GitHub CI/CD to rebuild the container so changing a website would be pushing my edits to main, then &lt;code&gt;compose down&lt;/code&gt;, &lt;code&gt;pull&lt;/code&gt;, and &lt;code&gt;up&lt;/code&gt; on the VPS.&lt;/p&gt;
&lt;p&gt;Currently I&amp;rsquo;ve only been using DockerHub for my containers, but the free plan only allows for a single private image, whereas on GitHub the free plan doesn&amp;rsquo;t have a number of packages limit - rather it has a total storage (500MB) and monthly transfers (1GB) &lt;a href="https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-packages/about-billing-for-github-packages"&gt;limits&lt;/a&gt;. Along with the aforementioned integration with GitHub CI/CD, this makes it the obvious place to store these images until my scale is large enough to set up my own registry (which I would probably do with &lt;a href="https://forgejo.org/"&gt;Forgejo&lt;/a&gt; on a VPS since the limits of running that inside my Tailscale network is starting to be a friction point anyway).&lt;/p&gt;
&lt;p&gt;Long story short - I want to start using the GitHub container registry, and this post steps through that.&lt;/p&gt;
&lt;h2 id="access-tokens"&gt;Access Tokens&lt;/h2&gt;
&lt;p&gt;If you set up your Docker Hub a while ago, you&amp;rsquo;ve probably forgotten that early on, you had to log into it from the command line with the &lt;code&gt;docker login&lt;/code&gt; command. With Docker Hub, that&amp;rsquo;s your usual username/password combo, but GitHub has a more fine-grained system of permissions, where you generate &amp;lsquo;Personal Access Tokens&amp;rsquo;. This is quite cool, for example you can generate a token with add/update/delete access for your main development laptop, but then generate a different token that only has read access to use on the server where you need to deploy the image.&lt;/p&gt;
&lt;p&gt;The Personal Access Token (PAT) is just used in place of a password when you log in. As well as the benefit of being able to control the permissions for each PAT when you create it, you also name them. This would be helpful for example if your software lead had their laptop stolen, and you needed to revoke the PAT for that device. It&amp;rsquo;s also possible to set expiry dates for the PATs.&lt;/p&gt;
&lt;p&gt;Generating the PATs is done in:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GitHub | Profile | Settings | Developer Settings (left column, bottom) | Personal Access Tokens | Tokens Classic | Generate Access Token Classic&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you have MFA set up (you should) it will ask for that. Then give it a &amp;lsquo;Note&amp;rsquo; and the permissions you want for &amp;ldquo;Packages&amp;rdquo; - Container images are stored in the &amp;ldquo;Packages&amp;rdquo; section of GitHub (where it&amp;rsquo;s also possible to store other artifacts such as your private NPM packages). In the example below we&amp;rsquo;ve asked for Read/Write/Delete access.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-11.49.54-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-11.49.54-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once that&amp;rsquo;s completed, you&amp;rsquo;ll be shown a list of your existing PATs, plus the new one you&amp;rsquo;ve just generated. This is the only time it will ever be displayed in GitHub, so you need to copy it out to where you need it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-11.50.11-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-11.50.11-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="logging-in"&gt;Logging in&lt;/h2&gt;
&lt;p&gt;Before we can push an image to the GitHub Container Registry (ghcr.io) we&amp;rsquo;ll need to use this PAT to log in. I&amp;rsquo;m using the command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker login --username &amp;lt;github username&amp;gt; --password &amp;lt;PAT we just generated&amp;gt; ghcr.io
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ghcr.io&lt;/code&gt; is just the URI for the container registry. It will complain about you pasting the PAT in the command line like that - I guess it&amp;rsquo;s in your bash history now. I&amp;rsquo;ll leave you to google how to do that more securely.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-12.02.37-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Note that you can be logged into several container registries at once. Logging into the ghcr.io won&amp;rsquo;t mean that you&amp;rsquo;ll need to re-logging to DockerHub later; that will still work fine.&lt;/p&gt;
&lt;h2 id="pushing"&gt;Pushing&lt;/h2&gt;
&lt;p&gt;Once that&amp;rsquo;s done, you can push images just as you are used to with DockerHub, with the exception that you need to specify the container registry as part of your image name. It&amp;rsquo;s possible to do that with &lt;code&gt;hub.docker.com&lt;/code&gt; as well, but Docker privileged themselves to make it a default. To use a different registry (in our case ghcr.io) it needs to be included in the image name, along with your GitHub use name.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker push ghcr.io/&amp;lt;github user name&amp;gt;/&amp;lt;container name&amp;gt;:&amp;lt;tag&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-12.08.50-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;If you head to GitHub, and go into &amp;ldquo;Packages&amp;rdquo; instead of &amp;ldquo;Repositories&amp;rdquo;, your container will be there.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-12.24.10-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-12.24.10-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="pulling"&gt;Pulling&lt;/h2&gt;
&lt;p&gt;Pulling the container is going to be even simpler, log in to the registry with the same command we used above, then just docker pull with the registry in the container name - exactly as suggested in the package page on GitHub above.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker pull ghcr.io/&amp;lt;github user name&amp;gt;/&amp;lt;container name&amp;gt;:&amp;lt;tag&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-12.29.33-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-06-at-12.29.33-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Containers</title><link>https://blog.iankulin.com/containers/</link><pubDate>Sun, 07 May 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/containers/</guid><description>&lt;p&gt;There&amp;rsquo;s a few things that really strike me as significant improvements to life since I was commercially developing 20 years ago:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accessing information - the first time I &lt;em&gt;bought&lt;/em&gt; the development stack to write commercial software against the Windows SDK it came in a huge carton with, I guess, fifteen or so 2&amp;quot; thick books. That was how you looked things up in those days. Fast forward to an internet connected world of websites, stack exchange, Discord and ChatGPT. So much better.&lt;/li&gt;
&lt;li&gt;Open Source - is an actual useful thing that the entire connected world runs on - not just a weird hippy idea. It&amp;rsquo;s almost routine to open source your code now and everyone benefits from that.&lt;/li&gt;
&lt;li&gt;Containers - &amp;ldquo;getting things working&amp;rdquo; used to be a thing. Most times now I want to spin something up to play with it, it just works because all the dependencies are bundled with it, and it doesn&amp;rsquo;t mutate the environment in any way I don&amp;rsquo;t know about. There&amp;rsquo;s no friction to run a giant app, and no hangover for the OS when I nuke it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I love this great explanation from Coderized about containers - I wish I&amp;rsquo;d seen it five months ago.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/J0NuOlA2xDc?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;
</description></item></channel></rss>