For the last 3 years I’m wor­king as a softwa­re deve­lo­per at Code­lab on a par­ti­cu­lar pro­ject. My respon­si­bi­li­ty was to imple­ment a new user inter­fa­ce to alre­ady exi­sting back-end appli­ca­tion using Spring and a pro­prie­ta­ry data­ba­se which was a com­mer­cial solu­tion for full text search. Docker is one of the main tools in this pro­ject. This artic­le is inten­ded to point out the issu­es enco­un­te­red, the solu­tions pro­vi­ded with focus on how docker assi­sted us during this project. 

Docker is a pro­gram which sup­ports sys­tem-level vir­tu­ali­za­tion. The first ver­sion of Docker was rele­ased in 2013. It got quic­kly adap­ted by many com­pa­nies which noti­ced the enor­mo­us value of this new model. Nowa­days Docker is almost eve­ry­whe­re and sup­ports developer’s daily work to cre­ate bet­ter appli­ca­tions. ‘Unit of work’ in this envi­ron­ment is a con­ta­iner which simu­la­tes ope­ra­ting sys­tem func­tio­na­li­ties, whi­le the con­ta­iner is built — it can be exe­cu­ted on any plat­form and har­dwa­re infra­struc­tu­re which sup­port Docker tech­no­lo­gy e.g. Win­dows, Linux, Clo­ud, on pre­mi­se servers. It is not only a gre­at plat­form for deve­lop­ment, but also for ship­ping and run­ning appli­ca­tion. It also sup­ports faster appli­ca­tion delivery. 

Con­ta­iners are cre­ated based on ima­ges that con­ta­in all depen­den­cies which appli­ca­tion needs to be exe­cu­ted e.g. to ope­ra­ting sys­tem as well to exter­nal com­po­nents. An Ima­ge is a sin­gle pac­ka­ge which sim­pli­fies it’s distri­bu­tion. Con­ta­iners are small and che­ap and can be used in the who­le life­cyc­le of the appli­ca­tions. The main advan­ta­ge of the con­ta­iners is that they simu­la­te envi­ron­ments in which appli­ca­tions are run­ning well. Even on dif­fe­rent machines/servers, becau­se of ope­ra­ting sys­tem level vir­tu­ali­za­tion, we can be sure that our appli­ca­tion will work as expec­ted. This is a big step for­ward for sup­por­ting the con­cept “build once, run any­whe­re”. Many CI/CD envi­ron­ments adapt docker as the­ir first-class citizen. 

It is easy to build auto­ma­ted deploy­ment pro­ces­ses with docker under the hood. More­over, docker is a heart of sys­tems for auto­ma­ting deploy­ment, sca­ling and mana­ging com­pu­ter appli­ca­tions. It is also the main featu­re cho­sen by the clo­ud pro­vi­ders to allow custo­mers deploy and sca­le the­ir appli­ca­tions based on the­ir needs. 

In our pro­ject we have deci­ded to use docker for CI/CD pur­po­se. Heart of our sys­tem was a pro­prie­ta­ry data­ba­se, pro­vi­ding very effi­cient full text search of big mount of vario­us docu­ments, whe­re we imple­ment the mid­dle lay­er to access the data and user frien­dly interface. 

