MedelMoln & infrastruktur

Docker

Docker

En plattform för att utveckla, leverera och köra applikationer i isolerade, portabla och lättviktiga containrar.

#container#virtualisering#devops#deployment#microservices

Vad är Docker?

Docker är en plattform med öppen källkod för att köra applikationer i containrar. En container innehåller applikationen tillsammans med de beroenden den behöver, vilket gör att samma applikation kan köras på utvecklarens laptop, en stagingserver eller i produktion med ett mer konsekvent beteende.

Analogin som ofta används är fraktcontainern, och den håller ganska bra. Innehållet kan variera, men själva förpackningsformen är alltid densamma. I mjukvaruvärlden är grundtanken snarlik: applikationen paketeras på ett mer enhetligt sätt så att den blir enklare att flytta och köra.

Problemet Docker löser

"It Works on My Machine"

Innan Docker fanns var det klassiska problemet enkelt: applikationen körde felfritt på utvecklarens laptop, men krånglade så fort den flyttades till en server.

Några vanliga orsaker:

  • Olika versioner av beroenden
  • Miljökonfigurationen skiljde sig åt
  • OS eller systembibliotek passade inte ihop

Docker hjälper genom att paketera applikationen tillsammans med de komponenter den behöver. Det betyder inte att alla problem försvinner, men skillnaderna mellan miljöer blir betydligt mindre.

Docker jämfört med virtuella maskiner

| Aspekt | Docker-container | Virtuell maskin | |-------|-----------------|-----------------| | Storlek | MB (megabyte) | GB (gigabyte) | | Uppstart | Sekunder | Minuter | | Prestanda | Nästan native | Märkbar overhead | | Isolering | Processnivå | Hårdvarunivå | | OS | Delar värdens kärna | Fullständigt OS per VM | | Resursanvändning | Effektiv | Tung |

Visualisering

Virtuell maskin:
┌─────────────────────────┐
│   App A   │   App B     │
├───────────┼─────────────┤
│  Guest OS │  Guest OS   │
├───────────┴─────────────┤
│     Hypervisor          │
├─────────────────────────┤
│     Host OS             │
├─────────────────────────┤
│     Hardware            │
└─────────────────────────┘

Docker:
┌─────────────────────────┐
│   App A   │   App B     │
├───────────┼─────────────┤
│ Container │ Container   │
├───────────┴─────────────┤
│    Docker Engine        │
├─────────────────────────┤
│      Host OS            │
├─────────────────────────┤
│      Hardware           │
└─────────────────────────┘

Viktiga Docker-koncept

1. Docker Image

En image är en skrivskyddad mall som innehåller instruktionerna för att skapa en container. Tänk på den som en "blueprint" eller ett "snapshot" av applikationen.

# Ladda ner image från Docker Hub
docker pull nginx:latest
docker pull node:18-alpine
docker pull postgres:15

2. Docker Container

En container är en körande instans av en image. En och samma image kan användas för att skapa många containrar.

# Kör en container från en image
docker run -d -p 8080:80 nginx:latest

# Lista körande containrar
docker ps

# Stoppa en container
docker stop <container_id>

3. Dockerfile

En instruktionsfil för att bygga en Docker-image. Ungefär som ett "recept" för att skapa en image.

# Exempel på Dockerfile för en Node.js-app
FROM node:18-alpine

# Sätt working directory
WORKDIR /app

# Kopiera package-filer
COPY package*.json ./

# Installera beroenden
RUN npm ci --production

# Kopiera källkod
COPY . .

# Exponera port
EXPOSE 3000

# Sätt miljö
ENV NODE_ENV=production

# Kommando som körs
CMD ["node", "server.js"]

4. Docker Compose

Ett verktyg för att definiera och köra applikationer med flera containrar.

# docker-compose.yml
version: '3.8'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://db:5432/myapp
    depends_on:
      - db
      - redis
  
  db:
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
  
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:
# Starta alla tjänster
docker-compose up -d

