Introductie
In een wereld waar je makkelijk een nieuw hoesje om je telefoon doet als je even wat anders wilt, computerchips modulair worden opgebouwd om ze beter te laten schalen en laptops die hardwarematig aanpasbaar zijn door de consument, heeft Docker een plek weten te bemachtigen in de softwareontwikkeling wereld, en niet geheel zonder goede reden.
Als een softwareontwikkelaar ben je vrijwel altijd bezig met het aanpassen of het bouwen van een nieuw product voor je bedrijf, of voor een klant. Maar bij het op de markt zetten van zo’n stuk software komt natuurlijk een stuk meer kijken. Om maar een paar dingen te noemen moet je al zorgen dat het juiste besturingssysteem draait, de juiste afhankelijke software geïnstalleerd is en de juiste poorten open staan naar de buitenwereld. Dit neemt veel tijd in beslag aangezien er vaker uitzonderingen zijn in plaats van dat alles volgens het boekje gaat. En daarbij is zeker de definitie “long tail” van toepassing. Het werkend krijgen van de laatste 20% neemt vaak 80% van je tijd in beslag.
Maak kennis met: Docker
Docker biedt hierin uitkomst. Zij bieden namelijk al 8 jaar een oplossing om deze 80% van je tijd makkelijker te maken! Dit o.a. door de mogelijkheid om snel testservers op te zetten bij mede ontwikkelaar en testers. De tijd van configureren en installeren verminderen is natuurlijk waardevol, maar dit is slechts een deel van de kracht van Docker.
Docker kan namelijk ook ondersteuning bieden in een deel van het vraagstuk waar veel mensen tegenaan lopen: Firewall security.
Als we namelijk kijken naar hoe Docker origineel geïnstalleerd wordt, wordt er één Docker netwerk, genaamd docker0 aangemaakt. Deze wringt zich in de beveiligingsregels van het netwerk. Dit netwerk staat in “Bridge” modus zodat het poorten openzet in de firewall die aangegeven worden in het Dockerfile bestand of in het docker-compose bestand. Dit is gedaan om het gemakkelijk te maken Docker containers zichtbaar te maken naar de buitenwereld op de “host”.
Het zichtbaar maken van de containers doe je door vervolgens een -p <poort:poort> parameter toe te voegen aan het docker run commando om de container online te zetten. In de praktijk betekent dit wanneer er bijvoorbeeld een React applicatie op poort 8080 draait, Docker er voor zorgt ervoor onderwater de poort 8080 in de firewall wordt open gezet.
Iedere ontwikkelaar en software beveiliging specialist zal je direct vertellen dat poorten naar buiten openzetten op een poort anders dan 80 en 443 een risico vormt, maar wat is hier de oplossing dan voor als Docker dit automatisch doet?
Een van de oplossingen is zelf een regel in de firewall maken om de poort te blokkeren, en een reverse proxy zoals NGINX, Apache of HAProxy te installeren en de applicatie via de reverse proxy open te stellen op poort 443 of poort 80 op een (sub-)domein. Een andere oplossing is om de poort direct aan poort 80 te binden door -p 80:8080 te gebruiken. Nog een andere oplossing is om de poort niet open te zetten en dus het -p commando weg te laten.
Deze oplossingen werken zeker, alleen vergt het bij de eerste oplossing eigenlijk veel werk voor iets wat eigenlijk niet eens een probleem hoeft te zijn. Bij de tweede oplossing is daarmee direct poort 8- niet meer beschikbaar om eventuele andere applicaties op te draaien, en bij de laatste oplossing is, de webserver in dit geval, niet meer bereikbaar van buiten het netwerk. Maar er is ook een oplossing op de Docker manier: de Docker registry bevat namelijk al images van de meest bekende proxies die gebruikt worden. Wat je hiermee kunt bereiken is dat de proxy wordt gestart met de -p 80:80 -p 443:443 parameters, en de React applicatie wordt gestart met het commando EXPOSE 8080 bovenaan in het Dockerfile of docker-compose bestand. Dit zorgt ervoor dat de container met de React applicatie wel binnen Docker te bereiken is door andere containers zoals in dit geval de proxy, maar Docker opent verder geen poorten in de firewall om deze naar buiten te publiceren. Een voorbeeld van zo’n configuratie is hieronder te zien als docker-compose.yml:
Om de mogelijkheden even op te sommen:
- Ports / -p: Zet de gespecificeerde poorten open in de firewall zodat ze van buiten Docker te bereiken zijn.
- Expose: Zet de poorten open binnen het Docker netwerk zodat de container aangesproken kan worden door andere containers binnen het Docker netwerk, maar de container zal niet direct aan te spreken zijn op de gespecificeerde poort buiten het Docker netwerk.
- Geen expose / ports: De container zal volledig geïsoleerd zijn van de buitenwereld, en de poorten zijn niet aan te roepen door zowel de buitenwereld en andere containers binnen het Docker netwerk.
Conclusie
Docker maakt het makkelijk om software geïsoleerd te draaien. Maar als je gewoon in Docker duikt na de tutorial online te hebben gelezen en je snel een service wilt neerzetten, kan je wel eens terecht komen in een situatie waar je beveiliging niet meer op order is zonder dat je er erg in hebt.
Het is dus erg belangrijk dat je begrijpt wat Docker standaard onderwater doet, en hoe je het zelf kan manipuleren zodat het werkt naar behoren. Er valt nog veel meer te vertellen over netwerkbeheer in Docker, maar dat is een onderwerp voor de volgende keer.