We've seen how flexible it is to consume virtual machines in a software defined datacenter in our previous article to code, design, build and RUN an application to quickly answer the DevOps challenges your organisation can have.
But what if some teams are using containers instead of virtual machines? There's a good chance that a number of your Dev(Ops) teams are now using this amazing technology. How do you provide them the right environment?
Containers (and particularly Docker) provide amazing benefits, my favorite one being to better control on the Dev-to-Prod lifecycle. One can see the containers as being the ultimate artifact which you can then deploy and manage as one unit (as opposed to the traditional way (VM based) which need many dependencies.
So there are benefits to containers, no doubt about it.
How do I turn my application into the amazing world of containers?
Well, you have 2 school of thoughts here.
A/ use your existing code, turn your app into a container => rip 95% of the benefits in a minimum amount of time
B/ modify your existing code (deeply I mean) to turn it into micro services because the God of Buzz (the 2016 one I mean) said so => rip 96% of the benefits in a huge amount of time (add a high level of risks on top of this)
Well, I choose option A :)
But, still, How do I do that? I am not going to explain what Docker is but rather show you my procedure. It worked pretty well.
In our previous article we talked about Tito's architecture:
We see that we have 2 tiers with different components inside:
Front end runs apache which use Tito's code
Backend use Mysql whom the DB structure is configured by a script
Here's the steps I used for each Tier:
For the front end:
- Reuse an existing front end PHP Docker image
- Customize the image for my specific needs (install php and sql modules)
- copy the code inside
- Use some Docker magic to know the IP of the backend container
To build my image each time I need it, I created a Docker file which is below:
COPY . /var/www/html/
COPY asset/Deployment/Docker/tito-fe/apache2-foreground /usr/local/bin/apache2-foreground
RUN chmod +x /usr/local/bin/apache2-foreground
RUN apt-get update
RUN apt-get install php5-mysql vim libmcrypt-dev -y
RUN docker-php-ext-install mysqli pdo pdo_mysql mcrypt
RUN cp /usr/share/php5/php.ini-production /usr/local/etc/php/php.ini
RUN echo "<IfModule env_module>" >> /etc/apache2/mods-enabled/env.conf
RUN echo " SetEnv TITO-SQL \"Tito-SQL\"" >> /etc/apache2/mods-enabled/env.conf
RUN echo "</IfModule>" >> /etc/apache2/mods-enabled/env.conf
the FROM state which image do I use. I used an official PHP image. It's pretty handy since it comes with a documentation which explains a lot of things and come with a community who has already gone through the steps you are now taking.
COPY copies the code inside the image
RUN simply run each commands. I'll explain later the echo lines
ENTRYPOINT is the script which is run each time the container starts
For the backend:
- Reuse an existing MySQL docker image
- Set the DB password
- copy the SQL script at the right place
- (that's it)
Here's the Docker file:
ENV MYSQL_ROOT_PASSWORD: Tito2016
ADD asset/Deployment/Docker/tito-sql/db_name.sql /docker-entrypoint-initdb.d
Nice things to know about this PHP image:
There are scripts inside which will automatically take the value of the environment variable MYSQL_ROOT_PASSWORD and will launch any .sql files available in the /docker-entrypoint-initdb.d folder.
OK, I have 2 containers, how do I have an app?
So I have created my 2 containers but I need to find a way to link them together on 2 levels:
I need a network for my containers to talk to each other and I also need the front end to know the IP address of the SQL container.
For the network creation, I create 2 networks, one to access the front end from outside (named front tier) and one to connect the front to the back end (named back tier)
To pass the SQL IP to the front end app, we're using the Link command which actually creates a tito-sql alias in the front end /etc/hosts with the right IP address. The tito-sql alias is then passed to the app by using the setenv mechanism.
So to summarize, we have created the 2 containers and now are using the Docker compose tool to make them work together and create the Tito app.
Here's the docker compose code:
A/ Containers are awesome stuff
They are very fast, very flexible. It's really a pleasure to build app with this technology
B/ Containers are (really) awesome stuff
They are very portable. You can take the above Compose code on you own Linux or anywhere and the Tito app will start working. Pretty amazing.
C/ Containers come with some... questions which, to be answered, need to bring some.... friends
Persistent storage - Where do I store my DB?
Network: there are several technology (on top of existing one), some of them are obsolete (links) some are specifics, little ramp up needed here
Orchestrator: Where do I run my containers? what happens when one crash? what happens when 2 containers need to communicate through the same network port? How do I manage them? etc.. etc... you soon need an orchestrator (Swarm, Kubernetes, Rancher for example) to answer the issues that containers bring with them
D/ therefore you can't turn everything in Containers. They are for stateless workloads (forget DB for now in Prod).
In short, you want to use the technology but you need to be aware that there's a specific road to take when you want to go up to the production with them.
In the future, we will see how we can overcome some of these challenges and keep up having fun by playing with the Tito app under various form.