# Stoppa alla tjänster
docker-compose down

Viktiga Docker-kommandon

Hantera images

# Lista images
docker images

# Bygg image från Dockerfile
docker build -t myapp:v1 .

# Tagga image
docker tag myapp:v1 username/myapp:v1

# Pusha till registry
docker push username/myapp:v1

# Ta bort image
docker rmi myapp:v1

Hantera containrar

# Kör container
docker run -d --name myapp -p 8080:3000 myapp:v1

# Kör med miljövariabler
docker run -d -e DATABASE_URL=postgres://... myapp:v1

# Kör med volymer
docker run -d -v /host/path:/container/path myapp:v1

# Kör ett kommando i en körande container
docker exec -it myapp /bin/sh

# Visa loggar
docker logs myapp
docker logs -f myapp  # Följ loggarna

# Stoppa container
docker stop myapp

# Starta en stoppad container
docker start myapp

# Ta bort container
docker rm myapp

# Ta bort alla stoppade containrar
docker container prune

Systemkommandon

# Visa Docker-info
docker info

# Visa diskanvändning
docker system df

# Städa bort oanvända resurser
docker system prune -a

# Visa containrarnas resursanvändning
docker stats

Bästa praxis för Dockerfile

1. Använd officiella basimages

Mindre bra:

FROM ubuntu
RUN apt-get update && apt-get install -y nodejs

Bättre:

FROM node:18-alpine

2. Minimera antalet lager

Mindre effektivt:

RUN apt-get update
RUN apt-get install -y git
RUN apt-get install -y curl

Mer effektivt:

RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

3. Flerstegsbyggen (multi-stage builds)

För att minska den slutliga image-storleken:

# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]

4. .dockerignore-fil

Exkludera filer från byggkontexten:

# .dockerignore
node_modules
npm-debug.log
.git
.env
.DS_Store
dist
coverage
*.md

5. Säkerhetspraxis

# Kör inte som root
FROM node:18-alpine

# Skapa en icke-root-användare
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

WORKDIR /app
COPY --chown=nodejs:nodejs . .
RUN npm ci --production

# Byt till icke-root-användaren
USER nodejs

EXPOSE 3000
CMD ["node", "server.js"]

Docker-nätverk

Bridge-nätverk (standard)

Containrar i samma nätverk kan kommunicera via namn.

# Skapa ett eget nätverk
docker network create mynetwork

# Kör containrar i samma nätverk
docker run -d --name db --network mynetwork postgres
docker run -d --name app --network mynetwork myapp

# App kan ansluta till db via: postgres://db:5432

Portmappning

# Mappa containerport till värdens port
docker run -p 8080:3000 myapp  # host:container

# Flera portar
docker run -p 8080:3000 -p 8081:3001 myapp

# Alla portar
docker run -P myapp

Docker-volymer

För beständig datalagring:

Namngivna volymer

# Skapa volym
docker volume create mydata

# Använd volym
docker run -v mydata:/app/data myapp

# Lista volymer
docker volume ls

# Inspektera volym
docker volume inspect mydata

Bind mounts

Montera en katalog från värden i containern:

# Utveckling: live reload
docker run -v $(pwd):/app myapp

# Windows
docker run -v %cd%:/app myapp

Praktiska användningsfall

1. Utvecklingsmiljö

# docker-compose.dev.yml
version: '3.8'
services:
  app:
    build: .
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
    command: npm run dev

2. Microservices-arkitektur

version: '3.8'
services:
  frontend:
    image: myapp/frontend
    ports:
      - "80:80"
  
  api-gateway:
    image: myapp/api-gateway
    ports:
      - "8080:8080"
  
  user-service:
    image: myapp/user-service
  
  product-service:
    image: myapp/product-service
  
  order-service:
    image: myapp/order-service

3. CI/CD-integration

# .github/workflows/docker.yml
name: Docker Build and Push
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .
      
      - name: Push to registry
        run: |
          echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
          docker push myapp:${{ github.sha }}

