Hello Docker

This post is not a how-to or tutorial about using Docker, fortunately you have a lot a resources on this topic, this is just my personal experience with this technology, my motivation behind it and my thoughts about it.

Lately I’ve been researching into the containers world, since the appearance of LXC I’ve been curious about this new technology, but until now I didn’t had the time to explore it and since nowadays everyone is talking about Docker so I decide to give it a try.

The motivation

In my latest challenge on the company I work, I’ve chosen virtualization to deploy our ERP software, PMS software and other systems because the software solutions were mostly Windows based, the ERP is even an old dinosaur, it’s an desktop based solution and  we had to deploy a Remote Desktop solution for users to access it,  not the state of art solution but hey when you have a job to do you got to do it well…. but this coming year we will be deploying the HRM and I’m looking into doing things a little bit different.

This new solution it’s web based and runs on Linux ( hurray, feeling happy now ) therefore containers it’s a technology I can look into as it makes more sense than virtualization, my goal is to enable the deployment and development of this new software as smooth as possible making it easy for the IT department to customize and extend it in the near future.

So this is where this journey begins.

The test lab

Before diving into the company servers and start deploying Docker,   I thought it could be a good exercise migrating my own personal server into using containers.

I live in the small island of Principe, unfortunately we do not have cable TV but we do have a pretty good Internet connection and in my home country, Portugal, my ISP  gives me 100mbits of upload bandwidth so this personal server was built to allow me to have quality TV channels streamed into my home here in Principe.

Some months ago after setting up the streaming service hosting this blog and my file sharing service on the same server felt like the way to go. The machine already had Ubuntu 16.04 LTS  installed therefore installing MySQL, Apache, PHP, WordPress and Nextcloud on it was very easy,  automating the SSL certificate generation was also possible using Let’s Encrypt bot and even setting the applications folder and database files on a different hard-drive for backup and scalability purposes made all sense to me ( and also because the OS is installed on a SSD drive )
Everything was working as planned, automatic backups were being done every day and transfered at late night into my external USB drive connected to my Raspberry Pi  here in Principe, which by the way is used as a set-top box to receive my TV channels.

So there it was my own cloud hosted on my personal server in Portugal, and the next step? Using it as a test lab to install Docker and migrate WordPress and Nextcloud to a container based solution, this would not only allow me to solve some issues I had before with apt upgrade, but also for me to do a test drive before doing it on the company server.

Hello Docker

I’ve been playing with Docker on my Macbook for a while now, I’ve been trying to understand how this could relates with my past experience with virtualization, I’m well aware that containerization on it’s core it’s way different from virtualization, but in the concept of separating services on an abstract level  it feels very familiar to me. I’ve been using virtualization not only as a mean to take advantage of the resources we have in the company, but also as a way to separate the network services in a logic manner.

  • The authentication system is a Samba AD controller from which all other systems authenticate using Kerberos or LDAP.
  • A Windows 2012 Server machine is connected to the gateway working as a Remote Desktop Gateway and a reverse-proxy
  • The Terminal Desktop is another Windows 2012 Server from which users connect to launch the ERP application
  • The PMS is a IIS hosted application on a Windows 2016 Server machine which is the frontend for our e-commerce page for each of the hotels.
  • The monitoring framework it’s a Icinga2 appliance

Having all of this machines operating on bare metal would make our infrastructure a more expensive than it actually was, and the way it is designed allow us to migrate it to a cloud infrastructure like AWS or AZURE in the future.

After taking a test-drive with Docker on my machine I could see how it was built for this purpose, launching and composing new services is as easy as creating a Docker composer file, using/building the right images to create complex architectures and develop all kind of business solutions. Today we have all kind of open source solutions for almost everything, building an IT solution that grows on the same direction of the business it supports is like playing with LEGO, give me the right building blocks and I build you what you need.

So with this in mind I moved to migrate my server to the container world, I knew I would have to use a reverse proxy to allow access from the outside to WordPress and Nextcloud, I would also need to automate the SSL certificate generation for my domains.

MAKING it work

First step was installing Docker and after following the instructions on their website everything was ready to go.

https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/

Next I needed to migrate the MySQL server to a container, this step was relatively easy since I’d already had MySQL files on a different location, as I’ve mentioned before, I’ve used a different hard-drive for all my service files, which was already mounted on /srv, including MySQL data files.

After stopping the MySQL server instance in my machine and take advantage of the bind mounts that Docker offers , getting the MySQL up and running was as easy as:

docker container run --publish 3306:3306 --name mysqldb --mount type=bind,source=/srv/databases/mysql,target=/var/lib/mysql --detach mysql:latest

To test if everything was up and running I tried to connect to the server:

mysql --protocol=tcp -h localhost -u root -p

First problem, I wasn’t allowed to connect to the server from 178.17.0.1, but the solution was connecting from inside of the MySQL container and fix the permissions, again Docker allows us to get inside with Bash.

docker container exec -it mysqldb bash

Connected to the server, updated the user permissions, logged out and voilá I was now able to connect to the database from the “outside” world, awesome, the database was up and running on a container, next step was moving the Nextcloud  to a container. here I’ve taken a different road, instead of running the container with the Docker command I’ve preferred to take my chance with Docker compose, this tool is perfect when you need to launch a lot of services at the same time and those services have dependencies.

