Från 3 dagar till 5 minuter: Hur Docker Compose sparar 150 000 euro per år åt min kund

Sammanfattning av ledningen

Inom modern mjukvaruutveckling kostar det i genomsnitt 2-3 dagar per team och releasecykel att sätta upp utvecklings-, test- och acceptansmiljöer. För ett utvecklingsteam på 7 personer innebär det en kostnad på över 150 000 euro per år - ren väntetid, inget mervärde.

Med en väl genomtänkt Docker Compose-installation kan denna process reduceras till mindre än 5 minuter. Den här artikeln använder ett riktigt SaaS-projekt för att visa hur detta fungerar - tekniskt sunt, men pragmatiskt realiserbart.

Viktiga slutsatser:

  • ROI: 99% tidsbesparing vid installation av miljöer
  • Infrastruktur som kod: Enhetlighet från utveckling till produktion
  • Fältbeprövad installation för komplexa multiservice-arkitekturer
  • Säkerhetshärdning utan komplexitetsökning

Måndagen då ingenting fungerade

Klockan är 9.00 på måndag morgon. Utvecklingsteamet är redo, sprintplaneringen är klar, användarberättelserna har prioriterats. Men så kommer beskedet: "Vi måste installera den nya testmiljön innan vi kan börja."

Alla som arbetar med mjukvaruutveckling vet vad som följer:

Den första utvecklaren installerar Postgres - version 16, eftersom det är den senaste versionen. Den andra sätter upp Redis - med andra konfigurationsparametrar än i produktionen. Den tredje kämpar med MinIO eftersom bucket-namnen inte är korrekta. Och DevOps-ingenjören försöker desperat få igång Traefik medan alla andra väntar.

Vid lunchtid på tisdagen är allt äntligen igång. Nästan. Versionerna stämmer inte överens, konfigurationen skiljer sig från produktionen och nästa uppdatering börjar om från början igen.

Lagförslaget är brutalt:

  • 7 utvecklare × 16 timmar × 80 euro/timme = 8 960 euro för EN miljö
  • × 3 miljöer (utveckling, test, godkännande) = 26 880 euro
  • × 6 release-cykler per år = 161 280 euro

Och detta är bara de direkta kostnaderna. De är inte inkluderade: Frustration, byte av sammanhang, försenade releaser.

Lösningen på problemet: Infrastruktur som kod - men på rätt sätt

"Varför använder ni inte bara Docker?" - En berättigad fråga, men den räcker inte långt. Docker i sig löser inte problemet. Kubernetes? Overkill för de flesta projekt och ofta mer komplext än det ursprungliga problemet.

Svaret ligger i mitten: Docker Compose som "Infrastructure as Code Light".

Med en välstrukturerad Docker Compose-installation blir tre dagars installationshelvete ett enda kommando:

git klon projekt-repo
docker compose --profil dev up -d

5 minuter senare: Alla tjänster körs, är konsekvent konfigurerade och har rätt versioner.

Låter det för bra för att vara sant? Låt oss ta en titt på hur det ser ut i praktiken.

Stacken: ett verkligt SaaS-exempel

Vårt exempel kommer från ett verkligt projekt - en modern SaaS-applikation med typisk mikroservicearkitektur:

Front-end nivå:

  • Traefik som omvänd proxy och SSL-terminering med Let's Encrypt
  • React UI med Vite, TypeScript, ShadCN och TailwindCSS

Backend-nivå:

  • Spring Boot Microservice som API-lager
  • PostgreSQL för relationsdata
  • Weaviate Vector-DB för inbäddningar och semantisk sökning
  • Redis för cachelagring och sessionshantering
  • MinIO som S3-kompatibel objektlagring
  • OpenAI API-integration för AI-stödda funktioner

Åtta tjänster, tre databaser, AI-integration, komplexa beroenden. Exakt den typ av installation som normalt tar flera dagar.

Så här ser det ut i praktiken:

Illustration: Alla tjänster körs i Docker Compose med strikt nätverksseparation mellan webb- och backend-lagren.

Hela installationen börjar med ett enda kommando: docker compose up -d_

Hemligheten: profiler och miljöseparering

Nyckeln ligger i den intelligenta användningen av Docker Compose Profiles. Vi skiljer mellan två lägen:

Dev-profil: Endast backend-tjänster körs i containern

  • Frontend körs lokalt (snabb omladdning, snabb utveckling)
  • Databaser och externa tjänster i container
  • Portar exponerade för direktåtkomst med GUI-verktyg

Produktprofil: Full stack

  • Alla tjänster i container
  • Traefik-routing med SSL
  • Nätverksisolering mellan webb och backend
  • Säkerhetsförstärkning aktiv

En enkel export COMPOSE_PROFILES=dev bestämmer vilka tjänster som ska starta. Ingen separat compose-fil, ingen duplicering, inga inkonsekvenser.

De underskattade spelförändrarna

Utöver de uppenbara fördelarna finns det tre aspekter som gör störst skillnad i praktiken:

1. "Rent bord" med en knapptryckning

