One place for hosting & domains

      Registry

      How To Set Up a Private Docker Registry on Top of DigitalOcean Spaces and Use It with DigitalOcean Kubernetes


      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      A Docker registry is a storage and content delivery system for named Docker images, which are the industry standard for containerized applications. A private Docker registry allows you to securely share your images within your team or organization with more flexibility and control when compared to public ones. By hosting your private Docker registry directly in your Kubernetes cluster, you can achieve higher speeds, lower latency, and better availability, all while having control over the registry.

      The underlying registry storage is delegated to external drivers. The default storage system is the local filesystem, but you can swap this for a cloud-based storage driver. DigitalOcean Spaces is an S3-compatible object storage designed for developer teams and businesses that want a scalable, simple, and affordable way to store and serve vast amounts of data, and is very suitable for storing Docker images. It has a built-in CDN network, which can greatly reduce latency when frequently accessing images.

      In this tutorial, you’ll deploy your private Docker registry to your DigitalOcean Kubernetes cluster using Helm, backed up by DigitalOcean Spaces for storing data. You’ll create API keys for your designated Space, install the Docker registry to your cluster with custom configuration, configure Kubernetes to properly authenticate with it, and test it by running a sample deployment on the cluster. At the end of this tutorial, you’ll have a secure, private Docker registry installed on your DigitalOcean Kubernetes cluster.

      Prerequisites

      Before you begin this tutorial, you’ll need:

      • Docker installed on the machine that you’ll access your cluster from. For Ubuntu 18.04 visit How To Install and Use Docker on Ubuntu 18.04. You only need to complete the first step. Otherwise visit Docker’s website for other distributions.

      • A DigitalOcean Kubernetes cluster with your connection configuration configured as the kubectl default. Instructions on how to configure kubectl are shown under the Connect to your Cluster step shown when you create your cluster. To learn how to create a Kubernetes cluster on DigitalOcean, see Kubernetes Quickstart.

      • A DigitalOcean Space with API keys (access and secret). To learn how to create a DigitalOcean Space and API keys, see How To Create a DigitalOcean Space and API Key.

      • The Helm package manager installed on your local machine, and Tiller installed on your cluster. Complete steps 1 and 2 of the How To Install Software on Kubernetes Clusters with the Helm Package Manager. You only need to complete the first two steps.

      • The Nginx Ingress Controller and Cert-Manager installed on the cluster. For a guide on how to do this, see How to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes.

      • A domain name with two DNS A records pointed to the DigitalOcean Load Balancer used by the Ingress. If you are using DigitalOcean to manage your domain’s DNS records, consult How to Manage DNS Records to create A records. In this tutorial, we’ll refer to the A records as registry.example.com and k8s-test.example.com.

      Step 1 — Configuring and Installing the Docker Registry

      In this step, you will create a configuration file for the registry deployment and install the Docker registry to your cluster with the given config using the Helm package manager.

      During the course of this tutorial, you will use a configuration file called chart_values.yaml to override some of the default settings for the Docker registry Helm chart. Helm calls its packages, charts; these are sets of files that outline a related selection of Kubernetes resources. You’ll edit the settings to specify DigitalOcean Spaces as the underlying storage system and enable HTTPS access by wiring up Let’s Encrypt TLS certificates.

      As part of the prerequisite, you would have created the echo1 and echo2 services and an echo_ingress ingress for testing purposes; you will not need these in this tutorial, so you can now delete them.

      Start off by deleting the ingress by running the following command:

      • kubectl delete -f echo_ingress.yaml

      Then, delete the two test services:

      • kubectl delete -f echo1.yaml && kubectl delete -f echo2.yaml

      The kubectl delete command accepts the file to delete when passed the -f parameter.

      Create a folder that will serve as your workspace:

      Navigate to it by running:

      Now, using your text editor, create your chart_values.yaml file:

      Add the following lines, ensuring you replace the highlighted lines with your details:

      chart_values.yaml

      ingress:
        enabled: true
        hosts:
          - registry.example.com
        annotations:
          kubernetes.io/ingress.class: nginx
          certmanager.k8s.io/cluster-issuer: letsencrypt-prod
          nginx.ingress.kubernetes.io/proxy-body-size: "30720m"
        tls:
          - secretName: letsencrypt-prod
            hosts:
              - registry.example.com
      
      storage: s3
      
      secrets:
        htpasswd: ""
        s3:
          accessKey: "your_space_access_key"
          secretKey: "your_space_secret_key"
      
      s3:
        region: your_space_region
        regionEndpoint: your_space_region.digitaloceanspaces.com
        secure: true
        bucket: your_space_name
      

      The first block, ingress, configures the Kubernetes Ingress that will be created as a part of the Helm chart deployment. The Ingress object makes outside HTTP/HTTPS routes point to internal services in the cluster, thus allowing communication from the outside. The overridden values are:

      • enabled: set to true to enable the Ingress.
      • hosts: a list of hosts from which the Ingress will accept traffic.
      • annotations: a list of metadata that provides further direction to other parts of Kubernetes on how to treat the Ingress. You set the Ingress Controller to nginx, the Let's Encrypt cluster issuer to the production variant (letsencrypt-prod), and tell the nginx controller to accept files with a max size of 30 GB, which is a sensible limit for even the largest Docker images.
      • tls: this subcategory configures Let's Encrypt HTTPS. You populate the hosts list that defines from which secure hosts this Ingress will accept HTTPS traffic with our example domain name.

      Then, you set the file system storage to s3 — the other available option would be filesystem. Here s3 indicates using a remote storage system compatible with the industry-standard Amazon S3 API, which DigitalOcean Spaces fulfills.

      In the next block, secrets, you configure keys for accessing your DigitalOcean Space under the s3 subcategory. Finally, in the s3 block, you configure the parameters specifying your Space.

      Save and close your file.

      Now, if you haven't already done so, set up your A records to point to the Load Balancer you created as part of the Nginx Ingress Controller installation in the prerequisite tutorial. To see how to set your DNS on DigitalOcean, see How to Manage DNS Records.

      Next, ensure your Space isn't empty. The Docker registry won't run at all if you don't have any files in your Space. To get around this, upload a file. Navigate to the Spaces tab, find your Space, click the Upload File button, and upload any file you'd like. You could upload the configuration file you just created.

      Empty file uploaded to empty Space

      Before installing anything via Helm, you need to refresh its cache. This will update the latest information about your chart repository. To do this run the following command:

      Now, you'll deploy the Docker registry chart with this custom configuration via Helm by running:

      • helm install stable/docker-registry -f chart_values.yaml --name docker-registry

      You'll see the following output:

      Output

      NAME: docker-registry ... NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/ConfigMap NAME DATA AGE docker-registry-config 1 1s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE docker-registry-54df68fd64-l26fb 0/1 ContainerCreating 0 1s ==> v1/Secret NAME TYPE DATA AGE docker-registry-secret Opaque 3 1s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE docker-registry ClusterIP 10.245.131.143 <none> 5000/TCP 1s ==> v1beta1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE docker-registry 0/1 1 0 1s ==> v1beta1/Ingress NAME HOSTS ADDRESS PORTS AGE docker-registry registry.example.com 80, 443 1s NOTES: 1. Get the application URL by running these commands: https://registry.example.com/

      Helm lists all the resources it created as a result of the Docker registry chart deployment. The registry is now accessible from the domain name you specified earlier.

      You've configured and deployed a Docker registry on your Kubernetes cluster. Next, you will test the availability of the newly deployed Docker registry.

      Step 2 — Testing Pushing and Pulling

      In this step, you'll test your newly deployed Docker registry by pushing and pulling images to and from it. Currently, the registry is empty. To have something to push, you need to have an image available on the machine you're working from. Let's use the mysql Docker image.

      Start off by pulling mysql from the Docker Hub:

      Your output will look like this:

      Output

      Using default tag: latest latest: Pulling from library/mysql 27833a3ba0a5: Pull complete ... e906385f419d: Pull complete Digest: sha256:a7cf659a764732a27963429a87eccc8457e6d4af0ee9d5140a3b56e74986eed7 Status: Downloaded newer image for mysql:latest

      You now have the image available locally. To inform Docker where to push it, you'll need to tag it with the host name, like so:

      • sudo docker tag mysql registry.example.com/mysql

      Then, push the image to the new registry:

      • sudo docker push registry.example.com/mysql

      This command will run successfully and indicate that your new registry is properly configured and accepting traffic — including pushing new images. If you see an error, double check your steps against steps 1 and 2.

      To test pulling from the registry cleanly, first delete the local mysql images with the following command:

      • sudo docker rmi registry.example.com/mysql && sudo docker rmi mysql

      Then, pull it from the registry:

      • sudo docker pull registry.example.com/mysql

      This command will take a few seconds to complete. If it runs successfully, that means your registry is working correctly. If it shows an error, double check what you have entered against the previous commands.

      You can list Docker images available locally by running the following command:

      You'll see output listing the images available on your local machine, along with their ID and date of creation.

      Your Docker registry is configured. You've pushed an image to it and verified you can pull it down. Now let's add authentication so only certain people can access the code.

      Step 3 — Adding Account Authentication and Configuring Kubernetes Access

      In this step, you'll set up username and password authentication for the registry using the htpasswd utility.

      The htpasswd utility comes from the Apache webserver, which you can use for creating files that store usernames and passwords for basic authentication of HTTP users. The format of htpasswd files is username:hashed_password (one per line), which is portable enough to allow other programs to use it as well.

      To make htpasswd available on the system, you'll need to install it by running:

      • sudo apt install apache2-utils -y

      Note:
      If you're running this tutorial from a Mac, you'll need to use the following command to make htpasswd available on your machine:

      • docker run --rm -v ${PWD}:/app -it httpd htpasswd -b -c /app/htpasswd_file sammy password

      Create it by executing the following command:

      Add a username and password combination to htpasswd_file:

      • htpasswd -B htpasswd_file username

      Docker requires the password to be hashed using the bcrypt algorithm, which is why we pass the -B parameter. The bcrypt algorithm is a password hashing function based on Blowfish block cipher, with a work factor parameter, which specifies how expensive the hash function will be.

      Remember to replace username with your desired username. When run, htpasswd will ask you for the accompanying password and add the combination to htpasswd_file. You can repeat this command for as many users as you wish to add.

      Now, show the contents of htpasswd_file by running the following command:

      Select and copy the contents shown.

      To add authentication to your Docker registry, you'll need to edit chart_values.yaml and add the contents of htpasswd_file in the htpasswd variable.

      Open chart_values.yaml for editing:

      Find the line that looks like this:

      chart_values.yaml

        htpasswd: ""
      

      Edit it to match the following, replacing htpasswd_file_contents with the contents you copied from the htpasswd_file:

      chart_values.yaml

        htpasswd: |-
          htpasswd_file_contents
      

      Be careful with the indentation, each line of the file contents must have four spaces before it.

      Once you've added your contents, save and close the file.

      To propagate the changes to your cluster, run the following command:

      • helm upgrade docker-registry stable/docker-registry -f chart_values.yaml

      The output will be similar to that shown when you first deployed your Docker registry:

      Output

      Release "docker-registry" has been upgraded. Happy Helming! LAST DEPLOYED: ... NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/ConfigMap NAME DATA AGE docker-registry-config 1 3m8s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE docker-registry-6c5bb7ffbf-ltnjv 1/1 Running 0 3m7s ==> v1/Secret NAME TYPE DATA AGE docker-registry-secret Opaque 4 3m8s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE docker-registry ClusterIP 10.245.128.245 <none> 5000/TCP 3m8s ==> v1beta1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE docker-registry 1/1 1 1 3m8s ==> v1beta1/Ingress NAME HOSTS ADDRESS PORTS AGE docker-registry registry.example.com 159.89.215.50 80, 443 3m8s NOTES: 1. Get the application URL by running these commands: https://registry.example.com/

      This command calls Helm and instructs it to upgrade an existing release, in your case docker-registry, with its chart defined in stable/docker-registry in the chart repository, after applying the chart_values.yaml file.

      Now, you'll try pulling an image from the registry again:

      • sudo docker pull registry.example.com/mysql

      The output will look like the following:

      Output

      Using default tag: latest Error response from daemon: Get https://registry.example.com/v2/mysql/manifests/latest: no basic auth credentials

      It correctly failed because you provided no credentials. This means that your Docker registry authorizes requests correctly.

      To log in to the registry, run the following command:

      • sudo docker login registry.example.com

      Remember to replace registry.example.com with your domain address. It will prompt you for a username and password. If it shows an error, double check what your htpasswd_file contains. You must define the username and password combination in the htpasswd_file, which you created earlier in this step.

      To test the login, you can try to pull again by running the following command:

      • sudo docker pull registry.example.com/mysql

      The output will look similar to the following:

      Output

      Using default tag: latest latest: Pulling from mysql Digest: sha256:f2dc118ca6fa4c88cde5889808c486dfe94bccecd01ca626b002a010bb66bcbe Status: Image is up to date for registry.example.com/mysql:latest

      You've now configured Docker and can log in securely. To configure Kubernetes to log in to your registry, run the following command:

      • sudo kubectl create secret generic regcred --from-file=.dockerconfigjson=/home/sammy/.docker/config.json --type=kubernetes.io/dockerconfigjson

      You will see the following output:

      Output

      secret/regcred created

      This command creates a secret in your cluster with the name regcred, takes the contents of the JSON file where Docker stores the credentials, and parses it as dockerconfigjson, which defines a registry credential in Kubernetes.

      You've used htpasswd to create a login config file, configured the registry to authenticate requests, and created a Kubernetes secret containing the login credentials. Next, you will test the integration between your Kubernetes cluster and registry.

      Step 4 — Testing Kubernetes Integration by Running a Sample Deployment

      In this step, you'll run a sample deployment with an image stored in the in-cluster registry to test the connection between your Kubernetes cluster and registry.

      In the last step, you created a secret, called regcred, containing login credentials for your private registry. It may contain login credentials for multiple registries, in which case you'll have to update the Secret accordingly.

      You can specify which secret Kubernetes should use when pulling containers in the pod definition by specifying imagePullSecrets. This step is necessary when the Docker registry requires authentication.

      You'll now deploy a sample Hello World image from your private Docker registry to your cluster. First, in order to push it, you'll pull it to your machine by running the following command:

      • sudo docker pull paulbouwer/hello-kubernetes:1.5

      Then, tag it by running:

      • sudo docker tag paulbouwer/hello-kubernetes:1.5 registry.example.com/paulbouwer/hello-kubernetes:1.5

      Finally, push it to your registry:

      • sudo docker push registry.example.com/paulbouwer/hello-kubernetes:1.5

      Delete it from your machine as you no longer need it locally:

      • sudo docker rmi registry.example.com/paulbouwer/hello-kubernetes:1.5

      Now, you'll deploy the sample Hello World application. First, create a new file, hello-world.yaml, using your text editor:

      Next, you'll define a Service and an Ingress to make the app accessible to outside of the cluster. Add the following lines, replacing the highlighted lines with your domains:

      hello-world.yaml

      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        name: hello-kubernetes-ingress
        annotations:
          kubernetes.io/ingress.class: nginx
          nginx.ingress.kubernetes.io/rewrite-target: /
      spec:
        rules:
        - host: k8s-test.example.com
          http:
            paths:
            - path: /
              backend:
                serviceName: hello-kubernetes
                servicePort: 80
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: hello-kubernetes
      spec:
        type: NodePort
        ports:
        - port: 80
          targetPort: 8080
        selector:
          app: hello-kubernetes
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: hello-kubernetes
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: hello-kubernetes
        template:
          metadata:
            labels:
              app: hello-kubernetes
          spec:
            containers:
            - name: hello-kubernetes
              image: registry.example.com/paulbouwer/hello-kubernetes:1.5
              ports:
              - containerPort: 8080
            imagePullSecrets:
            - name: regcred
      

      First, you define the Ingress for the Hello World deployment, which you will route through the Load Balancer that the Nginx Ingress Controller owns. Then, you define a service that can access the pods created in the deployment. In the actual deployment spec, you specify the image as the one located in your registry and set imagePullSecrets to regcred, which you created in the previous step.

      Save and close the file. To deploy this to your cluster, run the following command:

      • kubectl apply -f hello-world.yaml

      You'll see the following output:

      Output

      ingress.extensions/hello-kubernetes-ingress created service/hello-kubernetes created deployment.apps/hello-kubernetes created

      You can now navigate to your test domain — the second A record, k8s-test.example.com in this tutorial. You will see the Kubernetes Hello world! page.

      Hello World page

      The Hello World page lists some environment information, like the Linux kernel version and the internal ID of the pod the request was served from. You can also access your Space via the web interface to see the images you've worked with in this tutorial.

      If you want to delete this Hello World deployment after testing, run the following command:

      • kubectl delete -f hello-world.yaml

      You've created a sample Hello World deployment to test if Kubernetes is properly pulling images from your private registry.

      Conclusion

      You have now successfully deployed your own private Docker registry on your DigitalOcean Kubernetes cluster, using DigitalOcean Spaces as the storage layer underneath. There is no limit to how many images you can store, Spaces can extend infinitely, while at the same time providing the same security and robustness. In production, though, you should always strive to optimize your Docker images as much as possible, take a look at the How To Optimize Docker Images for Production tutorial.



      Source link

      How To Set Up a Private Docker Registry on Top of DigitalOcean Spaces and Use It with DO Kubernetes


      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      A Docker registry is a storage and content delivery system for named Docker images, which are the industry standard for containerized applications. A private Docker registry allows you to securely share your images within your team or organization with more flexibility and control when compared to public ones. By hosting your private Docker registry directly in your Kubernetes cluster, you can achieve higher speeds, lower latency, and better availability, all while having control over the registry.

      The underlying registry storage is delegated to external drivers. The default storage system is the local filesystem, but you can swap this for a cloud-based storage driver. DigitalOcean Spaces is an S3-compatible object storage designed for developer teams and businesses that want a scalable, simple, and affordable way to store and serve vast amounts of data, and is very suitable for storing Docker images. It has a built-in CDN network, which can greatly reduce latency when frequently accessing images.

      In this tutorial, you’ll deploy your private Docker registry to your DigitalOcean Kubernetes cluster using Helm, backed up by DigitalOcean Spaces for storing data. You’ll create API keys for your designated Space, install the Docker registry to your cluster with custom configuration, configure Kubernetes to properly authenticate with it, and test it by running a sample deployment on the cluster. At the end of this tutorial, you’ll have a secure, private Docker registry installed on your DigitalOcean Kubernetes cluster.

      Prerequisites

      Before you begin this tutorial, you’ll need:

      • Docker installed on the machine that you’ll access your cluster from. For Ubuntu 18.04 visit How To Install and Use Docker on Ubuntu 18.04. You only need to complete the first step. Otherwise visit Docker’s website for other distributions.

      • A DigitalOcean Kubernetes cluster with your connection configuration configured as the kubectl default. Instructions on how to configure kubectl are shown under the Connect to your Cluster step shown when you create your cluster. To learn how to create a Kubernetes cluster on DigitalOcean, see Kubernetes Quickstart.

      • A DigitalOcean Space with API keys (access and secret). To learn how to create a DigitalOcean Space and API keys, see How To Create a DigitalOcean Space and API Key.

      • The Helm package manager installed on your local machine, and Tiller installed on your cluster. Complete steps 1 and 2 of the How To Install Software on Kubernetes Clusters with the Helm Package Manager. You only need to complete the first two steps.

      • The Nginx Ingress Controller and Cert-Manager installed on the cluster. For a guide on how to do this, see How to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes.

      • A domain name with two DNS A records pointed to the DigitalOcean Load Balancer used by the Ingress. If you are using DigitalOcean to manage your domain’s DNS records, consult How to Manage DNS Records to create A records. In this tutorial, we’ll refer to the A records as registry.example.com and k8s-test.example.com.

      Step 1 — Configuring and Installing the Docker Registry

      In this step, you will create a configuration file for the registry deployment and install the Docker registry to your cluster with the given config using the Helm package manager.

      During the course of this tutorial, you will use a configuration file called chart_values.yaml to override some of the default settings for the Docker registry Helm chart. Helm calls its packages, charts; these are sets of files that outline a related selection of Kubernetes resources. You’ll edit the settings to specify DigitalOcean Spaces as the underlying storage system and enable HTTPS access by wiring up Let’s Encrypt TLS certificates.

      As part of the prerequisite, you would have created the echo1 and echo2 services and an echo_ingress ingress for testing purposes; you will not need these in this tutorial, so you can now delete them.

      Start off by deleting the ingress by running the following command:

      • kubectl delete -f echo_ingress.yaml

      Then, delete the two test services:

      • kubectl delete -f echo1.yaml && kubectl delete -f echo2.yaml

      The kubectl delete command accepts the file to delete when passed the -f parameter.

      Create a folder that will serve as your workspace:

      Navigate to it by running:

      Now, using your text editor, create your chart_values.yaml file:

      Add the following lines, ensuring you replace the highlighted lines with your details:

      chart_values.yaml

      ingress:
        enabled: true
        hosts:
          - registry.example.com
        annotations:
          kubernetes.io/ingress.class: nginx
          certmanager.k8s.io/cluster-issuer: letsencrypt-prod
          nginx.ingress.kubernetes.io/proxy-body-size: "30720m"
        tls:
          - secretName: letsencrypt-prod
            hosts:
              - registry.example.com
      
      storage: s3
      
      secrets:
        htpasswd: ""
        s3:
          accessKey: "your_space_access_key"
          secretKey: "your_space_secret_key"
      
      s3:
        region: your_space_region
        regionEndpoint: your_space_region.digitaloceanspaces.com
        secure: true
        bucket: your_space_name
      

      The first block, ingress, configures the Kubernetes Ingress that will be created as a part of the Helm chart deployment. The Ingress object makes outside HTTP/HTTPS routes point to internal services in the cluster, thus allowing communication from the outside. The overridden values are:

      • enabled: set to true to enable the Ingress.
      • hosts: a list of hosts from which the Ingress will accept traffic.
      • annotations: a list of metadata that provides further direction to other parts of Kubernetes on how to treat the Ingress. You set the Ingress Controller to nginx, the Let's Encrypt cluster issuer to the production variant (letsencrypt-prod), and tell the nginx controller to accept files with a max size of 30 GB, which is a sensible limit for even the largest Docker images.
      • tls: this subcategory configures Let's Encrypt HTTPS. You populate the hosts list that defines from which secure hosts this Ingress will accept HTTPS traffic with our example domain name.

      Then, you set the file system storage to s3 — the other available option would be filesystem. Here s3 indicates using a remote storage system compatible with the industry-standard Amazon S3 API, which DigitalOcean Spaces fulfills.

      In the next block, secrets, you configure keys for accessing your DO Space under the s3 subcategory. Finally, in the s3 block, you configure the parameters specifying your Space.

      Save and close your file.

      Now, if you haven't already done so, set up your A records to point to the Load Balancer you created as part of the Nginx Ingress Controller installation in the prerequisite tutorial. To see how to set your DNS on DigitalOcean, see How to Manage DNS Records.

      Next, ensure your Space isn't empty. The Docker registry won't run at all if you don't have any files in your Space. To get around this, upload a file. Navigate to the Spaces tab, find your Space, click the Upload File button, and upload any file you'd like. You could upload the configuration file you just created.

      Empty file uploaded to empty Space

      Before installing anything via Helm, you need to refresh its cache. This will update the latest information about your chart repository. To do this run the following command:

      Now, you'll deploy the Docker registry chart with this custom configuration via Helm by running:

      • helm install stable/docker-registry -f chart_values.yaml --name docker-registry

      You'll see the following output:

      Output

      NAME: docker-registry ... NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/ConfigMap NAME DATA AGE docker-registry-config 1 1s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE docker-registry-54df68fd64-l26fb 0/1 ContainerCreating 0 1s ==> v1/Secret NAME TYPE DATA AGE docker-registry-secret Opaque 3 1s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE docker-registry ClusterIP 10.245.131.143 <none> 5000/TCP 1s ==> v1beta1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE docker-registry 0/1 1 0 1s ==> v1beta1/Ingress NAME HOSTS ADDRESS PORTS AGE docker-registry registry.example.com 80, 443 1s NOTES: 1. Get the application URL by running these commands: https://registry.example.com/

      Helm lists all the resources it created as a result of the Docker registry chart deployment. The registry is now accessible from the domain name you specified earlier.

      You've configured and deployed a Docker registry on your Kubernetes cluster. Next, you will test the availability of the newly deployed Docker registry.

      Step 2 — Testing Pushing and Pulling

      In this step, you'll test your newly deployed Docker registry by pushing and pulling images to and from it. Currently, the registry is empty. To have something to push, you need to have an image available on the machine you're working from. Let's use the mysql Docker image.

      Start off by pulling mysql from the Docker Hub:

      Your output will look like this:

      Output

      Using default tag: latest latest: Pulling from library/mysql 27833a3ba0a5: Pull complete ... e906385f419d: Pull complete Digest: sha256:a7cf659a764732a27963429a87eccc8457e6d4af0ee9d5140a3b56e74986eed7 Status: Downloaded newer image for mysql:latest

      You now have the image available locally. To inform Docker where to push it, you'll need to tag it with the host name, like so:

      • sudo docker tag mysql registry.example.com/mysql

      Then, push the image to the new registry:

      • sudo docker push registry.example.com/mysql

      This command will run successfully and indicate that your new registry is properly configured and accepting traffic — including pushing new images. If you see an error, double check your steps against steps 1 and 2.

      To test pulling from the registry cleanly, first delete the local mysql images with the following command:

      • sudo docker rmi registry.example.com/mysql && sudo docker rmi mysql

      Then, pull it from the registry:

      • sudo docker pull registry.example.com/mysql

      This command will take a few seconds to complete. If it runs successfully, that means your registry is working correctly. If it shows an error, double check what you have entered against the previous commands.

      You can list Docker images available locally by running the following command:

      You'll see output listing the images available on your local machine, along with their ID and date of creation.

      Your Docker registry is configured. You've pushed an image to it and verified you can pull it down. Now let's add authentication so only certain people can access the code.

      Step 3 — Adding Account Authentication and Configuring Kubernetes Access

      In this step, you'll set up username and password authentication for the registry using the htpasswd utility.

      The htpasswd utility comes from the Apache webserver, which you can use for creating files that store usernames and passwords for basic authentication of HTTP users. The format of htpasswd files is username:hashed_password (one per line), which is portable enough to allow other programs to use it as well.

      To make htpasswd available on the system, you'll need to install it by running:

      • sudo apt install apache2-utils -y

      Note:
      If you're running this tutorial from a Mac, you'll need to use the following command to make htpasswd available on your machine:

      • docker run --rm -v ${PWD}:/app -it httpd htpasswd -b -c /app/htpasswd_file sammy password

      Create it by executing the following command:

      Add a username and password combination to htpasswd_file:

      • htpasswd -B htpasswd_file username

      Docker requires the password to be hashed using the bcrypt algorithm, which is why we pass the -B parameter. The bcrypt algorithm is a password hashing function based on Blowfish block cipher, with a work factor parameter, which specifies how expensive the hash function will be.

      Remember to replace username with your desired username. When run, htpasswd will ask you for the accompanying password and add the combination to htpasswd_file. You can repeat this command for as many users as you wish to add.

      Now, show the contents of htpasswd_file by running the following command:

      Select and copy the contents shown.

      To add authentication to your Docker registry, you'll need to edit chart_values.yaml and add the contents of htpasswd_file in the htpasswd variable.

      Open chart_values.yaml for editing:

      Find the line that looks like this:

      chart_values.yaml

        htpasswd: ""
      

      Edit it to match the following, replacing htpasswd_file_contents with the contents you copied from the htpasswd_file:

      chart_values.yaml

        htpasswd: |-
          htpasswd_file_contents
      

      Be careful with the indentation, each line of the file contents must have four spaces before it.

      Once you've added your contents, save and close the file.

      To propagate the changes to your cluster, run the following command:

      • helm upgrade docker-registry stable/docker-registry -f chart_values.yaml

      The output will be similar to that shown when you first deployed your Docker registry:

      Output

      Release "docker-registry" has been upgraded. Happy Helming! LAST DEPLOYED: ... NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/ConfigMap NAME DATA AGE docker-registry-config 1 3m8s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE docker-registry-6c5bb7ffbf-ltnjv 1/1 Running 0 3m7s ==> v1/Secret NAME TYPE DATA AGE docker-registry-secret Opaque 4 3m8s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE docker-registry ClusterIP 10.245.128.245 <none> 5000/TCP 3m8s ==> v1beta1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE docker-registry 1/1 1 1 3m8s ==> v1beta1/Ingress NAME HOSTS ADDRESS PORTS AGE docker-registry registry.example.com 159.89.215.50 80, 443 3m8s NOTES: 1. Get the application URL by running these commands: https://registry.example.com/

      This command calls Helm and instructs it to upgrade an existing release, in your case docker-registry, with its chart defined in stable/docker-registry in the chart repository, after applying the chart_values.yaml file.

      Now, you'll try pulling an image from the registry again:

      • sudo docker pull registry.example.com/mysql

      The output will look like the following:

      Output

      Using default tag: latest Error response from daemon: Get https://registry.example.com/v2/mysql/manifests/latest: no basic auth credentials

      It correctly failed because you provided no credentials. This means that your Docker registry authorizes requests correctly.

      To log in to the registry, run the following command:

      • sudo docker login registry.example.com

      Remember to replace registry.example.com with your domain address. It will prompt you for a username and password. If it shows an error, double check what your htpasswd_file contains. You must define the username and password combination in the htpasswd_file, which you created earlier in this step.

      To test the login, you can try to pull again by running the following command:

      • sudo docker pull registry.example.com/mysql

      The output will look similar to the following:

      Output

      Using default tag: latest latest: Pulling from mysql Digest: sha256:f2dc118ca6fa4c88cde5889808c486dfe94bccecd01ca626b002a010bb66bcbe Status: Image is up to date for registry.example.com/mysql:latest

      You've now configured Docker and can log in securely. To configure Kubernetes to log in to your registry, run the following command:

      • sudo kubectl create secret generic regcred --from-file=.dockerconfigjson=/home/sammy/.docker/config.json --type=kubernetes.io/dockerconfigjson

      You will see the following output:

      Output

      secret/regcred created

      This command creates a secret in your cluster with the name regcred, takes the contents of the JSON file where Docker stores the credentials, and parses it as dockerconfigjson, which defines a registry credential in Kubernetes.

      You've used htpasswd to create a login config file, configured the registry to authenticate requests, and created a Kubernetes secret containing the login credentials. Next, you will test the integration between your Kubernetes cluster and registry.

      Step 4 — Testing Kubernetes Integration by Running a Sample Deployment

      In this step, you'll run a sample deployment with an image stored in the in-cluster registry to test the connection between your Kubernetes cluster and registry.

      In the last step, you created a secret, called regcred, containing login credentials for your private registry. It may contain login credentials for multiple registries, in which case you'll have to update the Secret accordingly.

      You can specify which secret Kubernetes should use when pulling containers in the pod definition by specifying imagePullSecrets. This step is necessary when the Docker registry requires authentication.

      You'll now deploy a sample Hello World image from your private Docker registry to your cluster. First, in order to push it, you'll pull it to your machine by running the following command:

      • sudo docker pull paulbouwer/hello-kubernetes:1.5

      Then, tag it by running:

      • sudo docker tag paulbouwer/hello-kubernetes:1.5 registry.example.com/paulbouwer/hello-kubernetes:1.5

      Finally, push it to your registry:

      • sudo docker push registry.example.com/paulbouwer/hello-kubernetes:1.5

      Delete it from your machine as you no longer need it locally:

      • sudo docker rmi registry.example.com/paulbouwer/hello-kubernetes:1.5

      Now, you'll deploy the sample Hello World application. First, create a new file, hello-world.yaml, using your text editor:

      Next, you'll define a Service and an Ingress to make the app accessible to outside of the cluster. Add the following lines, replacing the highlighted lines with your domains:

      hello-world.yaml

      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        name: hello-kubernetes-ingress
        annotations:
          kubernetes.io/ingress.class: nginx
          nginx.ingress.kubernetes.io/rewrite-target: /
      spec:
        rules:
        - host: k8s-test.example.com
          http:
            paths:
            - path: /
              backend:
                serviceName: hello-kubernetes
                servicePort: 80
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: hello-kubernetes
      spec:
        type: NodePort
        ports:
        - port: 80
          targetPort: 8080
        selector:
          app: hello-kubernetes
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: hello-kubernetes
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: hello-kubernetes
        template:
          metadata:
            labels:
              app: hello-kubernetes
          spec:
            containers:
            - name: hello-kubernetes
              image: registry.example.com/paulbouwer/hello-kubernetes:1.5
              ports:
              - containerPort: 8080
            imagePullSecrets:
            - name: regcred
      

      First, you define the Ingress for the Hello World deployment, which you will route through the Load Balancer that the Nginx Ingress Controller owns. Then, you define a service that can access the pods created in the deployment. In the actual deployment spec, you specify the image as the one located in your registry and set imagePullSecrets to regcred, which you created in the previous step.

      Save and close the file. To deploy this to your cluster, run the following command:

      • kubectl apply -f hello-world.yaml

      You'll see the following output:

      Output

      ingress.extensions/hello-kubernetes-ingress created service/hello-kubernetes created deployment.apps/hello-kubernetes created

      You can now navigate to your test domain — the second A record, k8s-test.example.com in this tutorial. You will see the Kubernetes Hello world! page.

      Hello World page

      The Hello World page lists some environment information, like the Linux kernel version and the internal ID of the pod the request was served from. You can also access your Space via the web interface to see the images you've worked with in this tutorial.

      If you want to delete this Hello World deployment after testing, run the following command:

      • kubectl delete -f hello-world.yaml

      You've created a sample Hello World deployment to test if Kubernetes is properly pulling images from your private registry.

      Conclusion

      You have now successfully deployed your own private Docker registry on your DigitalOcean Kubernetes cluster, using DigitalOcean Spaces as the storage layer underneath. There is no limit to how many images you can store, Spaces can extend infinitely, while at the same time providing the same security and robustness. In production, though, you should always strive to optimize your Docker images as much as possible, take a look at the How To Optimize Docker Images for Production tutorial.



      Source link

      How To Set Up a Private Docker Registry on Ubuntu 18.04


      The author selected the Apache Software Foundation to receive a donation as part of the Write for DOnations program.

      Introduction

      Docker Registry is an application that manages storing and delivering Docker container images. Registries centralize container images and reduce build times for developers. Docker images guarantee the same runtime environment through virtualization, but building an image can involve a significant time investment. For example, rather than installing dependencies and packages separately to use Docker, developers can download a compressed image from a registry that contains all of the necessary components. Furthermore, developers can automate pushing images to a registry using continuous integration tools, such as TravisCI, to seamlessly update images during production and development.

      Docker also has a free public registry, Docker Hub, that can host your custom Docker images, but there are situations where you will not want your image to be publicly available. Images typically contain all the code necessary to run an application, so using a private registry is preferable when using proprietary software.

      In this tutorial, you will set up and secure your own private Docker Registry. You will use Docker Compose to define configurations to run your Docker applications and Nginx to forward server traffic from HTTPS to the running Docker container. Once you’ve completed this tutorial, you will be able to push a custom Docker image to your private registry and pull the image securely from a remote server.

      Prerequisites

      Before you begin this guide, you’ll need the following:

      • Two Ubuntu 18.04 servers set up by following the Ubuntu 18.04 initial server setup guide, including a sudo non-root user and a firewall. One server will host your private Docker Registry and the other will be your client server.
      • Docker and Docker-Compose installed on both servers by following the How to Install Docker-Compose on Ubuntu 18.04 tutorial. You only need to complete the first step of this tutorial to install Docker Compose. This tutorial explains how to install Docker as part of its prerequisites.
      • Nginx installed on your private Docker Registry server by following the How to Install Nginx on Ubuntu 18.04.
      • Nginx secured with Let’s Encrypt on your server for the private Docker Registry, by following How to Secure Nginx With Let’s Encrypt. Make sure to redirect all traffic from HTTP to HTTPS in Step 4.
      • A domain name that resolves to the server you’re using for the private Docker Registry. You will set this up as part of the Let’s Encrypt prerequisite.

      Step 1 — Installing and Configuring the Docker Registry

      The Docker command line tool is useful for starting and managing one or two Docker containers, but, for full deployment most applications running inside Docker containers require other components to be running in parallel. For example, a lot of web applications consist of a web server, like Nginx, that serves up the application’s code, an interpreted scripting language such as PHP, and a database server like MySQL.

      With Docker Compose, you can write one .yml file to set up each container’s configuration and the information the containers need to communicate with each other. You can then use the docker-compose command line tool to issue commands to all the components that make up your application.

      Docker Registry is itself an application with multiple components, so you will use Docker Compose to manage your configuration. To start an instance of the registry, you’ll set up a docker-compose.yml file to define the location where your registry will be storing its data.

      On the server you have created to host your private Docker Registry, you can create a docker-registry directory, move into it, and then create a data subfolder with the following commands:

      • mkdir ~/docker-registry && cd $_
      • mkdir data

      Use your text editor to create the docker-compose.yml configuration file:

      Add the following content to the file, which describes the basic configuration for a Docker Registry:

      docker-compose.yml

      version: '3'
      
      services:
        registry:
          image: registry:2
          ports:
          - "5000:5000"
          environment:
            REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
          volumes:
            - ./data:/data
      

      The environment section sets an environment variable in the Docker Registry container with the path /data. The Docker Registry application checks this environment variable when it starts up, and as a result begins to save its data to the /data folder.

      However, as you have included the volumes: - ./data:/data line, Docker will start to map the /data directory in that container to /data on your registry server. The end result is that the Docker Registry's data all gets stored in ~/docker-registry/data on the registry server.

      The ports section, with configuration 5000:5000, tells Docker to map port 5000 on the server to port 5000 in the running container. This allows you to send a request to port 5000 on the server, and have the request forwarded to the registry application.

      You can now start Docker Compose to check the setup:

      You will see download bars in your output that show Docker downloading the Docker Registry image from Docker's own registry. Within a minute or two, you'll see output that looks similar to the following (versions might vary):

      Output of docker-compose up

      Starting docker-registry_registry_1 ... done Attaching to docker-registry_registry_1 registry_1 | time="2018-11-06T18:43:09Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="redis not configured" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="Starting upload purge in 20m0s" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="listening on [::]:5000" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2

      You'll address the No HTTP secret provided warning message later in this tutorial. The output shows that the container is starting. The last line of the output shows it has successfully started listening on port 5000.

      By default, Docker Compose will remain waiting for your input, so hit CTRL+C to shut down your Docker Registry container.

      You have set up a full Docker Registry listening on port 5000. At this point the registry won't start unless you bring it up manually. Also, Docker Registry doesn't come with any built-in authentication mechanism, so it is currently insecure and completely open to the public. In the following steps, you will address these security concerns.

      Step 2 — Setting Up Nginx Port Forwarding

      You already have HTTPS set up on your Docker Registry server with Nginx, which means you can now set up port forwarding from Nginx to port 5000. Once you complete this step, you can access your registry directly at example.com.

      As part of the How to Secure Nginx With Let's Encrypt prerequisite, you have already set up the /etc/nginx/sites-available/example.com file containing your server configuration.

      Open this file with your text editor:

      • sudo nano /etc/nginx/sites-available/example.com

      Find the existing location line. It will look like this:

      /etc/nginx/sites-available/example.com

      ...
      location / {
        ...
      }
      ...
      

      You need to forward traffic to port 5000, where your registry will be running. You also want to append headers to the request to the registry, which provide additional information from the server with each request and response. Delete the contents of the location section, and add the following content into that section:

      /etc/nginx/sites-available/example.com

      ...
      location / {
          # Do not allow connections from docker 1.5 and earlier
          # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
          if ($http_user_agent ~ "^(docker/1.(3|4|5(?!.[0-9]-dev))|Go ).*$" ) {
            return 404;
          }
      
          proxy_pass                          http://localhost:5000;
          proxy_set_header  Host              $http_host;   # required for docker client's sake
          proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
          proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
          proxy_set_header  X-Forwarded-Proto $scheme;
          proxy_read_timeout                  900;
      }
      ...
      

      The $http_user_agent section verifies that the Docker version of the client is above 1.5, and ensures that the UserAgent is not a Go application. Since you are using version 2.0 of the registry, older clients are not supported. For more information, you can find the nginx header configuration in Docker's Registry Nginx guide.

      Save and exit the file. Apply the changes by restarting Nginx:

      • sudo service nginx restart

      You can confirm that Nginx is forwarding traffic to port 5000 by running the registry:

      • cd ~/docker-registry
      • docker-compose up

      In a browser window, open up the following url:

      https://example.com/v2
      

      You will see an empty JSON object, or:

      {}
      

      In your terminal, you'll see output similar to the following:

      Output of docker-compose up

      registry_1 | time="2018-11-07T17:57:42Z" level=info msg="response completed" go.version=go1.7.6 http.request.host=cornellappdev.com http.request.id=a8f5984e-15e3-4946-9c40-d71f8557652f http.request.method=GET http.request.remoteaddr=128.84.125.58 http.request.uri="/v2/" http.request.useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.125995ms http.response.status=200 http.response.written=2 instance.id=3093e5ab-5715-42bc-808e-73f310848860 version=v2.6.2 registry_1 | 172.18.0.1 - - [07/Nov/2018:17:57:42 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7"

      You can see from the last line that a GET request was made to /v2/, which is the endpoint you sent a request to from your browser. The container received the request you made, from the port forwarding, and returned a response of {}. The code 200 in the last line of the output means that the container handled the request successfully.

      Now that you have set up port forwarding, you can move on to improving the security of your registry.

      Step 3 — Setting Up Authentication

      With Nginx proxying requests properly, you can now secure your registry with HTTP authentication to manage who has access to your Docker Registry. To achieve this, you'll create an authentication file with htpasswd and add users to it. HTTP authentication is quick to set up and secure over a HTTPS connection, which is what the registry will use.

      You can install the htpasswd package by running the following:

      • sudo apt install apache2-utils

      Now you'll create the directory where you'll store our authentication credentials, and change into that directory. $_ expands to the last argument of the previous command, in this case ~/docker-registry/auth:

      • mkdir ~/docker-registry/auth && cd $_

      Next, you will create the first user as follows, replacing username with the username you want to use. The -B flag specifies bcrypt encryption, which is more secure than the default encryption. Enter the password when prompted:

      • htpasswd -Bc registry.password username

      Note: To add more users, re-run the previous command without the -c option, (the c is for create):

      • htpasswd registry.password username

      Next, you'll edit the docker-compose.yml file to tell Docker to use the file you created to authenticate users.

      • cd ~/docker-registry
      • nano docker-compose.yml

      You can add environment variables and a volume for the auth/ directory that you created, by editing the docker-compose.yml file to tell Docker how you want to authenticate users. Add the following highlighted content to the file:

      docker-compose.yml

      version: '3'
      
      services:
        registry:
          image: registry:2
          ports:
          - "5000:5000"
          environment:
            REGISTRY_AUTH: htpasswd
            REGISTRY_AUTH_HTPASSWD_REALM: Registry
            REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
            REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
          volumes:
            - ./auth:/auth
            - ./data:/data
      

      For REGISTRY_AUTH, you have specified htpasswd, which is the authentication scheme you are using, and set REGISTRY_AUTH_HTPASSWD_PATH to the path of the authentication file. Finally, REGISTRY_AUTH_HTPASSWD_REALM signifies the name of htpasswd realm.

      You can now verify that your authentication works correctly, by running the registry and checking that it prompts users for a username and password.

      In a browser window, open https://example.com/v2.

      After entering username and the corresponding password, you will see {} once again. You've confirmed the basic authentication setup: the registry only returned the result after you entered the correct username and password. You have now secured your registry, and can continue to using the registry.

      Step 4 — Starting Docker Registry as a Service

      You want to ensure that your registry will start whenever the system boots up. If there are any unforeseen system crashes, you want to make sure the registry restarts when the server reboots. Open up docker-compose.yml:

      Add the following line of content under registry::

      docker-compose.yml

      ...
        registry:
          restart: always
      ...
      

      You can start your registry as a background process, which will allow you to exit the ssh session and persist the process:

      With your registry running in the background, you can now prepare Nginx for file uploads.

      Step 5 — Increasing File Upload Size for Nginx

      Before you can push an image to the registry, you need to ensure that your registry will be able to handle large file uploads. Although Docker splits large image uploads into separate layers, they can sometimes be over 1GB. By default, Nginx has a limit of 1MB on file uploads, so you need to edit the configuration file for nginx and set the max file upload size to 2GB.

      • sudo nano /etc/nginx/nginx.conf

      Find the http section, and add the following line:

      /etc/nginx/nginx.conf

      ...
      http {
              client_max_body_size 2000M;
              ...
      }
      ...
      

      Finally, restart Nginx to apply the configuration changes:

      • sudo service nginx restart

      You can now upload large images to your Docker Registry without Nginx errors.

      Step 6 — Publishing to Your Private Docker Registry

      You are now ready to publish an image to your private Docker Registry, but first you have to create an image. For this tutorial, you will create a simple image based on the ubuntu image from Docker Hub. Docker Hub is a publicly hosted registry, with many pre-configured images that can be leveraged to quickly Dockerize applications. Using the ubuntu image, you will test pushing and pulling to your registry.

      From your client server, create a small, empty image to push to your new registry, the -i and -t flags give you interactive shell access into the container:

      • docker run -t -i ubuntu /bin/bash

      After it finishes downloading you'll be inside a Docker prompt, note that your container ID following root@ will vary. Make a quick change to the filesystem by creating a file called SUCCESS. In the next step, you'll be able to use this file to determine whether the publishing process is successful:

      Exit out of the Docker container:

      The following command creates a new image called test-image based on the image already running plus any changes you have made. In our case, the addition of the /SUCCESS file is included in the new image.

      Commit the change:

      • docker commit $(docker ps -lq) test-image

      At this point, the image only exists locally. Now you can push it to the new registry you have created. Log in to your Docker Registry:

      • docker login https://example.com

      Enter the username and corresponding password from earlier. Next, you will tag the image with the private registry's location in order to push to it:

      • docker tag test-image example.com/test-image

      Push the newly tagged image to the registry:

      • docker push example.com/test-image

      Your output will look similar to the following:

      Output

      The push refers to a repository [example.com/test-image] e3fbbfb44187: Pushed 5f70bf18a086: Pushed a3b5c80a4eba: Pushed 7f18b442972b: Pushed 3ce512daaf78: Pushed 7aae4540b42d: Pushed ...

      You've verified that your registry handles user authentication, and allows authenticated users to push images to the registry. Next, you will confirm that you are able to pull images from the registry as well.

      Step 7 — Pulling From Your Private Docker Registry

      Return to your registry server so that you can test pulling the image from your client server. It is also possible to test this from a third server.

      Log in with the username and password you set up previously:

      • docker login https://example.com

      You're now ready to pull the image. Use your domain name and image name, which you tagged in the previous step:

      • docker login example.com/test-image

      Docker will download the image and return you to the prompt. If you run the image on the registry server you'll see the SUCCESS file you created earlier is there:

      • docker run -it example.com/test-image /bin/bash

      List your files inside the bash shell:

      You will see the SUCCESS file you created for this image:

      SUCCESS  bin  boot  dev  etc  home  lib  lib64  media   mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
      

      You've finished setting up a secure registry to which users can push and pull custom images.

      Conclusion

      In this tutorial you set up your own private Docker Registry, and published a Docker image. As mentioned in the introduction, you can also use TravisCI or a similar CI tool to automate pushing to a private registry directly. By leveraging Docker and registries into your workflow, you can ensure that the image containing the code will result in the same behavior on any machine, whether in production or in development. For more information on writing Docker files, you can read this Docker tutorial explaining the process.



      Source link