Shipping images with a registry
- 1. Introduction
- 2. Self-hosting our registry
- 3. Using images from the Docker Hub
1. Introduction
Initially, our app was running on a single node
We could build and run in the same place
Therefore, we did not need to ship anything
Now that we want to run on a cluster, things are different
The easiest way to ship container images is to use a registry
How Docker registries work (a reminder)
What happens when we execute
docker run alpine?If the Engine needs to pull the
alpineimage, it expands it intolibrary/alpinelibrary/alpineis expanded intoindex.docker.io/library/alpineThe Engine communicates with
index.docker.ioto retrievelibrary/alpine:latestTo use something else than
index.docker.io, we specify it in the image nameExamples:
docker pull gcr.io/google-containers/alpine-with-bash:1.0 docker build -t registry.mycompany.io:5000/myimage:awesome . docker push registry.mycompany.io:5000/myimage:awesome
Running DockerCoins on Kubernetes
Create one deployment for each component
(hasher, redis, rng, webui, worker)
Expose deployments that need to accept connections
(hasher, redis, rng, webui)
For redis, we can use the official redis image
For the 4 others, we need to build images and push them to some registry
Building and shipping images
There are many options!
Manually:
build locally (with
docker buildor otherwise)push to the registry
Automatically:
build and test locally
when ready, commit and push a code repository
the code repository notifies an automated build system
that system gets the code, builds it, pushes the image to the registry
Which registry do we want to use?
There are SAAS products like Docker Hub, Quay ...
Each major cloud provider has an option as well
(ACR on Azure, ECR on AWS, GCR on Google Cloud...)
There are also commercial products to run our own registry
(Docker EE, Quay...)
And open source options, too!
When picking a registry, pay attention to its build system
(when it has one)
2. Self-hosting our registry
Note: this section shows how to run the Docker open source registry and use it to ship images on our cluster. While this method works fine, we recommend that you consider using one of the hosted, free automated build services instead. It will be much easier!
If you need to run a registry on premises, this section gives you a starting point, but you will need to make a lot of changes so that the registry is secured, highly available, and so that your build pipeline is automated.
Using the open source registry
We need to run a
registrycontainerIt will store images and layers to the local filesystem
(but you can add a config file to use S3, Swift, etc.)Docker requires TLS when communicating with the registry
unless for registries on
127.0.0.0/8(i.e.localhost)or with the Engine flag
--insecure-registry
Our strategy: publish the registry container on a NodePort,
so that it's available through127.0.0.1:xxxxxon each node
Deploying a self-hosted registry
- We will deploy a registry container, and expose it with a NodePort
Exercise
Create the registry service:
kubectl create deployment registry --image=registryExpose it on a NodePort:
kubectl expose deploy/registry --port=5000 --type=NodePort
Connecting to our registry
- We need to find out which port has been allocated
Exercise
View the service details:
kubectl describe svc/registryGet the port number programmatically:
NODEPORT=$(kubectl get svc/registry -o json | jq .spec.ports[0].nodePort) REGISTRY=127.0.0.1:$NODEPORT
Testing our registry
- A convenient Docker registry API route to remember is
/v2/_catalog
Exercise
View the repositories currently held in our registry:
curl $REGISTRY/v2/_catalog
We should see:
{"repositories":[]}
Testing our local registry
- We can retag a small image, and push it to the registry
Exercise
Make sure we have the busybox image, and retag it:
docker pull busybox docker tag busybox $REGISTRY/busyboxPush it:
docker push $REGISTRY/busybox
Checking again what's on our local registry
- Let's use the same endpoint as before
Exercise
- Ensure that our busybox image is now in the local registry:
curl $REGISTRY/v2/_catalog
The curl command should now output:
{"repositories":["busybox"]}
Building and pushing our images
- We are going to use a convenient feature of Docker Compose
Exercise
Go to the
stacksdirectory:cd ~/container.training/stacksBuild and push the images:
export REGISTRY export TAG=v0.1 docker-compose -f dockercoins.yml build docker-compose -f dockercoins.yml push
Let's have a look at the dockercoins.yml file while this is building and pushing.
version: "3"
services:
rng:
build: dockercoins/rng
image: ${REGISTRY-127.0.0.1:5000}/rng:${TAG-latest}
deploy:
mode: global
...
redis:
image: redis
...
worker:
build: dockercoins/worker
image: ${REGISTRY-127.0.0.1:5000}/worker:${TAG-latest}
...
deploy:
replicas: 10
Just in case you were wondering ... Docker "services" are not Kubernetes "services".
Avoiding the latest tag
Make sure that you've set the TAG variable properly!
If you don't, the tag will default to
latestThe problem with
latest: nobody knows what it points to!the latest commit in the repo?
the latest commit in some branch? (Which one?)
the latest tag?
some random version pushed by a random team member?
If you keep pushing the
latesttag, how do you roll back?Image tags should be meaningful, i.e. correspond to code branches, tags, or hashes
Checking the content of the registry
- All our images should now be in the registry
Exercise
Re-run the same
curlcommand as earlier:curl $REGISTRY/v2/_catalog
In these slides, all the commands to deploy DockerCoins will use a $REGISTRY environment variable, so that we can quickly switch from the self-hosted registry to pre-built images hosted on the Docker Hub. So make sure that this $REGISTRY variable is set correctly when running the exercises!
3. Using images from the Docker Hub
For everyone's convenience, we took care of building DockerCoins images
We pushed these images to the DockerHub, under the dockercoins user
These images are tagged with a version number,
v0.1The full image names are therefore:
dockercoins/hasher:v0.1dockercoins/rng:v0.1dockercoins/webui:v0.1dockercoins/worker:v0.1
Setting $REGISTRY and $TAG
In the upcoming exercises and labs, we use a couple of environment variables:
$REGISTRYas a prefix to all image names$TAGas the image version tag
For example, the worker image is
$REGISTRY/worker:$TAGIf you copy-paste the commands in these exercises:
make sure that you set
$REGISTRYand$TAGfirst!For example:
export REGISTRY=dockercoins TAG=v0.1(this will expand
$REGISTRY/worker:$TAGtodockercoins/worker:v0.1)