{"id":209659,"date":"2021-03-24T15:00:11","date_gmt":"2021-03-24T12:00:11","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/"},"modified":"2024-09-27T08:55:09","modified_gmt":"2024-09-27T05:55:09","slug":"how-to-create-your-own-private-docker-registry-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/","title":{"rendered":"#How to Create Your Own Private Docker Registry"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a2fd9ff2cc44\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a2fd9ff2cc44\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/#Running_a_Registry\" >Running a Registry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/#Accessing_Your_Registry\" >Accessing Your Registry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/#Setting_up_Authentication\" >Setting up Authentication<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/#Setting_Up_SSL\" >Setting Up SSL<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/#SSL_via_LetsEncrypt\" >SSL via LetsEncrypt<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-your-own-private-docker-registry-cloudsavvy-it\/#Other_Ways_to_Deploy\" >Other Ways to Deploy<\/a><\/li><\/ul><\/nav><\/div>\n<p><span style=\"font-size: revert; color: initial;\">Running your own Docker registry gives you a private place to store your Docker images. Whether you\u2019re in a corporate environment or just want to reduce your reliance on Docker Hub, here\u2019s how you can get up and running with a registry deployment.<\/span><\/p>\n<div id=\"article-content-area\">\n<p>Docker Registry is a server-side system that stores and indexes Docker images. You \u201cpush\u201d prebuilt images into the registry. Other users can then \u201cpull\u201d them down to run them, without needing access to the original Dockerfile.<\/p>\n<p>The best known public registry is Docker Hub. Using your own registry lets you take control of image storage and access methods. It can also facilitate integration with third-party tools.<\/p>\n<p>There are managed services available that let you quickly create registry installations. This guide focuses on self-hosting a registry on your own server. The only prerequisites are you\u2019ll need to <a href=\"https:\/\/docs.docker.com\/get-docker\" target=\"_blank\" rel=\"nofollow noopener\">have Docker and docker-compose installed<\/a> on the machine which will host the registry.<\/p>\n<h2 id=\"running-a-registry\"><span class=\"ez-toc-section\" id=\"Running_a_Registry\"><\/span>Running a Registry<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Docker Registry server is distributed as its own Docker image. You can get it <a href=\"https:\/\/hub.docker.com\/_\/registry\" target=\"_blank\" rel=\"nofollow noopener\">from Docker Hub<\/a>. The server is exposed on port 5000; you\u2019ll need to bind a host port to it so that clients can connect.<\/p>\n<p>You must also set up a volume so Docker Hub has somewhere to persistently store uploaded images. Make sure you\u2019ve got sufficient free space on your host. An actively used registry can quickly grow.<\/p>\n<p>Begin by creating a <code>docker-compose.yml<\/code> file to describe your deployment. You can adjust the ports and filesystem paths to match your preferences. This example will make the registry accessible on port 5000. Images will be stored in the <code>data<\/code> folder within your working directory.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co3\">version<\/span><span class=\"sy2\">: <\/span><span class=\"st0\">\"3\"<\/span><span class=\"co4\">\nservices<\/span>:<span class=\"co4\">\n  registry<\/span>:<span class=\"co3\">\n      image<\/span><span class=\"sy2\">: <\/span>registry:2<span class=\"co4\">\n      ports<\/span><span class=\"sy2\">:\n<\/span>        - 5000:5000<span class=\"co4\">\n      environment<\/span>:<span class=\"co3\">\n        - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY<\/span><span class=\"sy2\">: <\/span>\/data<span class=\"co3\">\n      restart<\/span><span class=\"sy2\">: <\/span>unless-stopped<span class=\"co4\">\n      volumes<\/span><span class=\"sy2\">:\n<\/span>        - .\/data:\/data<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Save the file and run <code>docker-compose up -d<\/code> to launch your registry. docker-compose will pull the registry image from Docker Hub. It\u2019ll then start a new container using your configuration.<\/p>\n<h2 id=\"accessing-your-registry\"><span class=\"ez-toc-section\" id=\"Accessing_Your_Registry\"><\/span>Accessing Your Registry<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You should now be able to start using your registry. Tag an image using a path which resolves to your registry. You can use <code>localhost<\/code> if you\u2019re working on the registry server itself. You should then be able to push the image up to the registry.<\/p>\n<pre>docker tag my-image localhost:5000\/my-image\ndocker push localhost:5000\/my-image<\/pre>\n<p>The image will now be available in the registry. If you inspect your <code>data<\/code> folder, you\u2019ll see the layers that make up the image. You could pull it down from another machine by using <code>docker pull<\/code>. Replace <code>localhost<\/code> with the network address of the server running the registry.<\/p>\n<h2 id=\"setting-up-authentication\"><span class=\"ez-toc-section\" id=\"Setting_up_Authentication\"><\/span>Setting up Authentication<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The registry is currently unsecured. Anyone can pull and push images! Let\u2019s resolve that by setting up authentication. Once configured, you\u2019ll need to use <code>docker login<\/code> before you can interact with the registry.<\/p>\n<p>Docker Registry\u2019s default <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>roach to authentication uses HTTP Basic Auth. You\u2019ll need to create an <code>htpasswd<\/code> file \u2013 this is best done using the command provided by <code>apache2-utils<\/code>.<\/p>\n<pre>sudo apt install apache2-utils\nmkdir auth\nhtpasswd -Bc auth\/.htpasswd my-username<\/pre>\n<p>This will create an authentication file for the user <code>my-username<\/code>. You\u2019ll be prompted to supply a password. The <code>htpasswd<\/code> file will then be written into the working directory as <code>auth\/.htpasswd<\/code>.<\/p>\n<p>Next update your <code>docker-compose.yml<\/code> to configure the authentication system. You must specify the type of authentication used and the path to the <code>htpasswd<\/code> file. This will need to be mounted as a new volume.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co3\">version<\/span><span class=\"sy2\">: <\/span><span class=\"st0\">\"3\"<\/span><span class=\"co4\">\nservices<\/span>:<span class=\"co4\">\n  registry<\/span>:<span class=\"co3\">\n      image<\/span><span class=\"sy2\">: <\/span>registry:2<span class=\"co4\">\n      ports<\/span><span class=\"sy2\">:\n<\/span>        - 5000:5000<span class=\"co4\">\n      environment<\/span>:<span class=\"co3\">\n        - REGISTRY_AUTH<\/span><span class=\"sy2\">: <\/span>htpasswd<span class=\"co3\">\n        - REGISTRY_AUTH_HTPASSWD_REALM<\/span><span class=\"sy2\">: <\/span>Registry Realm<span class=\"co3\">\n        - REGISTRY_AUTH_HTPASSWD_PATH<\/span><span class=\"sy2\">: <\/span>\/auth\/.htpasswd<span class=\"co3\">\n        - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY<\/span><span class=\"sy2\">: <\/span>\/data<span class=\"co3\">\n      restart<\/span><span class=\"sy2\">: <\/span>unless-stopped<span class=\"co4\">\n      volumes<\/span><span class=\"sy2\">:\n<\/span>        - .\/auth:\/auth\n        - .\/data:\/data<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Run <code>docker-compose up -d --force-recreate<\/code> to recreate the running registry container using the new configuration. You should find the Docker CLI now refuses to let you interact with the registry.<\/p>\n<p>To restore access, run <code>docker login localhost:5000<\/code>. You\u2019ll need to adjust the registry URI if you\u2019re not running Docker on the same machine. Docker will prompt you to supply your username and password. Use the values you set while creating the <code>.htpasswd<\/code> file.<\/p>\n<p>Once authentication succeeds, you\u2019ll be able to start pushing and pulling images again. Docker caches your credentials so you won\u2019t need to repeat authentication until you <code>docker logout<\/code>.<\/p>\n<h2 id=\"setting-up-ssl\"><span class=\"ez-toc-section\" id=\"Setting_Up_SSL\"><\/span>Setting Up SSL<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You\u2019ll need to add a SSL certificate for all but the most basic connections over <code>localhost<\/code>. You can add an SSL certificate to the registry by mounting the certificate into a volume and setting additional environment variables. You should usually update the port configuration so the registry listens on 443, the default HTTPS port.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co3\">version<\/span><span class=\"sy2\">: <\/span><span class=\"st0\">\"3\"<\/span><span class=\"co4\">\nservices<\/span>:<span class=\"co4\">\n  registry<\/span>:<span class=\"co3\">\n      image<\/span><span class=\"sy2\">: <\/span>registry:2<span class=\"co4\">\n      ports<\/span><span class=\"sy2\">:\n<\/span>        - 443:5000<span class=\"co4\">\n      environment<\/span>:<span class=\"co3\">\n        - REGISTRY_AUTH<\/span><span class=\"sy2\">: <\/span>htpasswd<span class=\"co3\">\n        - REGISTRY_AUTH_HTPASSWD_REALM<\/span><span class=\"sy2\">: <\/span>Registry Realm<span class=\"co3\">\n        - REGISTRY_AUTH_HTPASSWD_PATH<\/span><span class=\"sy2\">: <\/span>\/auth\/.htpasswd<span class=\"co3\">\n        - REGISTRY_HTTP_ADDR<\/span><span class=\"sy2\">: <\/span>0.0.0.0:443\n        - REGISTRY_HTTP_TLS_CERTIFICATE=\/certs\/cert.crt\n        - REGISTRY_HTTP_TLS_KEY=\/certs\/cert.key<span class=\"co3\">\n        - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY<\/span><span class=\"sy2\">: <\/span>\/data<span class=\"co3\">\n      restart<\/span><span class=\"sy2\">: <\/span>unless-stopped<span class=\"co4\">\n      volumes<\/span><span class=\"sy2\">:\n<\/span>        - .\/auth:\/auth\n        - .\/certs:\/certs\n        - .\/data:\/data<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Add your certificate files to <code>certs<\/code> and then restart the registry. It should come back up with HTTPS support, using the provided certificate file.<\/p>\n<h2 id=\"ssl-via-letsencrypt\"><span class=\"ez-toc-section\" id=\"SSL_via_LetsEncrypt\"><\/span>SSL via LetsEncrypt<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Registry server has built-in support for Let\u2019s Encrypt. This lets you automatically generate and renew your SSL certificates. To use Let\u2019s Encrypt, you <em>must<\/em> publicly expose your registry on port 443.<\/p>\n<p>Set the <code>REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL<\/code> and <code>REGISTRY_HTTP_TLS_LETSENCRYPT_HOSTS<\/code> environment variables to add TLS support to your registry. Let\u2019s Encrypt will use the email address as the contact for your SSL certificates.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co3\">version<\/span><span class=\"sy2\">: <\/span><span class=\"st0\">\"3\"<\/span><span class=\"co4\">\nservices<\/span>:<span class=\"co4\">\n  registry<\/span>:<span class=\"co3\">\n      image<\/span><span class=\"sy2\">: <\/span>registry:2<span class=\"co4\">\n      ports<\/span><span class=\"sy2\">:\n<\/span>        - 443:5000<span class=\"co4\">\n      environment<\/span>:<span class=\"co3\">\n        - REGISTRY_AUTH<\/span><span class=\"sy2\">: <\/span>htpasswd<span class=\"co3\">\n        - REGISTRY_AUTH_HTPASSWD_REALM<\/span><span class=\"sy2\">: <\/span>Registry Realm<span class=\"co3\">\n        - REGISTRY_AUTH_HTPASSWD_PATH<\/span><span class=\"sy2\">: <\/span>\/auth\/.htpasswd<span class=\"co3\">\n        - REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL<\/span><span class=\"sy2\">: <\/span>example@example.com<span class=\"co3\">\n        - REGISTRY_HTTP_TLS_LETSENCRYPT_HOSTS<\/span><span class=\"sy2\">: <\/span><span class=\"br0\">[<\/span>my-registry.com<span class=\"br0\">]<\/span><span class=\"co3\">\n        - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY<\/span><span class=\"sy2\">: <\/span>\/data<span class=\"co3\">\n      restart<\/span><span class=\"sy2\">: <\/span>unless-stopped<span class=\"co4\">\n      volumes<\/span><span class=\"sy2\">:\n<\/span>        - .\/auth:\/auth\n        - .\/certs:\/certs\n        - .\/data:\/data<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Recreate the container with <code>docker-compose up -d --force-recreate<\/code> to apply the change. The registry will use Let\u2019s Encrypt to acquire an SSL certificate for the specified domains. It might take a few minutes for the certificate to become available.<\/p>\n<h2 id=\"other-ways-to-deploy\"><span class=\"ez-toc-section\" id=\"Other_Ways_to_Deploy\"><\/span>Other Ways to Deploy<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Deploying with docker-compose, HTTP Basic Auth and Let\u2019s Encrypt is the simplest way of running a private container registry. There are other options available though, particularly if you want more advanced access control.<\/p>\n<p>Using Basic Auth doesn\u2019t scale well beyond a handful of users. As an alternative, the server supports a <a href=\"https:\/\/docs.docker.com\/registry\/spec\/auth\/token\" target=\"_blank\" rel=\"nofollow noopener\">delegated authentication routine<\/a> that relies on external token servers. This is designed for scenarios where tight integration with organisational access control systems is required.<\/p>\n<p>The Registry server doesn\u2019t implement token authentication itself. Projects such as <a href=\"https:\/\/github.com\/cesanta\/docker_auth\" target=\"_blank\" rel=\"nofollow noopener\">docker_auth<\/a> try to add this missing piece, providing a fully-fledged auth system that can be deployed alongside the main registry.<\/p>\n<p>Alternative projects aim to make it easier to manage your registry, without resorting to hands-on terminal commands. <a href=\"https:\/\/github.com\/SUSE\/Portus\" target=\"_blank\" rel=\"nofollow noopener\">Portus<\/a> is a SUSE project which provides a web frontend, as well as its own user authentication system.<\/p>\n<\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span> too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/10259\/how-to-create-your-own-private-docker-registry\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Running your own Docker registry gives you a private place to store your Docker images. Whether you\u2019re in a corporate environment or just want to reduce your reliance on Docker Hub, here\u2019s how you can get up and running with a registry deployment. Docker Registry is a server-side system that stores and indexes Docker images&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-209659","post","type-post","status-publish","format-standard","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/209659","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=209659"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/209659\/revisions"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=209659"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=209659"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=209659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}