I’ll have to admit it, I absolutely love Kubernetes! Having the ability to deploy a close to full environment on my local machine is a real treat. You can hone your deployment recipes and configurations along with your code from the Get-go.

That said, there is a bit of a pain point currently. Having to push Docker images to a remote registry to later download them back to my local machine is a royal pain in the ass. What I would rather have, is a local Docker Registry that both Docker and Kubernetes know about and from which I can push/pull my Docker images .

The following walks you thru on how to achieve this and hopefully makes your local dev K8s adventures a little bit more sane…

  1. Docker Registry Deployment

    The first thing we need to do is define a K8s deployment for our local Docker registry. For this we will use the official Docker image.

     # configs/registry/dp.yml
     kind:       Deployment
     apiVersion: extensions/v1beta1
     metadata:
       name: registry
       labels:
         app: registry
     spec:
       replicas: 1
       template:
         metadata:
           labels:
             app: registry
         spec:
           containers:
             - name:  registry
               image: docker.io/registry:2
               ports:
                 - containerPort: 5000
                   name:          client
    
  2. Docker Registry Service

    Next, we define a service to front our registry. Node that we are making this service externally available so we can access it from our localhost.

     # configs/registry/svc.yml
     kind:       Service
     apiVersion: v1
     metadata:
       name: registry
       labels:
         app: registry
     spec:
       type: LoadBalancer
       selector:
         app: registry
       ports:
         - name:       client
           port:       5000
           targetPort: client
     status:
       loadBalancer:
         ingress:
           - ip: 0.0.0.0
    
  3. Deploy!

    Now let’s schedule our recipes.

     ku create -f config/registry/dp.yml -f config/registry/svc.yml
    
  4. Retrieve Docker Registry Service Host/Port

    Next, we need to record our registry service NodePort and Vagrant minion IP. Let’s assume the NodePort will be 30123 and our Vagrant minion IP is 10.10.10.1

    ku describe svc registry | grep NodePort
    ku describe no | grep Address
    
  5. Configure Your DockerMachine

    The Docker registry should be up and running and accessible from our localhost. The key now is to tell docker-machine to use that registry instead of the default.

    # Create a new machine using your own Docker registry
    docker-machine create --driver virtualbox --engine-insecure-registry 10.10.10.1:30123 k8s
    
  6. Building And Pushing Our Service Image

    Say we have our coolio Blee service for which we’ve have an associated Dockerfile. We need to push our service image to our new K8s registry.

    # Switch to your new docker machine
    eval $(docker-machine env k8s)
    # Build and tag your image
    docker build -f Dockerfile --rm -t 10.10.10.1:30123/blee:0.0.1 .
    # Publish image to your own registry
    docker push 10.10.10.1:30123/blee
    # List out your new image
    docker images
    
  7. Create Your New Service Deployment

    Next, we will define a deployment for our Blee service and tell Kubernetes to use the image from our own Docker registry.

    #configs/blee/dp/yml
    kind:       Deployment
     apiVersion: extensions/v1beta1
     metadata:
       name: blee
       labels:
         app: blee
    spec:
       replicas: 1
       template:
         metadata:
           labels:
             app: blee
         spec:
           containers:
             - name:  blee
               image: 10.10.10.1:30123/blee:0.0.1
               ports:
                 - containerPort: 3500
                   name:          client
    

    Now deploy it!

    ku create -f configs/blee/dp.yml
    
  8. All Done!

    We can now test out our new service, tweak the image and deployment, perform rolling update with a great rate of speed and convenience. No longer do we need to hang out while the image is being pulled or pushed. We can rinse and repeat this process to our heart content til we get it just right. Once satisfied with our image and k8s recipes, we can officially deploy to our favorite external Docker hub and prepare for mass consumption!