Alla känner till problemet: utvecklingsmiljön har varit igång i flera veckor. Tester har körts, data har ändrats manuellt, felsökningssessioner har lämnat sina spår. Plötsligt beter sig systemet annorlunda än förväntat - men är det koden eller den "smutsiga" datan?

Med Docker Compose:

docker compose down -v
docker compose up -d

30 sekunder senare: En helt ny miljö. Inga gamla problem, inga artefakter, inget "men det fungerar för mig". Det är skillnaden mellan "låt oss prova" och "vi vet att det fungerar".

2. Automatisk skapande av databas med Flyway

Databasen är inte tom när den startas. Flyway-migrationer körs automatiskt vid uppstart:

  • Schemaändringar importeras
  • Frödata för tester är laddade
  • Versionering av DB-strukturen är en del av koden

En ny utvecklare får inte bara en DB som körs, utan en DB i exakt rätt skick - inklusive alla migreringar som har ägt rum under de senaste månaderna.

3. Justera produktionsfel - inom 5 minuter

"Felet uppstår endast hos kunder som fortfarande använder version 2.3." - Varje utvecklares mardröm.

Med Docker Compose:

export CV_APP_TAG=2.3.0
export POSTGRES_TAG=16
docker compose up -d

Den exakta produktionsmiljön körs lokalt. Samma versioner, samma konfiguration, samma databasmigreringar. Felet är reproducerbart, debuggbart, korrigerbart.

Ingen VM, ingen komplex installation, ingen vecka av förberedelser. Supportsamtalet kommer in, 5 minuter senare är utvecklaren igång med felsökning i kundens exakta installation.

Traefik: Mer än bara en omvänd proxy

En detalj som ofta förbises: Traefik körs i en separat container och är inte en del av definitionen av servicestacken. Detta har en avgörande fördel.

I små till medelstora produktionsmiljöer kan denna enda Traefik-container fungera som lastbalanserare för flera applikationer:

# En Traefik för alla projekt
traefik-behållare → cv-app-stack
                 → crm-app-stack
                 → analytics-app-stack

Istället för att konfigurera och underhålla tre separata lastbalanserare (eller tre nginx-instanser), hanterar en enda Traefik alla routningsregler. SSL-certifikat? Let's Encrypt tar hand om detta automatiskt - för alla domäner.

Installationen kan skalas på ett elegant sätt: från ett projekt på en server till flera stackar - utan att arkitekturen behöver ändras.

Säkerhet: Pragmatisk i stället för dogmatisk

"Men är inte öppna databasportar en säkerhetsrisk?" - En helt berättigad fråga.

Svaret ligger i sammanhanget: utveckling och test är inte produktion.

I utvecklings- och testmiljöer:

  • Portarna är avsiktligt exponerade för felsökning
  • Utvecklare använder GUI-verktyg (DBeaver, RedisInsight, MinIO Console)
  • Miljöerna körs i isolerade, icke-publika nätverk
  • Avvägning: utvecklarens produktivitet kontra teoretisk risk

I produktion:

  • Åtkomst endast via VPN eller bastion host
  • Strikta brandväggsregler
  • Övervakning och varning
  • Samma compose-fil, olika miljövariabler

Här görs ofta misstaget att säkra utvecklingsmiljöerna som Fort Knox, medan utvecklarna sedan kämpar med SSH-tunnlar och port forwarding. Resultatet: bortkastad tid och frustrerade team.

Tricket är att hitta rätt avvägning.

Säkerhetshärdning: där det räknas

Där vi inte gör några kompromisser: Containersäkerhet.

Varje tjänst kör med det:

  • Skrivskyddat filsystem: Förhindrar manipulation i körtid

  • Icke-root-användare (UID 1001): Minimiprivilegier

  • Tappade förmågor:cap_drop: ALLA - bara det som verkligen behövs

  • Inga nya privilegier: Förhindrar upptrappning av privilegier

  • tmpfs för temporär data: Begränsat, flyktigt minne

    cv-app: användare: "1001:1001" read_only: true tmpfs: - /tmp:rw,noexec,nosuid,nodev,storlek=100m säkerhet_opt: - no-new-privileges:true cap_drop: - ALL

Detta är inte en extra kostnad - det är en standardkonfiguration som konfigureras en gång och sedan gäller för alla miljöer.

Isolering av nätverk: Försvar på djupet

Två separata Docker-nätverk skapar tydliga gränser:

Webb-nätverk: Riktad mot Internet

  • Traefik Proxy
  • UI-tjänst
  • API-gateway

Backend-nätverk: Endast internt

  • Databaser (Postgres, Redis, Weaviate)
  • Objektlagring (MinIO)
  • Interna tjänster

En komprometterad container i webbnätverket har ingen direkt tillgång till databaserna. Försvar på djupet - implementerat i praktiken, inte bara på bilder.

Miljövariabler: Det underskattade problemet

En aspekt som ofta förbises: Hur hanterar du konfigurationen i olika miljöer?

Den dåliga lösningen: Lö senord i Git-arkivet Den komplicerade lösningen: Vault, Secrets Manager, komplexa verktygskedjor Den pragmatiska lösningen: Etappspecifika .env-filer utanför Git