Let’s compose it

Instead of writing the docker-compose.yml from scratch I’ve found on Github a similar configuration.

https://github.com/gilyes/docker-nginx-letsencrypt-sample

This was the base for my composer instructions, and again having already the application files on /srv made it very easy to migrate.

First dependency, Nginx as a reverse proxy with let’s encrypt automation,  and George Ilyes Github  files already had what I needed for my setup.

 nginx:
   restart: always
   image: nginx
   container_name: nginx
   ports:
     - "80:80"
     - "443:443"
   volumes:
     - /srv/etc/nginx/conf.d:/etc/nginx/conf.d
     - /srv/etc/nginx/conf.d:/etc/nginx/vhost.d
     - /srv/apps/default:/usr/share/nginx/html
     - /srv/etc/nginx/certs:/etc/nginx/certs:ro

There is a image that I want to take a deeper look into and it’s called nginx-get, as far as I could understand it connects to the Docker daemon using the unix socket and monitors when a new containers is launched, when this happens it automatically updates the Nginx configuration, a very useful tool.

nginx-gen:
  restart: always
  image: jwilder/docker-gen
  container_name: nginx-gen
  volumes:
    - /var/run/docker.sock:/tmp/docker.sock:ro
    - /srv/etc/templates/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
  volumes_from:
    - nginx
  entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf

And finally the Let’s Encrypt automation mechanism, again another useful image.

letsencrypt-nginx-proxy-companion:
  restart: always
  image: jrcs/letsencrypt-nginx-proxy-companion
  container_name: letsencrypt-nginx-proxy-companion
  volumes_from:
    - nginx
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - /srv/etc/nginx/certs:/etc/nginx/certs:rw
  environment:
    - NGINX_DOCKER_GEN_CONTAINER=nginx-gen

So there it was Nginx as a reverse proxy plus the Let’s Encrypt certificates automation, now I was ready to compose my own instructions.

Let’s start with MySQL.

db:
  restart: always
  container_name: mysqldb
  image: mysql
  volumes:
    - /srv/databases/mysql:/var/lib/mysql
  environment:
    - MYSQL_ROOT_PASSWORD

Redis was another Nextcloud dependency for caching, Docker already provides this image.

redis:
  restart: always
  container_name: redis
  image: redis
  volumes:
    - /srv/apps/redis/data:/data

And finally Nextcloud,

cloud:
  restart: always
  image: nextcloud
  container_name: nextcloud
  environment:
    - VIRTUAL_HOST=cloud.mydomain.com
    - VIRTUAL_NETWORK=nginx-proxy
    - VIRTUAL_PORT=80
    - LETSENCRYPT_HOST=cloud.mydomain.com
    - LETSENCRYPT_EMAIL=me@mydomain.com
  links:
   - db
   - redis
  volumes:
   - /srv/apps/nextcloud/apps:/var/www/html/apps
   - /srv/apps/nextcloud/config:/var/www/html/config
   - /srv/apps/nextcloud/data:/var/www/html/data

With everything ready to go the next step was crossing my fingers and run

docker-compose up

And there it was, Docker compose was preparing everything and some seconds later Nextcloud was running on a container.

Getting WordPress was even easier

 blog:
   restart: always
   image: wordpress
   links: 
     - db
   volumes:
     - /srv/apps/blog/wp-content:/var/www/html/wp-content
   environment:
     - VIRTUAL_HOST=blog.mydomain.com
     - VIRTUAL_NETWORK=nginx-proxy
     - VIRTUAL_PORT=80
     - LETSENCRYPT_HOST=blog.mydomain.com
     - LETSENCRYPT_EMAIL=me@mydomain.com
     - WORDPRESS_DB_HOST=db:3306
     - WORDPRESS_DB_USER=myuser
     - WORDPRESS_DB_PASSWORD=mypassword
Conclusion

This test-drive made me realize that containers are in fact a big game changer on the way we deploy applications, in the end of this journey I’ve realized how easy it was from now on for me to design and deploy solutions that depends on multiple services, containers do make our life easier when it comes to allow us to replicate the same conditions on any machine, if I need to hack into WordPress or Nextcloud having exactly the same conditions that are in my server I just need to use the docker-composer.yml and fire it  on my machine, I can even build my own images and use them for my own deployments.

And now, what about virtualization? It’s a fact that you can setup the same kind of automation with virtual machines, scripts do help us in multiple ways and there are tools like Vagrant that makes our life much easy, In my personal opinion, virtual machines will not go away any time soon,  many applications aren’t ready yet to migrate into the container world and there are a lot of services that depends on old technologies that will only be available through a virtualized solution, but containers will probably slowly take control of the cloud and probably virtualization will be left for compatibility purposes.

In the past we have seen some advancements on the hardware to improve the hypervisor overhead, Intel and AMD had made and are still making investments on this technology, so I wouldn’t be surprise if in a near future we start seeing an hybrid solution between containers and hypervisors since it can add an extra layer of security.

WHAT’S NEXT

My next goal is to explore the containers on a VLAN environment, this is another concern in a network environment, especially when you have a network with multiple segmentations and services like IPTV, VoIP, IP Cameras and so on.

Hope you enjoyed this post and I’ll be updating this blog with my personal experiences and challenges.