{"id":3745,"date":"2018-07-23T16:59:18","date_gmt":"2018-07-23T16:59:18","guid":{"rendered":"https:\/\/cloudkul.com\/blog\/?p=3745"},"modified":"2019-07-26T07:35:25","modified_gmt":"2019-07-26T07:35:25","slug":"how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu","status":"publish","type":"post","link":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/","title":{"rendered":"How to Setup and Manage a Secured Private Docker Registry on Ubuntu"},"content":{"rendered":"<p>In our previous blogs, we have discussed various possible docker architectures and its integration with e-commerce platforms like Magento. In today&#8217;s discussion, we will setup a secure private docker registry.<\/p>\n<p>Docker being a very powerful deployment tool, allows flexibility, scalability and centralisation. A centralised storage hub is facilitated by\u00a0<a href=\"https:\/\/hub.docker.com\/\">Docker hub<\/a>, a public registry for storing docker images. Using Docker hub for storing and accessing docker images is indeed a good idea for Devops personnel, however you might not want to share everything on a public docker registry, making it accessible to everyone.<\/p>\n<p>Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture. All images stored in private docker registry will be saved on the server.<\/p>\n<p>&nbsp;<\/p>\n<h2>Docker Registry Setup<\/h2>\n<p>&nbsp;<\/p>\n<p>In our project, we are using Ubuntu 16.04 as Operating System and docker-registry version 2. To deploy docker registry, please ensure that you have latest versions of docker engine and docker-compose tool installed on your server.<\/p>\n<p>For docker CE Installation:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">https:\/\/docs.docker.com\/install\/linux\/docker-ce\/ubuntu\/#install-docker-ce<\/pre>\n<p>&nbsp;<\/p>\n<p>To install docker-compose tool:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">https:\/\/docs.docker.com\/compose\/install\/<\/pre>\n<p>&nbsp;<\/p>\n<p>Now, create a project directory for docker registry,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">mkdir docker-registry<\/pre>\n<p>&nbsp;<\/p>\n<p>Create a <em><strong>docker-compose.yml<\/strong><\/em> file and a directory naming <em><strong>data<\/strong><\/em> in the docker-registry directory. Contents of docker-compose.yml are,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">registry:\r\n  image: registry\r\n  container_name: registry\r\n  ports:\r\n    - 5000:5000\r\n  environment:\r\n    - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=\/data\r\n    - REGISTRY_STORAGE_DELETE_ENABLED=true\r\n\r\n  volumes:\r\n    - .\/data:\/data<\/pre>\n<p>&nbsp;<\/p>\n<p>This docker-compose.yml file will pull <em>registry:latest<\/em> image and will run it on port 5000. Also, we are storing Images on our docker host, so we will map data directory with the\u00a0registry storage filesystem root directory inside registry container.\u00a0Also, we have enabled image deletion parameter in docker registry.<\/p>\n<p>So far we have added a block for registry setup in docker-compose.yml file. Still our private docker registry is running over plain HTTP and is accessible to everyone having docker registry URL.<\/p>\n<p>Now we will proceed with deploying SSL and user authentication mechanism in the registry. Create a directory<em><strong> nginx<\/strong><\/em> inside <em><strong>docker-registry<\/strong><\/em> directory. Upload your SSL certificates for your registry domain or create private SSL certificates to be added in nginx configuration file.<\/p>\n<p>To generate private certificates, run the following command,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">cd docker-registry\/nginx\/ &amp;&amp; \\ \r\necho -e \"\\n\\n\\n\\n\\n\\n\\n\" | openssl req -x509 -nodes -days 365 -newkey rsa:2048 \\ \r\n-keyout myregistry.key -out myregistry.crt<\/pre>\n<p>&nbsp;<\/p>\n<p>For user authentication management, create a user for basic HTTP authentication as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">cd docker-registry\/nginx\r\nhtpasswd -c registry.password my_user<\/pre>\n<p>&nbsp;<\/p>\n<p>Now, setup nginx configuration file as registry.conf inside nginx docker directory and mention path to SSL certificates, basic authentication configuration and registry info as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">upstream docker-registry {\r\nserver registry:5000;\r\n}\r\n\r\nserver {\r\n   listen 80 default_server;\r\n    server_name myregistry.com;\r\n    return 302 https:\/\/$server_name$request_uri;\r\n    }\r\n\r\nserver {\r\n\r\n  listen 443;\r\n  server_name myregistry.com;\r\n  # SSL\r\n   ssl on;\r\n   ssl_certificate \/etc\/nginx\/conf.d\/myregistry.crt;\r\n   ssl_certificate_key \/etc\/nginx\/conf.d\/myregistry.key;\r\n\r\n  # disable any limits to avoid HTTP 413 for large image uploads\r\n  client_max_body_size 0;\r\n\r\n  # required to avoid HTTP 411: see Issue #1486 (https:\/\/github.com\/docker\/docker\/issues\/1486)\r\n  chunked_transfer_encoding on;\r\n\r\n  # Do not allow connections from docker 1.5 and earlier\r\n  # docker pre-1.6.0 did not properly set the user agent on ping, catch \"Go *\" user agents\r\n   location = \/ {\r\n    rewrite ^ https:\/\/$server_name$request_uri\/v2\/_catalog redirect;\r\n}\r\n    location \/v2\/ {\r\n    if ($http_user_agent ~ \"^(docker\\\/1\\.(3|4|5(?!\\.[0-9]-dev))|Go ).*$\" ) {\r\n      return 404;\r\n    }\r\n   # To add basic authentication to v2 use auth_basic setting plus add_header\r\n     auth_basic \"registry.localhost\";\r\n     auth_basic_user_file \/etc\/nginx\/conf.d\/registry.password;\r\n     add_header 'Docker-Distribution-Api-Version' 'registry\/2.0' always;\r\n\r\n    proxy_pass                          http:\/\/docker-registry;\r\n    proxy_set_header  Host              $http_host;   # required for docker client's sake\r\n    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP\r\n    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;\r\n    proxy_set_header  X-Forwarded-Proto $scheme;\r\n    proxy_read_timeout                  900;\r\n  }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Here nginx will act as a SSL terminator for private docker registry. Now add Nginx block in docker-compose.yml.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">nginx:\r\n  image: \"nginx:1.9\"\r\n  container_name: nginx\r\n  ports:\r\n    - 443:443\r\n    - 80:80\r\n  links:\r\n    - registry:registry\r\n  volumes:\r\n    - .\/nginx\/:\/etc\/nginx\/conf.d\/\r\n\r\nregistry:\r\n  image: registry\r\n  container_name: registry\r\n  ports:\r\n    - 5000:5000\r\n  environment:\r\n    - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=\/data\r\n    - REGISTRY_STORAGE_DELETE_ENABLED=true\r\n\r\n  volumes:\r\n    - .\/data:\/data\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Now docker environment is ready to be created. We will build the images and deploy containers to run a secure private docker registry.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">docker-compose up -d<\/pre>\n<p>&nbsp;<\/p>\n<p>To check created docker images,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">docker images<\/pre>\n<p>&nbsp;<\/p>\n<p>To check running docker containers.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker-compose ps<\/pre>\n<p>&nbsp;<\/p>\n<h2>Pushing an Image to Secured Private Docker Registry<\/h2>\n<p>&nbsp;<\/p>\n<p>Your secured private docker registry is ready to be used. We\u00a0will now push a docker image to docker-registry. Lets pull docker image hello-world<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker pull hello-world<\/pre>\n<p>&nbsp;<\/p>\n<p>Login to private docker registry and enter your registry auth user and password. As in this case,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker login myregistry.com<\/pre>\n<p>&nbsp;<\/p>\n<p>Now tag docker image hello-world with the registry,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">docker tag hello-world myregistry.com\/hello-world<\/pre>\n<p>&nbsp;<\/p>\n<p>Push the tagged docker image as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">docker push myregitsry\/hello-world<\/pre>\n<p>&nbsp;<\/p>\n<p>Now check the uploaded image on docker registry from terminal using curl,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">curl -u my_user:my_user_password https:\/\/myregistry.com\/v2\/_catalog<\/pre>\n<p>&nbsp;<\/p>\n<p>Above command will list images in json format. We can also check list of docker images stored on registry by inspecting data directory on docker host,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">ls docker-registry\/data\/docker\/registry\/v2\/repositories\/<\/pre>\n<p>&nbsp;<\/p>\n<p>In order to delete any particular image, first check image availability along with its tag as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">curl -u my_user:my_user_password https:\/\/registry.com\/v2\/mention_image_name\/tags\/list<\/pre>\n<p>&nbsp;<\/p>\n<p>Now, delete image repositories and blobs, and restart registry container as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">cd docker-registry\/data\/docker\/registry\/v2\/repositories\/\r\nrm -rf mention_image_name\r\ndocker exec -ti registry bin\/registry garbage-collect \/etc\/docker\/registry\/config.yml\r\ndocker-compose restart registry<\/pre>\n<p>&nbsp;<\/p>\n<p>Finally, list all the images of docker registry to check available images,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">curl -u my_user:my_user_password https:\/\/myregistry.com\/v2\/_catalog<\/pre>\n<p>&nbsp;<\/p>\n<p>At last, you are all set to launch your own private docker registry over ssl. Explore more and more with docker containers and docker registry applications. A well managed container architecture lays strong foundation of distributed architecture.<\/p>\n<p>You can discuss your doubts and queries with us at <a href=\"mailto:support@webkul.com\">support@webkul.com<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In our previous blogs, we have discussed various possible docker architectures and its integration with <a class=\"text-primary\" title=\"read more\" href=\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/\">[&#8230;]<\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2,35,86,96,36],"tags":[189,5,201,200,202],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Setup and Manage a Secured Private Docker Registry on Ubuntu - Cloudkul<\/title>\n<meta name=\"description\" content=\"Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Setup and Manage a Secured Private Docker Registry on Ubuntu - Cloudkul\" \/>\n<meta property=\"og:description\" content=\"Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudkul\" \/>\n<meta property=\"article:published_time\" content=\"2018-07-23T16:59:18+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-07-26T07:35:25+00:00\" \/>\n<meta name=\"author\" content=\"Alankrit Srivastava\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/\",\"url\":\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/\",\"name\":\"How to Setup and Manage a Secured Private Docker Registry on Ubuntu - Cloudkul\",\"isPartOf\":{\"@id\":\"https:\/\/cloudkul.com\/blog\/#website\"},\"datePublished\":\"2018-07-23T16:59:18+00:00\",\"dateModified\":\"2019-07-26T07:35:25+00:00\",\"author\":{\"@id\":\"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16\"},\"description\":\"Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudkul.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Setup and Manage a Secured Private Docker Registry on Ubuntu\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudkul.com\/blog\/#website\",\"url\":\"https:\/\/cloudkul.com\/blog\/\",\"name\":\"Cloudkul\",\"description\":\"Host your eCommerce Store on AWS with Optimized Performance\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudkul.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16\",\"name\":\"Alankrit Srivastava\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g\",\"caption\":\"Alankrit Srivastava\"},\"description\":\"DevOps Manager at Webkul Software Privated Limited\",\"sameAs\":[\"http:\/\/cloudkul.com\"],\"url\":\"https:\/\/cloudkul.com\/blog\/author\/alankrit-srivastava256\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Setup and Manage a Secured Private Docker Registry on Ubuntu - Cloudkul","description":"Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/","og_locale":"en_US","og_type":"article","og_title":"How to Setup and Manage a Secured Private Docker Registry on Ubuntu - Cloudkul","og_description":"Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture.","og_url":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/","og_site_name":"Cloudkul","article_published_time":"2018-07-23T16:59:18+00:00","article_modified_time":"2019-07-26T07:35:25+00:00","author":"Alankrit Srivastava","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/","url":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/","name":"How to Setup and Manage a Secured Private Docker Registry on Ubuntu - Cloudkul","isPartOf":{"@id":"https:\/\/cloudkul.com\/blog\/#website"},"datePublished":"2018-07-23T16:59:18+00:00","dateModified":"2019-07-26T07:35:25+00:00","author":{"@id":"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16"},"description":"Docker provides its own image to setup a private docker registry, deploying which we can store docker images within our internal server architecture.","breadcrumb":{"@id":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/cloudkul.com\/blog\/how-to-setup-and-manage-a-secured-private-docker-registry-on-ubuntu\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudkul.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to Setup and Manage a Secured Private Docker Registry on Ubuntu"}]},{"@type":"WebSite","@id":"https:\/\/cloudkul.com\/blog\/#website","url":"https:\/\/cloudkul.com\/blog\/","name":"Cloudkul","description":"Host your eCommerce Store on AWS with Optimized Performance","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudkul.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16","name":"Alankrit Srivastava","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g","caption":"Alankrit Srivastava"},"description":"DevOps Manager at Webkul Software Privated Limited","sameAs":["http:\/\/cloudkul.com"],"url":"https:\/\/cloudkul.com\/blog\/author\/alankrit-srivastava256\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts\/3745"}],"collection":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/comments?post=3745"}],"version-history":[{"count":15,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts\/3745\/revisions"}],"predecessor-version":[{"id":6459,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts\/3745\/revisions\/6459"}],"wp:attachment":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/media?parent=3745"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/categories?post=3745"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/tags?post=3745"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}