.env.dev # För lokal utveckling
.env.test # För testmiljö
.env.staging # För acceptans
.env.prod # För produktion (lagras i krypterad form)

En enkel källa .env.dev före docker komponera upp - klar.

För produktion: Hemligheter injiceras via CI/CD-pipeline eller lagras krypterade med SOPS/Age. Men inte alla miljöer behöver hemlighetshantering i företagsklass.

Arbetsflödet i praktiken

Ny utvecklare i teamet:

git clone projekt-repo
cp .env.example .env.dev
# Ange API-nycklar
docker compose --profil dev up -d

4 kommandon, 5 minuter - utvecklaren är produktiv.

Driftsättning i test:

ssh test-server
git dra
docker compose --profil prod pull
docker compose --profil prod up -d --force-recreate

Driftsättning utan nedtid? Hälsokontroller i compose-filen tar hand om detta:

hälsokontroll:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
  intervall: 30s
  timeout: 10s
  nya försök: 3
  start_period: 60s

Docker väntar tills tjänsterna är friska innan gamla behållare stoppas.

Lärdomar: Vad jag skulle göra annorlunda

Efter flera projekt med den här installationen - några insikter:

1. Investera tid i den första komponeringsfilen De första 2-3 dagarna av installationen kommer att betala sig hundrafalt under projektets gång. Varje timme här sparar dagar senare.

2. Hälsokontroller är inte valfria Utan hälsokontroller kan du starta tjänster innan DB är redo. Detta leder till mystiska fel och felsökningssessioner.

3. Version pinning är din vänpostgres:senaste är bekvämt - tills en uppdatering förstör allt. postgres:17 skapar reproducerbarhet.

4. Dokumentera dina avvägningar Varför är portarna öppna? Varför det här tillvägagångssättet istället för det andra? Du (och ditt team) kommer att tacka dig i framtiden.

5. En compose-fil, flera steg Försöket att upprätthålla separata compose-filer för varje miljö slutar i kaos. En fil, styrd via Env-variabler och profiler.

Avkastningen på investeringen: övertygande siffror

Tillbaka till vårt måndagsmorgonscenario. Med Docker Compose:

Innan:

  • Installationstid: 16-24 timmar per framkallare
  • Bristande överensstämmelse mellan miljöer: ofta
  • Felsökning av miljöproblem: flera timmar per vecka
  • Kostnader per år: 160 000+ euro

Efteråt:

  • Installationstid: 5 minuter
  • Inkonsekvenser: praktiskt taget eliminerade
  • Felsökning av miljöproblem: sällsynt
  • Kostnader för initial installation: ca 16 timmar = 1 280 euro
  • Besparingar under det första året: 158.720 euro

Och då har vi inte ens tagit hänsyn till de mjuka faktorerna: Mindre frustration, snabbare introduktion, mer tid för funktioner i stället för infrastruktur.

Vem är det lämpligt för?

Docker Compose är inte en silverkula. Det passar inte för:

  • Högskaliga mikrotjänstarkitekturer (100+ tjänster)
  • Driftsättning i flera regioner med komplex routing
  • Miljöer som kräver automatisk skalning

Den är perfekt för:

  • Start-ups och scale-ups med upp till 50 utvecklare
  • SaaS-produkter med 5-20 tjänster
  • Byråer med flera kundprojekt
  • Alla team som slösar tid på att installera miljön

Vägen till skalning: från Compose till Kubernetes

En ofta underskattad fördel: Docker Compose är inte en investering i en återvändsgränd. Om ditt projekt växer och behöver riktiga Kubernetes är det förvånansvärt enkelt att migrera.

Varför är det så? För att containerstrukturen redan finns på plats:

  • Bilderna är byggda och testade
  • Miljövariabler är dokumenterade
  • Nätverkstopologin är definierad
  • Hälsokontroller genomförs

Verktyg som Kompose konverterar automatiskt Compose-filer till Kubernetes-manifest. Migreringen är inte en omskrivning, utan ett lyft och en förskjutning.

Rekommendationen: Börja med Compose. Om du verkligen behöver Kubernetes (inte för att det låter coolt på konferenser, utan för att du har verkliga problem) har du en solid grund för migreringen. Fram till dess: Håll det enkelt.

Det första steget

Frågan är inte om Docker Compose är rätt verktyg. Frågan är: Hur mycket tid slösar ditt team för närvarande på att konfigurera miljön?

Räkna ut det:

  • Antal utvecklare × timmar för installation × timpris × antal installationer per år

Om det är ett fyrsiffrigt belopp är det värt att investera. Om det är femsiffrigt borde du ha börjat redan igår.


Om författaren: Andre Jahn hjälper företag att optimera sina utvecklingsprocesser och på ett pragmatiskt sätt implementera Infrastructure as Code. Med över 20 års erfarenhet av mjukvaruutveckling och DevOps ligger fokus på lösningar som faktiskt fungerar - inte bara på bilder.

Ytterligare
Ytterligare

Digital suveränitet