Store privately your container images in Telefónica Open Cloud

Fernando de la Iglesia
7 min readOct 27, 2017

by Fernando de la Iglesia, Technology Expert at Telefónica I+D

Following the suggestion from Jose manuel de arce on my previous post

I would like to show with a very simple example how to create and upload to Docker Hub a container image to be used to create applications in our Open Cloud CCE cluster. Moreover, taking advantage of the suggestion I will show how to upload and store images privately in the Open Cloud CCE private registry.

Creating the container image for your application

In order to be able to create a container image you need to work in some environment running docker. Of course you can use and login in some of the nodes of your CCE cluster or you can use a docker environment installed in your laptop. For many purposes as image creation, I use Docker Toolbox installed in my Windows laptop.

It is very easy to find how to create a container image in the Internet. As an example, let us create a simple image for running a node.js web server. First, you need to create the file containing the code for your application, in our case a simple web server

$ cat server.js
'use strict';
const express = require('express');// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
// App
const app = express();
app.get('/', (req, res) => {
res.send('Hello world<br>This is a very simple example\n');
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

In this case, the application requires the package express as you can see in the second line of code; therefore, you need to describe this dependency in the corresponding package.json file

$ cat package.json
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "Fernando de la Iglesia <https://medium.com/@fernando.delaiglesia>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.13.3"
}
}

Finally for the container image creation you need to create a file called Dockerfile describing the source image to come from (in this case, obviously, an image containing the Node.js framework) as well as what files to copy to the new image and what actions to execute at image creation

$ cat Dockerfile
FROM node:8.7
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json .
RUN npm install# Bundle app source
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]

Great. Now is time to create the image ‘simplenodeweb’

$ ls
Dockerfile package.json server.js
$ docker build -t simplenodeweb .
Sending build context to Docker daemon 5.12 kB
Step 1 : FROM node:8.7
---> badd967af535
Step 2 : WORKDIR /usr/src/app
---> Running in a63375a9e4ab
---> 97f5a0358387
Removing intermediate container a63375a9e4ab
Step 3 : COPY package.json .
---> a7daa9edb6cc
Removing intermediate container 34d0070cfb16
Step 4 : RUN npm install
---> Running in 56748b95501b
npm info it worked if it ends with ok
npm info using npm@5.4.2
npm info using node@v8.7.0
npm info lifecycle docker_web_app@1.0.0~preinstall: docker_web_app@1.0.0
... (a lot of output from the npm install instruction)...
npm info lifecycle undefined~shrinkwrap: undefined
npm notice created a lockfile as package-lock.json. You should commit this file.
npm info lifecycle undefined~postshrinkwrap: undefined
npm WARN docker_web_app@1.0.0 No repository field.
npm WARN docker_web_app@1.0.0 No license field.
added 48 packages in 3.523s
npm info ok
---> 8f2fbaf299bd
Removing intermediate container 56748b95501b
Step 5 : COPY . .
---> b2ed590b10af
Removing intermediate container f24da3a01365
Step 6 : EXPOSE 8080
---> Running in ecbb0935ff90
---> 16d94291956f
Removing intermediate container ecbb0935ff90
Step 7 : CMD npm start
---> Running in a43f4d48af49
---> 960c7920247c
Removing intermediate container a43f4d48af49
Successfully built 960c7920247c
$ docker images
REPOSITORY
TAG IMAGE ID CREATED SIZE
simplenodeweb latest 32b919f875bf About a minute ago 674.5 MB
node 8.7 badd967af535 10 days ago 671.6 MB
busybox latest 54511612f1c4 5 weeks ago 1.129 MB
node boron cb4fff641acf 7 weeks ago 660.2 MB

Push your image to Docker Hub

We are prepared to upload our image to Docker Hub. Using a free account for Docker Hub the images you upload are public that means that any user can discover and use them. The complete guide to push images can be found here, and of course you need an account and prepare your docker environment to use that account to push images. You can find how to prepare the environment in the link provided. Once the environment is prepared, you have to tag your image providing your user account name, in my case fernandodelaiglesia, and after that to push the image. This is an easy task:

$ docker tag simplenodeweb:latest fernandodelaiglesia/simplenodeweb:latest$ docker push fernandodelaiglesia/simplenodeweb:latest
The push refers to a repository [docker.io/fernandodelaiglesia/simplenodeweb]
9d70f494d8fe: Pushed
7059942fce6b: Pushed
eb18664c889f: Pushed
26399bbc5f09: Pushed
e7f6a8a9e92c: Pushed
4cd1cd602ff8: Pushed
7df250eb9e5c: Pushed
e9591a63b7e4: Pushed
d752a0310ee4: Pushed
db64edce4b5b: Pushed
d5d60fc34309: Pushed
c01c63c6823d: Pushed
latest: digest: sha256:484e5573bee35222f9b0ed97651c5f752b4e28df7475381835658abe8d80d124 size: 2839

Superb. Going back to the previous post we can deploy your brand new application in your CCE cluster (see section “Creating your first application”) by creating the Replication Controller (RC) and Service yaml files, and creating the RC and Service objects by using the kubctl tool.

Push you image to the Open Cloud CCE private registry

