”Installera en Linux-virtuell maskin och bygg upp exakt samma miljö.”
Tre månader efter att jag började på företaget var stämningen på kontoret märklig. Teamets enda senior hade blivit omplacerad till ett annat projekt och var så upptagen med att packa sina egna saker att någon ordentlig överlämning knappt gick att tänka på, medan teamleaden hade varit borta från praktiskt utvecklingsarbete länge och stod ganska långt ifrån de senaste tekniktrenderna.
En dag kallade teamleaden på mig. ”När din senior försvinner är du den enda som kommer att kunna sköta servrarna. Även om servern kraschar måste du kunna återställa den själv. Installera Linux som en virtuell maskin, VM, på din nuvarande utvecklingslaptop, Windows, och försök bygga exakt samma miljö som produktionsservern.”
Där började mitt slit. Jag installerade VMware, laddade ner Ubuntu-ISO:n, och bara installationen tog en halv dag. Jag grävde i företagets wiki för att installera Java, Node.js och PostgreSQL. Jag tänkte: ”Nyare måste vara bättre”, så jag installerade Java 17, bara för att upptäcka att legacy-koden byggde på Java 8 och inte ens gick att bygga. Jag fick radera allt och installera om. Varje gång jag ändrade en enda rad kod behövde jag köra mvn build, flytta jar-filen till VM:n och köra den där. Det var ren plåga.
Då slog en fråga mig plötsligt. ”Vänta lite. Senast vi deployade till produktionsservern, räckte det inte att bara skriva en enda docker service update-rad?”
Min lokala virtuella maskin var så här tung och krävde en hel hög med inställningar, så vad var egentligen det där ‘Docker’ på produktionsservern som kunde uppdatera allt med ett enda kommando?

Den tunga lösningen: den virtuella maskinen
Metoden som teamleaden bad mig använda, alltså att installera Linux ovanpå Windows, är precis vad en virtuell maskin, VM, är. Det är som att bygga ett helt ‘virtuellt hus’, ett guest OS, ovanpå en fysisk dator, hosten.
- Metod: man kör flera operativsystem på en och samma dator. (Linux ovanpå Windows, och ovanpå det ännu ett Linux…)
- Problem: för att bygga ett hus måste man bygga allt på nytt, ända ner till pelare, väggar och badrum (kärnan).
- Bara för att köra en enda app måste man installera ett helt operativsystem på flera gigabyte.
- Uppstarten tar en evighet. (Det är därför min laptop blev så långsam)
- Resurserna används ineffektivt. (Även när den inte gör någonting äter den minne bara för att hålla OS:et igång)
I slutändan isolerar en VM miljön på ett tillförlitligt sätt, men för utveckling eller deployment är den helt enkelt för tung och för långsam för att skickas fram och tillbaka varje gång.
Den lätta revolutionen: Docker
Det var därför Docker dök upp, alltså containertekniken. Docker bygger inte ett helt hus som en VM gör. I stället sätter den upp ett tält.
- Metod: den delar gården (kärnan) i ett redan byggt hus (host-OS, Linux) och slår bara upp ett isolerat tält (container).
- Egenskaper:
- Delar OS:et (kärnan): inne i tältet finns inget tungt operativsystem, bara min app och dess bibliotek.
- Lätt: storleken räknas i megabyte (MB).
- Snabb: uppstart? Något sådant finns inte. Den startar lika snabbt som när man startar en vanlig process (millisekunder).
Kommandot update som jag körde på produktionsservern installerade alltså inte om ett tungt operativsystem. Det innebar bara att ”ta ner det gamla tältet och resa ett nytt tält med den nya kodversionen i.” Klart att det kunde bli färdigt nästan direkt.

[Code Verification] Är Docker verkligen så lätt?
Låt oss inte bara säga att Docker är lätt, utan faktiskt kontrollera det. Om målet är att köra en Linux-, Ubuntu-, miljö är skillnaden mellan en VM och Docker dramatisk.
- Köra Ubuntu i en VM: ladda ner ISO-filen (2GB) -> installera (20 minuter) -> starta (1 minut).
- Köra Ubuntu med Docker:
# Kor Ubuntu via Docker-kommando (laddar ner image om den saknas)
$ docker run -it ubuntu:latest /bin/bash
Resultat:
- Nedladdning: cirka 30MB (en avskalad image, ett tunt skal med bara det allra nödvändigaste från Ubuntu)
- Starttid: cirka 0,5 sekunder
I samma ögonblick som jag tryckte Enter befann jag mig redan i en Ubuntu-miljö. Det är möjligt därför att en Docker-container inte är ett riktigt operativsystem. Den är bara ”ett isolerat utrymme som lånar kärnan från host-OS, alltså min dator, samtidigt som den låtsas vara ett separat OS.”
Praktiskt råd: den verkliga anledningen att använda Docker
När vi väl införde Docker i det dagliga arbetet förändrades mitt liv helt.
- ”Sätt upp din miljö” försvann: förr fick en nyanställd ett dokument på tio A4-sidor med beskedet ”Installera Java, ställ in miljövariablerna, installera databasen…”. Nu säger vi bara: ”Installera Docker och skriv
docker-compose up.” - Flykten från versionshelvetet: vad gör man om projekt A måste använda Java 8 och projekt B Java 17? Installerar man båda lokalt blir det konflikter och allt trasslar ihop sig. Med Docker kan du lägga Java 8 i container A och Java 17 i container B och köra dem samtidigt utan minsta problem, eftersom de är fullständigt ‘isolerade’ (isolation) från varandra.
Avslutning: vi levererar inte en körbar fil, utan en “miljö”
Med Docker förändrades utvecklingens paradigm. Vi skickar inte längre bara källkoden, .java, till servern. Vi fryser även OS-inställningar, bibliotek och miljövariabler som koden behöver till en ‘image’ och skickar hela paketet.
Men hur byggs egentligen denna nästan magiska ‘Docker image’? Är det bara en komprimerad fil? Överraskande nog sägs en Docker image vara uppbyggd i flera lager, layers, som en tårta.
Nästa gång ska vi gräva i hemligheten bakom Dockers effektivitet: images och deras lagerstruktur.


