 {"id":519721,"date":"2025-11-26T21:01:17","date_gmt":"2025-11-27T04:01:17","guid":{"rendered":"https:\/\/jorgep.com\/blog\/?p=519721"},"modified":"2026-01-11T21:07:37","modified_gmt":"2026-01-12T04:07:37","slug":"moving-to-github-container-registry-ghcr","status":"publish","type":"post","link":"https:\/\/jorgep.com\/blog\/moving-to-github-container-registry-ghcr\/","title":{"rendered":"Moving to GitHub Container Registry (GHCR)"},"content":{"rendered":"<style>.wp-block-kadence-advancedheading.kt-adv-heading519190_4a1b6f-84, .wp-block-kadence-advancedheading.kt-adv-heading519190_4a1b6f-84[data-kb-block=\"kb-adv-heading519190_4a1b6f-84\"]{font-size:var(--global-kb-font-size-sm, 0.9rem);font-style:normal;}.wp-block-kadence-advancedheading.kt-adv-heading519190_4a1b6f-84 mark.kt-highlight, .wp-block-kadence-advancedheading.kt-adv-heading519190_4a1b6f-84[data-kb-block=\"kb-adv-heading519190_4a1b6f-84\"] mark.kt-highlight{font-style:normal;color:#f76a0c;-webkit-box-decoration-break:clone;box-decoration-break:clone;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.wp-block-kadence-advancedheading.kt-adv-heading519190_4a1b6f-84 img.kb-inline-image, .wp-block-kadence-advancedheading.kt-adv-heading519190_4a1b6f-84[data-kb-block=\"kb-adv-heading519190_4a1b6f-84\"] img.kb-inline-image{width:150px;vertical-align:baseline;}<\/style>\n<p class=\"kt-adv-heading519190_4a1b6f-84 wp-block-kadence-advancedheading\" data-kb-block=\"kb-adv-heading519190_4a1b6f-84\">AI Disclaimer I love exploring new technology, and that includes using AI to help with research and editing! My digital &#8220;team&#8221; includes tools like Google Gemini, Notebook LM, Microsoft Copilot, Perplexity.ai, Claude.ai, and others as needed. They help me gather insights and polish content\u2014so you get the best, most up-to-date information possible.<\/p>\n\n\n\n<p>If you&#8217;re a developer working with containers, chances are Docker Hub has been your go-to for years. It&#8217;s the default, the familiar, and for many, the &#8220;it just works&#8221; solution for storing and distributing Docker images. But if you&#8217;re like me, and vibe coding, Coding Assistants has moved to doing and deploying so many of those apps you always wanted to help you with, using the free tier for personal projects or small teams, you&#8217;ve probably started bumping into some frustrating limitations.   <\/p>\n\n\n\n<p>That&#8217;s why I&#8217;m making the switch, and I believe many of you should too: <strong>I&#8217;m moving my personal projects Docker images from Docker Hub to the GitHub Container Registry (GHCR).<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Docker Hub Free Tier Dilemma: Why I&#8217;m Making the Jump<\/h3>\n\n\n\n<p>Let&#8217;s be honest: Docker Hub&#8217;s free tier has become quite restrictive for active developers.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>The One Private Repository Trap:<\/strong> For solo developers or small teams, having only <em>one<\/em> private repository is a significant bottleneck. What if you have multiple microservices, internal tools, or client projects that need private image storage? You&#8217;re forced to make everything public (a bad idea for proprietary code) or upgrade to a paid plan.<\/li>\n\n\n\n<li><strong>Pull Rate Limits:<\/strong> This is the big one that hit me hard. With 200 pulls per 6 hours, your CI\/CD pipelines, development environments, and even local testing can quickly grind to a halt. Imagine your CI pipeline failing because it can&#8217;t pull a base image, or your local <code>docker-compose up<\/code> command gets throttled during a busy day. It&#8217;s a productivity killer.<\/li>\n<\/ol>\n\n\n\n<p>These limitations aren&#8217;t just minor inconveniences; they directly impact workflow efficiency and force difficult choices for managing private images.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enter GHCR: The Modern, Developer-Friendly Alternative<\/h3>\n\n\n\n<p>GitHub Container Registry (GHCR) isn&#8217;t just another registry; it&#8217;s a seamless extension of the GitHub ecosystem many of us already live in. Launched in <strong>public beta on September 1, 2020, and reaching General Availability in mid-2021<\/strong>, GHCR was designed to address the shortcomings of traditional registries and integrate deeply with developer workflows.<\/p>\n\n\n\n<p>Here&#8217;s why GHCR is a game-changer:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">1. Unlimited Private Repositories (Yes, Really!)<\/h4>\n\n\n\n<p>This is perhaps the biggest draw for free-tier users. GHCR offers <strong>unlimited private repositories<\/strong> for your container images. Whether you have two projects or twenty, you can keep all your images private without hitting a paywall. This alone makes it superior to Docker Hub&#8217;s free offering.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">2. Generous (and Often Non-Existent) Pull Limits<\/h4>\n\n\n\n<p>Say goodbye to &#8220;Error: You have reached your pull rate limit!&#8221; GHCR is far more lenient with pull requests. For public images, pulls are essentially unlimited. For private images, while there are theoretical limits, they are significantly higher than Docker Hub&#8217;s and typically won&#8217;t impact average usage. Crucially, <strong>pulls made by GitHub Actions within GitHub are completely free and unlimited<\/strong>, making it perfect for CI\/CD.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">3. Granular Permissions &amp; Integration<\/h4>\n\n\n\n<p>GHCR offers superior control over who can access your images.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Repository-Scoped Permissions:<\/strong> By default, an image pushed to <code>ghcr.io\/your-username\/your-repo<\/code> will have the same permissions as <code>your-repo<\/code>. This means if someone has access to your code, they also have access to the associated image.<\/li>\n\n\n\n<li><strong>Decoupled Permissions:<\/strong> You can also host images independently of a specific repository and manage their access permissions separately, giving you more flexibility.<\/li>\n\n\n\n<li><strong>GitHub Actions Integration:<\/strong> This is where GHCR truly shines. You can use the built-in <code>GITHUB_TOKEN<\/code> to authenticate your workflows, making it incredibly simple to build and push images without managing extra secrets.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">4. Excellent Performance &amp; Stability<\/h4>\n\n\n\n<p>GHCR was built to handle modern container workloads. It&#8217;s fast, reliable, and backed by GitHub&#8217;s robust infrastructure. Having been generally available since 2021, it&#8217;s a mature and trusted platform used by countless projects, including major open-source initiatives.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">5. Free Tier That Actually Works<\/h4>\n\n\n\n<p>While there are some limits, they are very generous:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Public Images:<\/strong> Completely free storage and data transfer.<\/li>\n\n\n\n<li><strong>Private Images:<\/strong> You get <strong>500MB of free storage<\/strong> and <strong>1GB of free outgoing data transfer per month<\/strong>. For most personal projects, this is more than sufficient.<\/li>\n\n\n\n<li><strong>The GitHub Actions Advantage:<\/strong> As mentioned, data transfer <em>within<\/em> GitHub Actions is unlimited and free, meaning your CI\/CD pipelines won&#8217;t eat into your quota.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Making the Switch: A Quick How-To<\/h3>\n\n\n\n<p>Ready to move? Here&#8217;s the basic workflow:<\/p>\n\n\n\n<p>Step 1: Create a Personal Access Token (PAT)<\/p>\n\n\n\n<p>Go to your GitHub Settings &gt; Developer Settings &gt; Personal Access Tokens (Classic). Generate a new token with the write:packages and read:packages scopes. Keep this token secure!<\/p>\n\n\n\n<p><strong>Step 2: Log In to GHCR via Docker CLI<\/strong><\/p>\n\n\n\n<p>Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"YOUR_PAT_TOKEN\" | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin\n<\/code><\/pre>\n\n\n\n<p>Step 3: Tag Your Image for GHCR<\/p>\n\n\n\n<p>Replace my-node-app with your image name and your-username with your GitHub username.<\/p>\n\n\n\n<p>Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker tag my-local-image:latest ghcr.io\/your-username\/my-node-app:latest\n<\/code><\/pre>\n\n\n\n<p><strong>Step 4: Push Your Image<\/strong><\/p>\n\n\n\n<p>Bash<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker push ghcr.io\/your-username\/my-node-app:latest\n<\/code><\/pre>\n\n\n\n<p>That&#8217;s it! Your image is now safely stored on GHCR. You can then update your deployment manifests (e.g., Kubernetes, Docker Compose) to pull from <code>ghcr.io\/your-username\/my-node-app:latest<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Future of My Containers<\/h3>\n\n\n\n<p>Moving to GHCR resolves the core pain points I experienced with Docker Hub&#8217;s free tier. The ability to host unlimited private repositories, the freedom from restrictive pull limits, and the seamless integration with GitHub Actions make it an undeniable upgrade for my workflow.<\/p>\n\n\n\n<p>If you&#8217;re feeling constrained by Docker Hub, I highly recommend exploring GHCR. It&#8217;s a robust, feature-rich, and developer-centric registry that will likely become your new go-to.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div style=\"font-family: Verdana, Geneva, sans-serif; font-size: 11px;\"><b>Disclaimer<\/b>: \u00a0I work for <a href=\"https:\/\/www.dell.com\/en-us\/work\/learn\/by-service-type-deployment\">Dell Technology Services<\/a> as a Workforce Transformation Solutions Principal.\u00a0 \u00a0 It is my passion to help guide organizations\u00a0through the current technology transition specifically as it relates to <a href=\"https:\/\/www.delltechnologies.com\/en-us\/what-we-do\/workforce-transformation.htm\">Workforce Transformation<\/a>.\u00a0 Visit <a href=\"https:\/\/www.delltechnologies.com\/en-us\/index.htm\">Dell Technologies<\/a>\u00a0site for more information.\u00a0 Opinions are my own and not the views of my employer.<\/div>\n<div><\/div><br>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;re a developer working with containers, chances are Docker Hub has been your go-to for years. It&#8217;s the default, the familiar, and for many, the &#8220;it just works&#8221; solution for storing and distributing Docker images. But if you&#8217;re like me, and vibe coding, Coding Assistants has moved to doing and deploying so many of&#8230;<\/p>\n","protected":false},"author":2,"featured_media":519237,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","episode_type":"","audio_file":"","podmotor_file_id":"","podmotor_episode_id":"","cover_image":"","cover_image_id":"","duration":"","filesize":"","filesize_raw":"","date_recorded":"","explicit":"","block":"","itunes_episode_number":"","itunes_title":"","itunes_season_number":"","itunes_episode_type":"","_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[441,446],"tags":[510,919,989,1013],"class_list":["post-519721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech-talk","category-tips-tools-resources","tag-coding","tag-docker","tag-vibe-coding","tag-zero-vps-strategy"],"taxonomy_info":{"category":[{"value":441,"label":"Tech Talk"},{"value":446,"label":"Tips, Tools &amp; Resources"}],"post_tag":[{"value":510,"label":"coding"},{"value":919,"label":"Docker"},{"value":989,"label":"Vibe Coding"},{"value":1013,"label":"Zero VPS Strategy"}]},"featured_image_src_large":["https:\/\/jorgep.com\/blog\/wp-content\/uploads\/Featured-Helpful-Hints-Series.png",930,330,false],"author_info":{"display_name":"Jorge Pereira","author_link":"https:\/\/jorgep.com\/blog\/author\/jorge\/"},"comment_info":0,"category_info":[{"term_id":441,"name":"Tech Talk","slug":"tech-talk","term_group":0,"term_taxonomy_id":451,"taxonomy":"category","description":"","parent":0,"count":668,"filter":"raw","cat_ID":441,"category_count":668,"category_description":"","cat_name":"Tech Talk","category_nicename":"tech-talk","category_parent":0},{"term_id":446,"name":"Tips, Tools &amp; Resources","slug":"tips-tools-resources","term_group":0,"term_taxonomy_id":456,"taxonomy":"category","description":"","parent":0,"count":79,"filter":"raw","cat_ID":446,"category_count":79,"category_description":"","cat_name":"Tips, Tools &amp; Resources","category_nicename":"tips-tools-resources","category_parent":0}],"tag_info":[{"term_id":510,"name":"coding","slug":"coding","term_group":0,"term_taxonomy_id":520,"taxonomy":"post_tag","description":"","parent":0,"count":3,"filter":"raw"},{"term_id":919,"name":"Docker","slug":"docker","term_group":0,"term_taxonomy_id":929,"taxonomy":"post_tag","description":"","parent":0,"count":9,"filter":"raw"},{"term_id":989,"name":"Vibe Coding","slug":"vibe-coding","term_group":0,"term_taxonomy_id":999,"taxonomy":"post_tag","description":"","parent":0,"count":13,"filter":"raw"},{"term_id":1013,"name":"Zero VPS Strategy","slug":"zero-vps-strategy","term_group":0,"term_taxonomy_id":1023,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"}],"_links":{"self":[{"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/posts\/519721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/comments?post=519721"}],"version-history":[{"count":2,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/posts\/519721\/revisions"}],"predecessor-version":[{"id":519723,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/posts\/519721\/revisions\/519723"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/media\/519237"}],"wp:attachment":[{"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/media?parent=519721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/categories?post=519721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgep.com\/blog\/wp-json\/wp\/v2\/tags?post=519721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}