Docker i produktion

Orkestreringsverktyg

För att hantera containrar i skala:

  1. Docker Swarm - Dockers inbyggda orkestrering
  2. Kubernetes - Det vanligaste valet för containerorkestrering
  3. AWS ECS - Amazons containertjänst
  4. Google Cloud Run - Serverlösa containrar

Health checks

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/health || exit 1

Resursbegränsningar

# Begränsa minne och CPU
docker run -m 512m --cpus=1 myapp

Docker för utvecklare

Fördelar

  1. Mer konsekvent miljö - Dev, staging och produktion skiljer sig inte lika mycket åt
  2. Bättre isolerade projekt - Beroenden mellan projekt krockar inte lika lätt
  3. Snabbare setup - Nya projekt kan köras utan lång manuell installation
  4. Smidigare samarbete - Teamet använder en i stort sett likadan miljö
  5. Säkrare experiment - Enklare att prova databaser, meddelandekö eller andra tjänster

Utmaningar

  1. Kräver inlärning i början - Koncept som image, container, volym och nätverk tar tid att förstå
  2. Kräver lagringsutrymme - Images och volymer kan snabbt växa sig stora
  3. Viss overhead på Windows eller macOS - Vanligtvis via Docker Desktop
  4. Nätverksfelsökning kan kännas förvirrande - Särskilt i början

Tips för att komma igång med Docker

  1. Börja med en enda tjänst - Flytta inte hela systemet på en gång
  2. Använd officiella images - Säkrare att lära sig på, och dokumentationen brukar vara bättre
  3. Lär dig Docker Compose - Till stor hjälp när applikationen har flera tjänster
  4. Prova i ett projekt du redan känner till - Lättare att förstå hur beteendet ändras
  5. Följ communityn - Många vardagsproblem löses snabbare genom diskussioner med andra utvecklare

Alternativ till Docker

  • Podman - Daemonless, rootless containrar
  • LXC/LXD - Systemcontainrar
  • rkt - Alternativ container-runtime (utfasad)
  • containerd - Kärnan i container-runtimen (används av Docker internt)

Docker med smbCloud

smbCloud stödjer Docker-baserad deployment utan ett långdraget setup-flöde.

# smbCloud identifierar Dockerfile automatiskt
$ cat Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "start"]

$ git push smb main
# smbCloud bygger image och deployar automatiskt

Fördelar:

  • Inget behov av att sätta upp ett eget Docker-registry för grundflödet
  • Image kan byggas direkt från Dockerfile
  • Containern kan skalas via plattformens funktioner
  • Grundläggande övervakning finns redan på plats

Felsökning av vanliga problem

Container avslutas direkt

# Kontrollera loggar
docker logs <container_id>

# Kör interaktivt för att felsöka
docker run -it myapp /bin/sh

Porten används redan

# Hitta processen som använder porten
lsof -i :8080  # Mac/Linux
netstat -ano | findstr :8080  # Windows

# Döda processen eller använd en annan port
docker run -p 8081:3000 myapp

Diskutrymmet är slut

# Ta bort oanvända images
docker image prune -a

# Ta bort oanvända volymer
docker volume prune

# Städa allt
docker system prune -a --volumes

Slutsats

Docker hjälper utvecklare att köra applikationer i en mer konsekvent miljö. Därför används Docker ofta för utveckling, testning, CI/CD och ända fram till deployment.

Om du precis har börjat behöver du inte tänka på stora kluster eller komplexa arkitekturer direkt. Börja med en enda applikation, förstå Dockerfile, skilj på image och container, och prova sedan att köra flera tjänster med Compose. Efter det brukar de mer avancerade koncepten kännas betydligt mer begripliga.

Relaterade termer

Fler inom Moln & infrastruktur

Kom igång

Redo att bygga med smbCloud?

Distribuera Node.js, Swift och Ruby med ett enda kommando.

Kom igång med smbCloud →

Senast uppdaterad: 15 januari 2024