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
alpine
image, it expands it intolibrary/alpine
library/alpine
is expanded intoindex.docker.io/library/alpine
The Engine communicates with
index.docker.io
to retrievelibrary/alpine:latest
To 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 build
or 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
registry
containerIt 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:xxxxx
on 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=registry
Expose 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/registry
Get 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/busybox
Push 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
stacks
directory:cd ~/container.training/stacks
Build 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
latest
The 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
latest
tag, 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
curl
command 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.1
The full image names are therefore:
dockercoins/hasher:v0.1
dockercoins/rng:v0.1
dockercoins/webui:v0.1
dockercoins/worker:v0.1
Setting $REGISTRY
and $TAG
In the upcoming exercises and labs, we use a couple of environment variables:
$REGISTRY
as a prefix to all image names$TAG
as the image version tag
For example, the worker image is
$REGISTRY/worker:$TAG
If you copy-paste the commands in these exercises:
make sure that you set
$REGISTRY
and$TAG
first!For example:
export REGISTRY=dockercoins TAG=v0.1
(this will expand
$REGISTRY/worker:$TAG
todockercoins/worker:v0.1
)