Docker gebruiken voor development

Docker

Als consultant heb ik de afgelopen jaren aan verschillende softwareprojecten gewerkt. Hierdoor heb ik kennis gemaakt met hele uiteenlopende bedrijven. Van startups en grote softwarebedrijven tot bedrijven die een softwareproject naast hun core business runnen. Ik heb geleerd dat software ontwikkelen op veel verschillende manieren kan. Ook ben ik nog geen projecten tegen gekomen die precies hetzelfde zijn.

Doordat ik aan veel verschillende projecten werk, loop ik tegen wat dingen aan. Om te kunnen ontwikkelen wil ik de applicatie en dependencies lokaal kunnen draaien. Vaak is er een beschreven ‘Build and run’ pagina op Confluence, of ergens in een Dropbox map. Deze pagina legt uit hoe de dependencies op de development machine  geïnstalleerd moet worden. Toch ben ik al snel uren bezig om een ontwikkelomgeving de eerste keer op te zetten. Wat hierbij bijvoorbeeld mis kan gaan is:

  • De “Build and run” is geschreven voor Windows, in macOS werkt het dan net weer iets anders.

  • Een ander project waar je aan werkt maakt gebruik van dezelfde dependency maar dan net een andere versie die niet zomaar verhoogd kan worden.

  • Het project gebruikt bijvoorbeeld SQL server en dat draait niet op macOs.

Als de ontwikkelomgeving opgezet is voor het project moet ik mijn OS kunnen updaten en eenvoudig kunnen switchen tussen projecten. Dit verliep ook niet altijd soepel. Kan dit niet eenvoudiger?

Het blijkt dat er tools zijn die ons leven hier wat makkelijker kunnen maken en Docker is daar één van.

Docker

Docker is open-source software waarmee het mogelijk wordt een applicatie in een lichtgewicht en verplaatsbare container te verpakken. Het concept is hetzelfde als een virtual machine maar het is veel lichter en sneller. Dit komt omdat een docker container gebruik maakt besturingssysteem en dependencies die op de host beschikbaar zijn. Hierdoor kan de container zelf veel kleiner gehouden worden. Een container heeft een geïsoleerde environment, hierdoor ontstaan er geen conflicten met dependencies op de host of met andere containers.

Een container wordt opgebouwd op basis van een image. Dat is de “blauwdruk” van de container. Er zijn veel images beschikbaar, deze zijn te vinden in Docker Hub. Zo zijn er bijvoorbeeld images voor frameworks (bijv. Angular, Spring boot en Django), databases (mongoDB, MySQL en PostgreSQL), servers (Tomcat en Nginx) maar ook complete applicaties als SonarQube, Jenkins en Sentry.

Er zijn al veel images beschikbaar. Je kunt bijna voor alles wat je nodig hebt voor het ontwikkelen, bouwen en draaien van een applicatie een container gebruiken. Stel je applicatie heeft een PostreSQL database nodig. Die kun je lokaal installeren… maar je kunt hier ook een container voor opstarten.

Het starten van een container kan met één commando. Met het commando hieronder starten we een PostreSQL database:

sql
$ docker run --name postgres-container -e POSTGRES_PASSWORD=mysecretpassword -d postgres

In het commando hierboven wordt een container gemaakt met de laatste versie van postgres. Wanneer het postgres image lokaal nog niet bestaat zal het image van Docker Hub gedownload worden. De run opties die in het commando worden gebruikt, worden hieronder uitgelegd:

  • –name geeft de container een naam zodat je hem later makkelijker kunt terugvinden.

  • -e zet de environment variabele als key=value

  • -d runt container in de achtergrond (detached mode)

Door middel van run opties in het commando is het mogelijk de database en container te configureren.

Met één commando draait er dus een PostreSQL database waar je applicatie mee kan verbinden.

Als in het commando veel geconfigureerd moet worden, wordt dit een complex commando. Je kunt je voorstellen dat een applicatie meerdere dependencies en dus containers nodig heeft. Om dit proces te vereenvoudigen gebruiken we Docker Compose.

Docker Compose

Docker Compose is een tool om containers te definiëren en runnen. Dit gebeurd via een docker-compose.yml file. In het bestand worden alle services beschreven die gestart moeten worden, de configuratie en de afhankelijkheden tussen de containers. De postgres container starten doen we op de volgende manier:


sql
version: '3.1' 

services:

  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD:  mysecretpassword

De configuratie van de container moet nog steeds beschreven worden maar dit gebeurd nu niet in het commando maar in een Compose file. De Compose file zetten we in version control zodat alle teamleden het kunnen gebruiken. Nu kunnen we alle services starten door middel van één commando:


sql
$ docker-compose up

stoppen kan door middel van:

 

sql
$ docker-compose down

Tot slot

In het voorbeeld hierboven wordt alleen het opzetten van een database beschreven. Dit is in sommige gevallen al voldoende. Docker is een krachtige tool maar dat betekent niet dat je niet eenvoudig kunt beginnen door bijvoorbeeld alleen je databases in Docker te draaien. Je kunt dit later uitbreiden met meerdere containers bijvoorbeeld voor caching of het serveren van je content over http. Het is zelfs mogelijk om de applicatie niet lokaal maar in bijvoorbeeld een Gradle container te laten bouwen. Je kunt het project zo opzetten dat Docker, Docker Compose en je favoriete IDE de enige dependencies zijn die je machine nodig heeft en dat je met één commando de hele ontwikkelomgeving hebt draaien.

Ik ben pas sinds kort bekend met Docker, maar het heeft mijn leven als ontwikkelaar in elk geval al een stuk makkelijker gemaakt. Probeer het eens uit en misschien kan het ook wat voor jou development process betekenen.

Docker