PROSJEKT
Del artikkel
Skrevet av: Marius C. K. Gulbrandsen (Development Engineer)
PROSJEKT
Del artikkel
Skrevet av: Marius C. K. Gulbrandsen (Development Engineer)
Å utvikle software i team kan fort føre til mange utfordringer. En av disse er at man har ulike datamaskiner med ulike operativsystem og ulike versjoner av utviklingsverktøy. Når man da kommer til kompilering og testing av koden, så vil man fort finne ut at koden kan fungere for deg på din PC, men ikke for andre på teamet ditt. En god løsning på denne utfordringen kan være å flytte utviklingsmiljøet inn i en Docker container og versjonere denne containeren i et versjoneringssystem, som for eksempel Git. Da vil ikke lenger den enkelte utvikler sitte og konfigurere sine egne kompilatorer og annen nødvendig software, men alle vil bruke nøyaktig det samme utviklingsmiljøet. Dette skaper en forutsigbarhet i utviklingen av software hvor man raskere kan finne feil, i tillegg til flere andre fordeler.
Først er det nødvendig med en introduksjon til Docker og containere for å forstå hvordan man skal kunne bruke det som et utviklingsmiljø. Containere er isolerte prosesser som pakker kode og ‘dependencies’ sammen. Det betyr at en container inneholder alt som trengs for å kjøre en applikasjon. En container likner en virtuell maskin, men den er ikke det samme. For å kjøre en virtuell maskin så må du ha en hypervisor, som delegerer tilgangen til ressursene fra vertsmaskinen til gjestoperativsystemet. Til forskjell så kjører containere på vertsoperativsystemet som en selvstendig prosess og har direkte tilgang til kjernen. På grunn av dette trenger ikke containere å emulere operativsystemet, så de blir betydelig mindre i størrelse og kan starte opp i løpet av sekunder. Bildene illustrerer ulikheten mellom containere og virtuelle maskiner.
Figur 1. Forskjellen på containere og virtuelle maskiner [docker.com]
Portabiliteten til containere gjør at applikasjoner i dag kan bli utviklet med konseptet “microservices”, hvor en container kan sees på som én modul i en applikasjon. Se for deg en nettside hvor databasen, GUI, back-end og API alle er hver sin container som kjører som en isolert prosess. Kommunikasjonen mellom disse containerne er typisk et internt lokalt nettverk over TCP. Dette gir mer modulær, gjenbrukbar kode med høyere sikkerhet. Om noen skulle få tilgang til én container så vil de ikke ha tilgang til hele applikasjonen eller systemet.
Det finnes mange ulike implementasjoner av containere, men det mest populære av verktøyene for å utvikle containere er Docker. For å få kjørt containere på en maskin så trenger man bare Docker. Dette gir da fordelen at en applikasjon utviklet som en container kan kjøre på en hvilken som helst maskin med Docker installert og den trenger ingen flere ‘dependencies’, for disse er allerede pakket inn i containeren. Dette er en stor fordel for produksjon, testing og utvikling. Hvis man da tar dette et steg videre og utvikler inne i en container, i stedet for å installere utviklingsverktøy på din egen PC, så skaper dette en mer forutsigbar og effektiv utvikling av software.
Kanskje det mest typiske man hører fra en kollega når man driver feilsøking av kode er “det fungerer på min pc”. Dette kan det selvfølgelig være mange grunner til, som for eksempel at kollegaen er på kompilatorversjon 1.0.0 og du er på versjon 1.0.1. Det er også mulig at et utviklingsverktøy er fjernet eller glemt å installeres. Alt dette kan unngås hvis alle testet og bygde kode på den samme maskinen. Ved bruk av containere som utviklingsmiljø, eller det som kalles en utviklingscontainer, så er man i prinsippet på “den samme maskinen”.
Linux er det vanligste operativsystemet for å kjøre containere på og er det som Docker originalt ble utviklet for. Når man snakker om en container, så er det en prosess som har sitt eget Linux User space og som deler Kernel med operativsystemet. Man baserer en container på en Linux distribusjon, som Ubuntu, Debian, Alpine eller liknende. Derfor vil du inne i en utviklingscontainer være i det som føles ut som en virtuell maskin, men som bare er en isolert prosess. Alt som installeres av kompilatorer, programmeringsverktøy og alt annet hører til inne i utviklingscontainer og er usynlig for alle andre prosesser.
Figur 2. Tilkobling til en container med VS Code [Develop Inside a Container]
En container er bygget fra en Dockerfile, eller det som kalles for et Docker image. Containeren kan startes og stoppes, men for å ha tilgang til verktøyene inne i den må man koble til den over for eksempel SSH. Bildet over illustrerer hvordan man kan koble seg til en container ved å bruke Visual Studio Code.
Utviklingsmiljø i containere gir noen interessante fordeler. Fordi utviklingsmiljøet ditt eksisterer i en container som kan bygges når som helst, så kan den også fjernes enkelt. Derfor vil du ikke trenge å “forsøple” din egen maskin med installasjoner av software som fort kan føre til uforventede feil på maskinen din. En applikasjon som ødelegger filsystemet eller en feilinstallert kompilator som var vanskelig å fullstendig avinstallere. Eller hva med de 5 ulike versjonene av GCC som du har installert?
Hvis noe skulle gå galt ved installering av software i en utviklingscontainer, så er det bare å bygge den på nytt med Docker. Det gjør det da enkelt å fullstendig “installere maskinen på nytt” ved å bare bygge med Docker, som vil ta alt fra noen sekunder til minutter. Ulike versjoner av software er ikke noe problem å bruke i hver sin utviklingscontainer og prototyping er så lett som å skrive inn en kommando i terminalen for å hente en ferdigbygget C++ container fra Docker hub.
Docker-filene for utviklingscontainer burde helst versjoneres i Git. Da får man fordelen ved at hele teamet samarbeider om å bygge og vedlikeholde utviklingsmiljøet, slik at den enkelte utvikler slipper å bruke flere timer, eller ofte dager på å sette opp å kunne kompilere kode. Man kan også få de utviklerne som er gode på spesifikke teknologier til å sette opp disse delene av utviklingsmiljøet for hele teamet, fordi de alle utvikler med den samme containeren. Dette gjør det også enda enklere å ta imot nye utviklere i et allerede etablert team ved å gi de et ferdig oppsatt utviklingsmiljø, i tillegg til at det også er lettere å bytte mellom maskiner for utvikling.
Siden Docker hovedsakelig er laget for Linux, så kan man fort lure på hvordan man skal kjøre dette på en Windows PC. Docker har en applikasjon som heter Docker Desktop som er laget for Windows og denne har en Windows Subsystem for Linux (WSL) backend. For den enkleste og raskeste utviklingen med Docker på Windows vil nok WSL være det beste valget. Dette er en Linux kernel som er integrert i Windows, slik at du kan kjøre en Linux distribusjon med direkte tilgang til hardwaren på maskinen. WSL støtter ikke grafiske applikasjoner i Windows 10, men med Windows 11 er dette støttet og våren 2022 vil det komme en oppdatering for Windows 10.
Kombinasjonen Docker, WSL og utviklingscontainere er noe som fungerer veldig bra og WSL gir nesten de samme hastighetene man kunne oppnådd med en Linux installasjon, som nok er 3-5 ganger raskere på kompilering enn en virtuell maskin. Alternativet er selvfølgelig å bruke Linux i en virtuell maskin ved bruk av VirtualBox eller liknende og installere Docker her.
Microservices er et konsept hvor man kan modularisere en applikasjon ved å isolere en uavhengig del av applikasjonen i en egen container. Bildet illustrerer en tradisjonell monolittisk struktur i forhold til en struktur basert på microservices, hvor hver microservice er en container.
Figur 3. Monolittiske applikasjoner vs microservices [Developing a monolithic service…]
Å utvikle applikasjoner med konseptet microservices er ikke noe man nødvendigvis kan gjøre på et embedded system, fordi det krever både Docker og Linux. Siden embedded systemer har begrensede ressurser er det ikke sikkert du engang har et operativsystem. Derimot vil det fortsatt kunne være et godt valg å bruke utviklingscontainere for utviklingen av embedded software og dra fordel av alt som er blitt diskutert i denne artikkelen.
Docker og containere er noe som det utvilsomt kan være komplisert å forstå, med en bratt læringskurve, men som absolutt er verdt tiden det tar å lære seg og da spesielt utviklingscontainere. Tiden man sparer på oppsett og vedlikehold av utviklingsmiljøet gjør at man kan fokusere mer på den faktiske utviklingen, i stedet for fikling med installasjoner av utviklingsverktøy.
R&D Manager