Continuous Delivery Pipeline med docker

Igår återsamlades vi en liten grupp DevOps-intresserade konsulter från flera olika konkurrerande bolag för att gemensamt bygga vidare på vår build pipeline. Den här gången höll vi till i CAGs lokaler inne i city.

IMG_20140604_201356[1]

Huvudtemat för dagen var docker. Idén var att införa docker som provider till Vagrant i vår build pipeline. docker innebär att nya maskiner blir betydligt mer lättviktiga än om varje maskin är en egen virtualbox-instans som vi hittils kört med Vagrant.

Eftersom docker-images får en hanterbar storlek vill vi direkt dra nytta av detta och ändra pipelinen att istället för att skicka runt applikationsartefakten (till exempel myapp.war) mellan byggstegen i pipelinen så låter vi första byggsteget bygga docker-images för hela miljön, till och börja med bara appserverns image, och skicka denna image mellan de olika teststegen i pipelinen: funktionell test, systemtest, GUI-test, lasttest och allt man kan hitta på.

Vi började med att skapa ett nytt github-projekt för att definiera en maskin att köra docker på. Den borde med facit i hand byta namn till dockerPipelineHost eller något liknande. Anledningen att vi öht skapar en docker host (alla Linux-maskiner kan ju köra docker native) är att vi vill kunna köra exakt samma pipeline såväl på utveckarmaskiner som i produktion.

Om vi lägger docker-definitionen i ett eget github-projekt kan vi bygga en docker-image som kan finnas i dockers repository (dockers affärsmodell är liknande githubs, de hostar images gratis så länge de är publika. Vill du ha privata docker images kostar det).

Vi provar att utgå från phusion/baseimage därför att den har stöd för ssh, default för docker är att ssh-stöd saknas. Tankemodellen för docker är att man kör igång en process och inte bootar en helt maskin, även om processen man kör igång får en egen maskin. Det kan dock underlätta att kunna ssh-a in till docker-containern för att felsöka.

Först skapade vi en VagrantFile, sedan körde vi igång den:

$ vagrant up --provider=docker

Vi slogs ett tag med att docker behöver port 4243 och det kolliderade med CrashPlan, så har man CrashPlan eller nåt annat på 4243 får man stoppa det.

Vi började med att skapa en databasmaskin. Vi tror att rätt modell med docker är att starta en docker-container per databas och inte försöka klämma in flera databaser i samma docker-container, även om det går om man absolut skulle vilja.

I nästa steg tänkte vi oss att skapa en appserver med tomcat. Vi fick trassel med hängning vid uppstart:

...
==> app: Creating the container...
app: Name: app
app: Image: phusion/baseimage
app: Cmd: /sbin/my_init --enable-insecure-key
app: Volume: /var/lib/docker/docker_1401893872_25527:/vagrant
app: Port: 2222:22

Här hänger den i evigheter vid vagrant up --provider=docker. Beror detta på att vi kör phusion/baseimage? Efter lång väntan lossnade maskinerna. Förmodligen nån nedladdning som tog tid här.

Efter att ha trasslat med att försöka starta tomcat som en process/kommando när startscriptet /etc/init.d/tomcat försöker starta en demon, övergick vi att köra en applikation som har tomcat inbäddad. Vi tror att detta är modellen – en applikation – en webcontainer – en maskin (som är en docker-container). Vi ser ingen större poäng att separera applikationen för att köra den i en standalone tomcat i något steg.

Vi övergick alltså från att köra petclinic till att köra doodleshop
doodleshop som är en nyligen ihopslängd demoapp på Spring Boot och embedded tomcat. Då behöver vi bara ha JRE på maskinen och kommandot för docker-containern blir enkelt:

java -jar doodleshop.jar

Vi tänkte oss först att lägga CoreOS i botten, dvs starta denna med Vagrant. CoreOS har docker installerat. Vår miljö implementerar vi som docker-containers: prodserver, testserver, databaserver, lastbalanserare och ci-server.

Vi måste mappa upp kataloger i containrarna till hostens filsystem. Annars försvinner datat när man plockar ned containern, eller när man gör vagrant halt på docker-hosten. Till exempel databasen skall lagra sitt data i en katalog som mappas till en katalog på dess docker-host CoreOS. Och denna katalog på CoreOS måste i sin tur mappas till en katalog i dess hosts filsystem, t.ex. en Mac OS X. Samma gäller appservrar för att få ut loggar.

Vi började drömma oss bort till centraliserad loggning här för att slippa att mappa upp appservrarna. Vi tror på logstash, ELK stack med logstash socket log appender i applikationen. Det får bli en annan kväll.

Sedan kom vi på att det blir svårt att starta nya docker-containers (prod, test, lb, db) från CI-servern om även denna ligger som en docker-container, det går säkert via dockers REST-api eller nåt, men det lät inte som enklaste vägen. Detta innebär att vi övergår till att installera CI på hosten, samma som docker själv kör på. Detta innebär i sin tur att det förmodligen är mest praktiskt att köra precise64 där istället för CoreOS.

Första steget i build pipeline är ”Build”. Denna bygger artefakten från senaste källkoden och kör enhetstester. Sedan skapas en docker-image. Integrationstestjobbet löses genom att pre-integration-test i maven deployar denna versions docker image till en docker container och startar denna. Integrationstesterna kör mot denna container. URL är miljöspecifik så man kan köra integrationtesterna lokalt också. post-integration-test tar ned containern och slänger den. Containern heter typ myapp-1.0.127, alltså byggnummer.

Vi fortsatte med att implementera detta i Go. Vi har behov av att flytta ut konfigurationsparametrarna för olika miljöer till environmentvariabler, t.ex. http-port. När man startar en docker-container med docker run anger man vilken port den skall exponera. Applikationen måste startas med samma port och porten beror av vilken docker-container applikationen kör. Denna parameter måste kunna styras utifrån för att informationen om vilken port vi kör på inte ska behöva finnas på två ställen, dvs först incheckad i den miljöspecifika konfigurationen och dessutom i den incheckade go-jobbkonfigen. Samma gäller andra parametrar som databas url.

Här någonstans hade klockan passerat läggdags och vi började krokna. Vi fortsätter vid ett senare tillfälle.

docker känns inte helt stabilt i alla lägen men verkar helt klart ha förutsättningar att bli något riktigt bra.

Förberedelser inför nästa mangling:

  • Mikael byter favoriteditor
  • Marell skaffar en fungerande VGA-adapter
  • Minst en av oss tar med en displayport-ethernet-adapter så vi kan tanka med mer än 15 MB/s
  • Någon fixar så vi slipper ladda ned hela Go varje gång CI-maskinen ska upp

IT Consultant at CAG Edge. Cloud and Continuous Delivery specialist, software developer and architect, Node.js, Java.

Publicerad i Continuous Delivery, DevOps, Java, Linux

Kategorier

WP to LinkedIn Auto Publish Powered By : XYZScripts.com