For the last 3 years I’m work­ing as a soft­ware developer at Codelab on a par­tic­u­lar pro­ject. My respons­ib­il­ity was to imple­ment a new user inter­face to already exist­ing back-end applic­a­tion using Spring and a pro­pri­et­ary data­base which was a com­mer­cial solu­tion for full text search. Dock­er is one of the main tools in this pro­ject. This art­icle is inten­ded to point out the issues encountered, the solu­tions provided with focus on how dock­er assisted us dur­ing this project. 

Dock­er is a pro­gram which sup­ports sys­tem-level vir­tu­al­iz­a­tion. The first ver­sion of Dock­er was released in 2013. It got quickly adap­ted by many com­pan­ies which noticed the enorm­ous value of this new mod­el. Nowadays Dock­er is almost every­where and sup­ports developer’s daily work to cre­ate bet­ter applic­a­tions. ‘Unit of work’ in this envir­on­ment is a con­tain­er which sim­u­lates oper­at­ing sys­tem func­tion­al­it­ies, while the con­tain­er is built — it can be executed on any plat­form and hard­ware infra­struc­ture which sup­port Dock­er tech­no­logy e.g. Win­dows, Linux, Cloud, on premise serv­ers. It is not only a great plat­form for devel­op­ment, but also for ship­ping and run­ning applic­a­tion. It also sup­ports faster applic­a­tion delivery. 

Con­tain­ers are cre­ated based on images that con­tain all depend­en­cies which applic­a­tion needs to be executed e.g. to oper­at­ing sys­tem as well to extern­al com­pon­ents. An Image is a single pack­age which sim­pli­fies it’s dis­tri­bu­tion. Con­tain­ers are small and cheap and can be used in the whole life­cycle of the applic­a­tions. The main advant­age of the con­tain­ers is that they sim­u­late envir­on­ments in which applic­a­tions are run­ning well. Even on dif­fer­ent machines/servers, because of oper­at­ing sys­tem level vir­tu­al­iz­a­tion, we can be sure that our applic­a­tion will work as expec­ted. This is a big step for­ward for sup­port­ing the concept “build once, run any­where”. Many CI/CD envir­on­ments adapt dock­er as their first-class citizen. 

It is easy to build auto­mated deploy­ment pro­cesses with dock­er under the hood. Moreover, dock­er is a heart of sys­tems for auto­mat­ing deploy­ment, scal­ing and man­aging com­puter applic­a­tions. It is also the main fea­ture chosen by the cloud pro­viders to allow cus­tom­ers deploy and scale their applic­a­tions based on their needs. 

In our pro­ject we have decided to use dock­er for CI/CD pur­pose. Heart of our sys­tem was a pro­pri­et­ary data­base, provid­ing very effi­cient full text search of big mount of vari­ous doc­u­ments, where we imple­ment the middle lay­er to access the data and user friendly interface. 

In order to speed up the devel­op­ment we wanted to cre­ate a CI/CD sys­tem which: 

  • Every stage can be executed inde­pend­ently to oth­er stages accord­ing single respons­ib­il­ity principle 
  • We can intro­duce changes to the con­fig­ur­a­tion of every stage without break­ing and need­ing to adapt oth­er stages 
  • Assures that applic­a­tion is tested by developers and QA on the same envir­on­ment that it’s used on the production 
  • Each test can be executed inde­pend­ently to oth­ers and can be parallelized. 
  • Allow to cre­ate and execute auto­mated integ­ra­tion tests which are inde­pend­ent from data in the DB and it’s state, struc­ture and configuration. 

  We agreed to use git­lab for pre­par­ing the CI/CD envir­on­ment because we already had some exper­i­ence with this open-source product. We were aware of its advant­ages which are very act­ive com­munity and com­pet­it­ive­ness in the com­mer­cial mar­ket. Fur­ther­more, git­lab has the pos­sib­il­ity to define all the steps how the applic­a­tion is built, tested, ana­lyzed and deployed in YAML con­fig­ur­a­tion file, which can be incre­ment­ally adop­ted to pro­ject needs. . In our case every step in the git­lab was executed with­in a sep­ar­ate dock­er con­tain­er. All the stages were defined with appro­pri­ate dock­er image that needs to be used dur­ing the step exe­cu­tion. The CI/CD envir­on­ment was con­figured to build new soft­ware image after every com­mit so that every change was auto­mat­ic­ally tested and after prop­er veri­fic­a­tion delivered to the devel­op­ment serv­ers. The built images were addi­tion­ally stored in the git­lab con­tain­er registry, and were tagged with their own unique com­mit hash ID. This setup let us eas­ily veri­fy which ver­sion was run­ning on the serv­ers if needed. While some prob­lems were detec­ted it was very easy for developers to get the right ver­sion to repro­duce the errors. 

In our case, test­ing of the front-end integ­ra­tion with priopri­et­ary DB solu­tion was cru­cial part for the effect­ive and high qual­ity sot­ware devel­op­ment. We have decided to pre­par our own image of the data­base which was used only dur­ing test­ing. Cre­at­ing pro­duc­tion ready data­base image is much more com­plic­ated and time-con­sum­ing, mainly due to mul­ti­pli­city of cases that must be tested. 

We used Test­con­tain­ers lib­rary that nat­ively sup­port dock­er. It is a fant­ast­ic lib­rary that can be smoothly added to the pro­ject, even by those, who would like to adapt dock­er fea­tures incre­ment­ally. The lib­rary allows to cre­ate a new con­tain­er type designed for data­bases and provides func­tion­al­ity for con­fig­ur­a­tion of the DB and for effect­ive usage of the image in the tests. Dur­ing tests exe­cu­tion new con­tain­er with instance of the data­base was cre­ated and closed auto­mat­ic­ally after all tests were executed. As a next step, we con­figured that each single test was run sep­ar­ately and inde­cently, in par­al­lel because each of them has it is own inde­pend­ent data­base container. 

It is also easi­er to new developers in the pro­ject to build and run loc­ally whole soft­ware because the major­ity of tasks can be auto­mated with dock­er sup­port. Last but not least, using dock­er images allows whole envir­on­ment to migrate eas­ily to new serv­ers. All the defin­i­tions e.g. git­lab YAML file are auto­mat­ic­ally sup­por­ted because they are con­nec­ted to dock­er, not to host on which they are run­ning.    To sum up, dock­er is widely used by many com­pan­ies includ­ing Codelab. It sim­pli­fies the pro­cess of build­ing and deliv­er­ing soft­ware, as well as sup­ports applic­a­tions in their life­cycle. Dock­er, owing to it inde­pend­ence from vari­ous frame­works, pro­gram­ming lan­guages and lib­rar­ies, is an excel­lent tool, espe­cially for developers and devops. With the sup­port of extern­al tools such as dock­er swarm or kuber­netes or lib­rar­ies like test con­tain­ers, it has been very help­ful in pro­cess of cre­at­ing soft­ware. Although, dock­er is so pop­u­lar, it is still hard to use without exper­i­ence. One needs to famil­i­ar­ize them­selves with it before using it at pro­duc­tion. Regard­less of all the effort that dock­er requires from its users I strongly recom­mend this tool because it is suc­cess­fully used in many of our projects.