In order to spe­ed up the deve­lop­ment we wan­ted to cre­ate a CI/CD sys­tem which: 

  • Eve­ry sta­ge can be exe­cu­ted inde­pen­den­tly to other sta­ges accor­ding sin­gle respon­si­bi­li­ty principle 
  • We can intro­du­ce chan­ges to the con­fi­gu­ra­tion of eve­ry sta­ge witho­ut bre­aking and needing to adapt other stages 
  • Assu­res that appli­ca­tion is tested by deve­lo­pers and QA on the same envi­ron­ment that it’s used on the production 
  • Each test can be exe­cu­ted inde­pen­den­tly to others and can be parallelized. 
  • Allow to cre­ate and exe­cu­te auto­ma­ted inte­gra­tion tests which are inde­pen­dent from data in the DB and it’s sta­te, struc­tu­re and configuration. 

  We agre­ed to use gitlab for pre­pa­ring the CI/CD envi­ron­ment becau­se we alre­ady had some expe­rien­ce with this open-sour­ce pro­duct. We were awa­re of its advan­ta­ges which are very acti­ve com­mu­ni­ty and com­pe­ti­ti­ve­ness in the com­mer­cial mar­ket. Fur­ther­mo­re, gitlab has the possi­bi­li­ty to defi­ne all the steps how the appli­ca­tion is built, tested, ana­ly­zed and deploy­ed in YAML con­fi­gu­ra­tion file, which can be incre­men­tal­ly adop­ted to pro­ject needs. . In our case eve­ry step in the gitlab was exe­cu­ted within a sepa­ra­te docker con­ta­iner. All the sta­ges were defi­ned with appro­pria­te docker ima­ge that needs to be used during the step exe­cu­tion. The CI/CD envi­ron­ment was con­fi­gu­red to build new softwa­re ima­ge after eve­ry com­mit so that eve­ry chan­ge was auto­ma­ti­cal­ly tested and after pro­per veri­fi­ca­tion deli­ve­red to the deve­lop­ment servers. The built ima­ges were addi­tio­nal­ly sto­red in the gitlab con­ta­iner regi­stry, and were tag­ged with the­ir own uni­que com­mit hash ID. This setup let us easi­ly veri­fy which ver­sion was run­ning on the servers if needed. Whi­le some pro­blems were detec­ted it was very easy for deve­lo­pers to get the right ver­sion to repro­du­ce the errors. 

In our case, testing of the front-end inte­gra­tion with prio­prie­ta­ry DB solu­tion was cru­cial part for the effec­ti­ve and high quali­ty sotwa­re deve­lop­ment. We have deci­ded to pre­par our own ima­ge of the data­ba­se which was used only during testing. Cre­ating pro­duc­tion ready data­ba­se ima­ge is much more com­pli­ca­ted and time-con­su­ming, main­ly due to mul­ti­pli­ci­ty of cases that must be tested. 

We used Test­con­ta­iners libra­ry that nati­ve­ly sup­port docker. It is a fan­ta­stic libra­ry that can be smo­oth­ly added to the pro­ject, even by tho­se, who would like to adapt docker featu­res incre­men­tal­ly. The libra­ry allows to cre­ate a new con­ta­iner type desi­gned for data­ba­ses and pro­vi­des func­tio­na­li­ty for con­fi­gu­ra­tion of the DB and for effec­ti­ve usa­ge of the ima­ge in the tests. During tests exe­cu­tion new con­ta­iner with instan­ce of the data­ba­se was cre­ated and clo­sed auto­ma­ti­cal­ly after all tests were exe­cu­ted. As a next step, we con­fi­gu­red that each sin­gle test was run sepa­ra­te­ly and inde­cen­tly, in paral­lel becau­se each of them has it is own inde­pen­dent data­ba­se container. 

It is also easier to new deve­lo­pers in the pro­ject to build and run local­ly who­le softwa­re becau­se the majo­ri­ty of tasks can be auto­ma­ted with docker sup­port. Last but not least, using docker ima­ges allows who­le envi­ron­ment to migra­te easi­ly to new servers. All the defi­ni­tions e.g. gitlab YAML file are auto­ma­ti­cal­ly sup­por­ted becau­se they are con­nec­ted to docker, not to host on which they are run­ning.    To sum up, docker is wide­ly used by many com­pa­nies inc­lu­ding Code­lab. It sim­pli­fies the pro­cess of buil­ding and deli­ve­ring softwa­re, as well as sup­ports appli­ca­tions in the­ir life­cyc­le. Docker, owing to it inde­pen­den­ce from vario­us fra­me­works, pro­gram­ming lan­gu­ages and libra­ries, is an excel­lent tool, espe­cial­ly for deve­lo­pers and devops. With the sup­port of exter­nal tools such as docker swarm or kuber­ne­tes or libra­ries like test con­ta­iners, it has been very help­ful in pro­cess of cre­ating softwa­re. Altho­ugh, docker is so popu­lar, it is still hard to use witho­ut expe­rien­ce. One needs to fami­lia­ri­ze them­se­lves with it befo­re using it at pro­duc­tion. Regar­dless of all the effort that docker requ­ires from its users I stron­gly recom­mend this tool becau­se it is suc­cess­ful­ly used in many of our projects.