Deploying a self-hosted Android Ci Solution with Drone & Gogs (Pt.4 - Registry)

Pre-flight:

At this point the following should be done:

  • Drone is set up and running.
  • Nginx is working without issues.
  • Docker is running without crashing and setup properly.
  • You've build the Android CI Image to be used with Docker.

Finally we can setup our registry so that we can push our image that will be used by Drone with each ci build.

This part requires the user be root. Some commands simply don't work with sudo, so this is the only part of the guide you really need to be root.

Let's go

Docker Registry deployment:

  • Create your docker registry directory:
mkdir /docker-registry/

  • Create the data directory within the registry as this is needed:
mkdir /docker-registry/data

  • You can chown the docker-registry directory so you don't need to elevate to root when you need to work in it should you ever need to:
chown -R myuser:myuser  /docker-registry/
  • Write up your docker-compose.yml file that will configure the registry container:
vi mkdir /docker-registry/docker-compose.yml

Add the below contents:


registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

  • Save and exit the file

  • Create the Unit file that will control the docker registry service:

 sudo vi /etc/systemd/system/docker-reg.service

  • Now put the below contents in there:
[Unit]
Description=Docker Registry Service
After=docker.service nginx.service

[Service]
Restart=always
ExecStart=/usr/local/bin/docker-compose -f /docker-registry/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /docker-registry/docker-compose.yml stop

[Install]
WantedBy=multi-user.target

  • Start your docker registry by issuing the following command:
systemctl status dregistry

Using your ssl cert with docker registry on local or remote do the following:

  • cat your cert file (also works with letsencrypt) (you also need to do this as root):
# cd /etc/letsencrypt/live/<your cert dir>/cert.pem

  • Copy the contents that look like this:

-----BEGIN CERTIFICATE-----
MIIFIz....

....kJ0byqGGmcYfiH8x+nXAlnA=
-----END CERTIFICATE-----

  • Then then make a directory such as the below:
mkdir /usr/local/share/ca-certificates/docker-dev-cert/

  • Create the cert file:
vi /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

  • Paste the above cert contents, then run the following command:
sudo update-ca-certificates

  • Restart Docker so that it picks up the new cert:
sudo systemctl restart docker

  • Just make sure all services that belong to docker are running by issuing the following commands:
sudo  systemctl status drone
sudo  systemctl status docker-reg

  • Enable these services on system startup should you need to reboot at some point:
# We build all the time!

~$ sudo systemctl enable drone
Created symlink from /etc/systemd/system/multi-user.target.wants/drone.service to /etc/systemd/system/drone.service.

~$ sudo systemctl enable docker-reg
Created symlink from /etc/systemd/system/multi-user.target.wants/dregistry.service to /etc/systemd/system/dregistry.service.
 

In order to push images:

  • Remember the credentials you used when dealing with nginx? you need these here. Login to your registry first with those creds:
docker login https://registry.example.net
Username: your_user
Password:
Login Succeeded
  • Then tag the image you built earlier:
docker tag androidbuilder registry.yourdomain.net/android-image-sdk-27
  • if you've logged in successfully, you should be able to push the image once tagged:
[email protected]:/docker-registry$ docker push registry.yourdomain.net/android-image-sdk-27
The push refers to repository [registry.yourdomain.net/android-image-sdk-27]
e1229e6dcbbc: Pushing [=============>                                     ]  181.1MB/677.1MB
f9f6e6b71edd: Pushing [===========================================>       ]  213.8MB/246.4MB
e5ee1ef60d62: Pushing [===============================>                   ]  438.7MB/691.2MB
59839856c7d9: Pushed
dcef88dfed7e: Pushing [==================================================>]  296.1MB
6774e2ecce7d: Pushed
e48845e06286: Pushed
875b1eafb4d0: Pushed
7ce1a454660d: Pushing [===================>                               ]  176.4MB/461.2MB
d3b195003fcc: Pushed
92bd1433d7c5: Pushing [==================================================>]  3.584kB
f0ed7f14cbd1: Waiting
b31411566900: Waiting
06f4de5fefea: Waiting
851f3e348c69: Waiting
e27a10675c56: Waiting

Something to watch out for

You may end up getting hit with this error during push:

error parsing HTTP 413 response body: invalid character '<' looking for beginning of value: "<html>\r\n<head><title>413 Request Entity Too Large</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>413 Request Entity Too Large</h1></center>\r\n<hr><center>cloudflare-nginx</center>\r\n</body>\r\n</html>\r\n"

This is an nginx issue where the upload size is limited.

Firstly double check that the following is done in our server block for the registry config:

client_max_body_size 0;

One more thing to note. If you're using Cloudflare (and you should be) , you will have to put a manual hosts entry for your registry server. This is because even though your client_max_body_size is 0, cloudflare doesn't allow big client upload sizes. Not too sure what the actual allowed size is, but we can get around this by essentially telling our server the real server ip for the registry rather than rely on domain name, as that will ultimately point to cloudflare.

Once all this is done, you should be able to have successully pushed an image to your registry server:

[email protected]:/docker-registry$ docker push registry.yourdomain.net/android-image-sdk-27
The push refers to repository [registry.yourdomain.net/android-image-sdk-27]
e1229e6dcbbc: Pushed
f9f6e6b71edd: Pushed
e5ee1ef60d62: Pushed
59839856c7d9: Layer already exists
dcef88dfed7e: Pushed
6774e2ecce7d: Layer already exists
e48845e06286: Layer already exists
875b1eafb4d0: Layer already exists
7ce1a454660d: Pushed
d3b195003fcc: Layer already exists
92bd1433d7c5: Layer already exists
f0ed7f14cbd1: Layer already exists
b31411566900: Layer already exists
06f4de5fefea: Layer already exists
851f3e348c69: Layer already exists
e27a10675c56: Layer already exists
latest: digest: sha256:e5c4376820bb4edbd0dab5319c256ccd5b299b09377303389274bbeed96c281d size: 3696

You've successfully deployed a ci server using drone + docker!

What's nice about this is that after each build, your android container will be killed and started as and when a build is needed. in the next few posts we will go over:

  • How the UI works.
  • How to login to your registry through Drone.
  • Setting up gogs to work with Drone (from the gogs side)

However if you've made it this far, congrats! You should be proud of yourself. The terminal can get tiring if you've never done anything sys-adminy before so definitely a pat on the back and your favourite poison.

A lot of the information here was made possible from the below links:

Vusi Moyo

Some guy that found code on the internet and is treating it like play dough

Read More