To have the image in the Docker Hub registry is great, but probably you need to maintain your application and business software private while maintaining the flexibility to deploy it in CCE clusters. That can be achieved using the Open Cloud CCE private registry. The complete instructions for that can be found in the Open Cloud Help Center, and starts by downloading the certificate from the Open Cloud CCE web console as you can see below (by clicking in Upload Container Image button, the menu below including the Download a certificate file link is expanded)

By doing this you obtain the dockercfg file containing something similar to

$ cat dockercfg.txt
{"auths":{"200.29.32.137:443":{"auth":"X2F1dGhfdG9rZW46N2FhNWVhOWU3NzA4NGI1NThlOTk5ZjQ4N2Y3MTM0NTMtNTlNV0dHR0dMM0xOT0ZaTU1PVajarenareEwMjIwNzMyNTEtMzU3NWYwNzUzNWE4YTFjYTdkNzhhNjdjMjIyNGM1ZWM2ZmJjOWNlNmIyY2ZiNjdiMTg3OTg1YTVmMGVkZDZiNg==","email":""}}}

You need to copy the content of this file to the config.json file located in the .docker directory of the operating system user that executes the docker instructions

$ cat config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "ZmVybmFuZG9kZWxhajarenareTohU2VzYW0wIQ=="
},
"200.29.32.137:443":{
"auth":"X2F1dGhfdG9rZW46N2FhNWVhOWU3NzA4NGI1NThlOTk5ZjQ4N2Y3MTM0NTMtNTlNV0dHR0dMM0xOT0ZaTU1PVajarenareEwMjIwNzMyNTEtMzU3NWYwNzUzNWE4YTFjYTdkNzhhNjdjMjIyNGM1ZWM2ZmJjOWNlNmIyY2ZiNjdiMTg3OTg1YTVmMGVkZDZiNg==",
"email":""
}
}
}

and to configure docker to authorize the docker client to access the private container registry following instructions (depending on your operating system) in step 4 of the Open Cloud Help Center we refer to previously.

Now, as we did before for Docker Hub, we have to tag the image and push it. For tagging the image, you have to use the registry and user corresponding to the private registry. OK, the server is just the one that appears in the dockercfg file we downloaded previously. And what about the user? The user is your domain name in Open Cloud, all in lowercase and without spaces. My domain name is TEST_TG_B2B, therefore the tag should be

$ docker tag simplenodeweb:latest 200.29.32.137:443/test_tg_b2b/simplenodeweb

Now we can push the image to the CCE private registry

$ docker push 200.29.32.137:443/test_tg_b2b/simplenodeweb
The push refers to a repository [200.29.32.137:443/test_tg_b2b/simplenodeweb]
9d70f494d8fe: Pushed
7059942fce6b: Pushed
eb18664c889f: Pushed
26399bbc5f09: Pushed
e7f6a8a9e92c: Pushed
4cd1cd602ff8: Pushed
7df250eb9e5c: Pushed
e9591a63b7e4: Pushed
d752a0310ee4: Pushed
db64edce4b5b: Pushed
d5d60fc34309: Pushed
c01c63c6823d: Pushed
latest: digest: sha256:78854bfcb6f446a740f60d4bbe9ec06ab2ead818eb4a6e62022fdf63da091be2 size: 2839

That’s great!. Time to deploy your application in your CCE cluster from the private registry. Following the previous post, we create the RC and Service yaml files

$ cat simplenode-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: simplenode
spec:
replicas: 1
selector:
app: simplenode
template:
metadata:
name: simplenode
labels:
app: simplenode
spec:
containers:
- name: simplenode
image: 200.29.32.137:443/test_tg_b2b/simplenodeweb
ports:
- containerPort: 8080
name: node-port
imagePullSecrets:
- name: myregistry
$ cat simplenode-service.yaml
apiVersion: v1
kind: Service
metadata:
name: simplenode
labels:
apps: simplenode
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
protocol: TCP
selector:
app: simplenode

Note the differences with respect to the original Replication Controller in the previous post. First image is pointing to the image we just uploaded to the private registry, and second, we have to add the imagePullSecrets section. The secret object used in the imagePullSecrets is authomatically configured for you in the CCE cluster.

The next task is to create the Replication Controller and the Service as usual

$ kubectl create -f simplenode-rc.yaml
replicationcontroller "simplenode" created
$ kubectl create -f simplenode-service.yaml
service "simplenode" created
$ kubectl get rc
NAME DESIRED CURRENT READY AGE
simplenode 1 1 1 1m
tomcat 3 3 3 48d
web 1 1 1 25d
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.247.0.1 <none> 443/TCP 88d
simplenode 10.247.185.245 <nodes> 8080:30068/TCP 8s
tomcat 10.247.182.156 <nodes> 8080:31500/TCP 48d
web 10.247.207.66 <nodes> 80:30999/TCP 25d

and of course to access to the service

$ curl -i http://200.29.XXX.XXX:30068/
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 45
ETag: W/"2d-xUePkkhYSerb0p3OaM1vlVwkBwg"
Date: Mon, 23 Oct 2017 12:41:08 GMT
Connection: keep-alive
Hello world<br>This is a very simple example

Wow! Now you can make your business grow with Telefónica Open Cloud CCE service, and in addition to store your business software privately in the private register provided by CCE to deploy it when needed.

--

--

Fernando de la Iglesia

I love to learn, specially how nature works, and this is why I studied physics and love quantum “things”.