As I detailed in my previous post Oracle Always Free Cloud instances in HA configuration is great resource to deploy a cloud dev/test environment.

Assuming that you already have a two node cluster up and running with GlusterFS working in replica mode

Deployment diagram

lets try to deploy:

NGINX HTTP front-end to support multiples domains

Portainer.IO Docker Swarm UI management console

A private Docker registry to push your own docker images

A registry UI to browser your private images

A load balancer to receive your external HTTP/HTTPS traffic

Lets start this deployment by installing a GlusterFS docker volume driver, it will simplify the Docker stack deployment, there is project with a volume driver for GlusterFS at GitHub, with a PR merged using latest Oracle Linux 7 slim image and a correct GlusterFS version, just run as root in node1:

# docker plugin install --alias glusterfs trajano/glusterfs-volume-plugin:v2.0.3 --grant-all-permissions --disable

# docker plugin set glusterfs SERVERS=localhost,remote

# docker plugin enable glusterfs

repeat above steps at node2 instance, GlusterFS volume plugin could be checked using:

# docker plugin ls

ID NAME DESCRIPTION ENABLED

b728c6465a61 glusterfs:latest GlusterFS plugin for Docker true

or if you already create a GlusterFS volume named myvolume, check them using:

# docker volume create --driver glusterfs myvolume

# # docker run -it --rm -v myvolume:/mnt oraclelinux:7-slim bash

bash-4.2# ls -l /mnt

total 1048592

drwxr-xr-x. 5 root root 4096 Oct 23 11:25 configs

drwxr-xr-x. 2 root root 4096 Oct 27 22:02 html

drwxr-xr-x. 5 root root 4096 Oct 25 00:18 portainer

drwxr-xr-x. 3 root root 4096 Oct 26 17:17 registry

-rw-r--r--. 1 root root 1073741824 Oct 26 19:34 test1.img

well, now We have a GlusterFS replicated storage ready for using under Docker Swarm, lets deploy first a Docker private registry/UI and Portainer.IO, create a shared storage for both services in order to persist and survive docker restart and migration across nodes:

# mkdir -p /gluster-storage/registry /gluster-storage/portainer /gluster-storage/html

# docker network create -d overlay lb_network

A private registry with UI stack:

docker-compose-registry.yml

A Portainer.IO stack:

docker-compose-portainer.yml

finally an NGINX stack working as frontend for above services:

docker-compose-nginx.yml

config files references at above stack can be created using:

nginx.conf -

# curl -s portainer.conf -

# curl -s registry.conf -

# curl -s registry-ui.conf - # curl -s https://gist.githubusercontent.com/marcelo-ochoa/30123f50c30a15bed5c6f2ef326db475/raw/7fc34bb98d8a06397aff6f17797806a32046e994/nginx.conf | docker config create# curl -s https://gist.githubusercontent.com/marcelo-ochoa/bfd014f4e9ff59315a1928233da57fe0/raw/902d7ceb57ac9d0b2c837fa8bec2e5a0acf9d0f7/portainer.conf | docker config create# curl -s https://gist.githubusercontent.com/marcelo-ochoa/189573847373d59dd82eef230a0b8899/raw/6894c59d09c3c31fb5a092e23c0af1eb34526942/registry.conf | docker config create# curl -s https://gist.githubusercontent.com/marcelo-ochoa/55b07f94a7a459f64edd19f1004319b9/raw/0b4855691ab3dc948c7aaee8ed81789ee85fb940/registry-ui.conf | docker config create

note that above config files reference my upstream servers as 10.0.1.20 and 10.0.1.22 change with your private IPs assigned to node1 and node2 instances at the Oracle Cloud, also registry-ui.conf refers to the public load balancer IP, replace 1.1.1.1 with a value obtained below. Finally just deploy above stacks and reconfigure Linux firewall using:

# firewall-cmd --permanent --zone=public --add-port=80/tcp

# firewall-cmd --permanent --zone=public --add-port=443/tcp

# firewall-cmd --permanent --zone=public --add-port=5000/tcp

# firewall-cmd --permanent --zone=public --add-port=8000/tcp

# firewall-cmd --permanent --zone=public --add-port=9000/tcp

# firewall-cmd --permanent --zone=public --add-port=9001/tcp

# firewall-cmd --reload

# docker stack deploy -c docker-compose-nginx.yml nginx

# docker stack deploy -c docker-compose-portainer.yml portainer

# docker stack deploy -c docker-compose-registry.yml registry

stack and services deployed

now a finally step is to configure Oracle Cloud Free Load Balancer to redirect incoming HTTP/HTTPS traffic to our NGINX frontend, here a sequence of screenshots with the steps:

Load Balancer Definition Step 1

Adding Backend

HTTP Listener definition

Self signed SSL certificate, see below

HTTPS listener definition

Review of ingress rules for ports 80/443 from anywhere (0.0.0.0/0)

Note: A self signed certificate generated with OpenSSL is used, here the step to create using mydomain-com.conf:

mydomain-com.key.pem -days 365 -out mydomain-com.cert.pem # openssl req -config mydomain-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout-days 365 -out

Once you have your Load Balancer up and running obtain your assigned public IP from Networking -> Public IPs menu, here an screenshot:

Load Balancer Public IP

with above information you can edit your /etc/hosts file, here an example:

$ more /etc/hosts

127.0.0.1 localhost

127.0.1.1 my-notebook # The following lines are desirable for IPv6 capable hosts

::1 ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

150.nnn.mmm.226 registry.mydomain.com

150.nnn.mmm.226 registry-ui.mydomain.com

150.nnn.mmm.226 portainer.mydomain.com 150.nnn.mmm.226 www.mydomain.com 150.nnn.mmm.226 registry.mydomain.com150.nnn.mmm.226 registry-ui.mydomain.com150.nnn.mmm.226 portainer.mydomain.com

and that’s all check Portainer.IO, NGINX or Registry-UI access using your browser and URLs http[s]://[www|registry-ui|portainer].mydomain.com

NGINX Working

Registry-UI

Portainer.IO

If you want to upload Docker images from you local computer to your Oracle Cloud hosted environment is necessary to copy the self-signed certificate into your local docker directory for certs, for example:

$ ls -l /etc/docker/certs.d/registry.mydomain.com/ca.crt

-rw-r--r-- 1 root root 1671 oct 24 08:43 /etc/docker/certs.d/registry.mydomain.com/ca.crt

$ docker pull hello-world:latest

latest: Pulling from library/hello-world

1b930d010525: Pull complete

Digest: sha256:c3b4ada4687bbaa170745b3e4dd8ac3f194ca95b2d0518b417fb47e5879d9b5f

Status: Downloaded newer image for hello-world:latest

docker.io/library/hello-world:latest

$ docker tag hello-world:latest registry.mydomain.com/hello-world:latest

$ docker push registry.mydomain.com/hello-world:latest

The push refers to repository [registry.mydomain.com/hello-world]

af0b15c8625b: Layer already exists

latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

ca.crt is copy of the file mydomain-com.cert.pem generated with OpenSSL.

Next post will be something more real such as a Node.js App using Oracle DB, a REST endpoint for Apex or an OpenHab automation hub, keep in sync.