.net in the box

.NET Usergroup Rhein/Ruhr

24.05.2017

Frank Pommerening

  • Senior - Softwareentwickler
  • Consultant
  • Softwarearchitekt


frank@pommerening-online.de
AXP Consulting GmbH & Co. KG in Leipzig
Gründung: Mai 2012
Anzahl Mitarbeiter: 8 feste
Branchenfokus: Energiebranche


  • Consulting (fachlich & IT)
    • Requirements Engineering / Projektmanagement
    • IT-Fachprozess-Analyse / Dokumentation
  • Software-Entwicklung
    • Microservices, SOA, REST, OOA und OOD
    • Microsoft Technologien z.B. .NET (C#), WPF, WCF
    • Datenbanken (MS SQL Server / Oracle / MongoDB)

Docker im Überblick

Was ist Docker?

Anwendungsvirtualisierung: Anwendungen werden unter Verwendung von Betriebssystemvirtualisierung in Containern isoliert ausgeführt.

Buzzword-Bingo:
  • Microservices
  • DevOps
  • CI / CD (Continuous Integration / Continuous Deployment)
  • XaaS (Anything as a Service)
  • Portablität

Virtualisierung vs. Container

schema virtual maschine schema docker

Images

docker layers
  • Template für Container
  • Snapshot / Archiv
  • Readonly und versioniert
  • Ebenenprinzip (Speicherung nur Differenzen)

Container

  • Laufende Instanz eines Image
  • nur zur Laufzeit existent
  • Schreibbare Schicht wird
    oberhalb des Image bereitgestellt
schema docker

Docker-Ökosystem

Docker umfasst mehr als die Ausführungsumgebung für Container:
Compose Verwalten von Anwendungsstacks
Hub (öffentliche) Docker-Registry
Swarm / Swarm Mode Verwaltung von Container in Clustern
Cloud Hostinganbieter
Maschine Bereitstellung von Docker-Hosts
Store Bereitstellung zertifizierter Images
Kinematic Grafisches Verwaltungswerkzeug

Docker unter Linux

Start im März 2013
Alles neu - NEIN
Verwendung von erprobten Technologien des Linux-Kernel
  • LXC (BSD Jails / Solaris Zonen / OpenVZ)
  • Cgroups
    • Ressourcenlimits
    • CPU-Zeit, Speicher, IO ...
  • Namespaces
    • Simulation geschlossener Umgebungen
    • Hostnamen, Netzwerk, Prozesse ...
  • chroot (Verbindung des Mountpunkt)
Heute Bestandteil vieler Standard-Distributionen
  • Arch Linux
  • CentOS
  • Red Hat Enterprise Linux
  • openSUSE / SUSE Linux Enterprise
  • Ubuntu
  • ...


Spezielle Docker-Host Distributionen
  • Core-OS
  • Rancher-OS
  • Docker unter Windows

    • Partnerschaft zwischen Microsoft und Docker seit 2014
    • Container-Technik enthalten in
      • Windows Server 2016
      • Windows 10 Professional / Enterprise (ab Anniversary Update)
    • Unterstützung des kompletten Ökosystems (Hub / Compose / Swarm)
    • Docker-Integration Visual Studio 2017
    • Azure Container Services
    • SQL-Server als Linux-Container

    Isolation

    Windows Container vs. Hyper-V Container
    schema virtual maschine schema docker

    Basisimages

    • Bereitstellung über Dockerhub
    • microsoft/windowsservercore
      • Unterstützt Großteil der Windows Server Anwendung
      • IIS
      • SQL-Server
      • .net Framework 1.0 bis 4.7 (full)
      • 5 GB (komprimiert)
    • microsoft/nanoserver
      • Minimale Windows Version
      • IIS 10
      • .net Core
      • 333 MB (komprimiert)

    Docker - Grundlagen

    Informationen

    Docker-Host 

    docker info [OPTIONS]
    Zeigt Informationen über die Docker-Installation und
    den Host (OS / CPU / RAM ...).

    Container 

    docker ps [OPTIONS] 
    Zeigt Informationen für die Container z.B. Name, Image, Port ... an.
    -a / --all zeigt Informationen zu allen, auch inaktiven, Containern
    -l / --latest zeigt Informationen zum letzten erstellten Container

    Container-Operationen

    Erstellung 

    docker run [OPTIONS] IMAGE[:Tag] [COMMAND]
    Name --name [Name] (muss eindeutig im Host sein)
    Startverhalten -it (interaktives Terminal) /-d (Hintergrunddienst)
    Volumen-Mapping -v Quellpfad:Zielpfad
    Port-Mapping -p Container-Port:Host-Port
    Endverhalten -rm Container direkt entfernen
    Die Angabe des Containers erfolgt per Name oder Hash.

    Starten

    docker start [OPTIONS] CONTAINER
    -a / --attach Verbindung mit der Standardausgabe herstellen.
    -i / --interactive Verbindung mit der Standardeingabe herstellen.

    Stoppen

    docker stop [OPTIONS] CONTAINER
    -t / --time Zeit, in Sekunden, bis Container gekillt wird.

    Verbindung herstellen

    docker attach [OPTIONS] CONTAINER
    Stellt eine Verbindung mit der Standardausgabe des laufenden Containers her.

    Löschen

    docker rm [OPTIONS] CONTAINER
    -f / --force Bricht den noch laufenden Container ab
    -v / --volumes Löscht die mit dem Container verbundenen Volumes

    Log-Meldung anzeigen

    docker logs [OPTIONS] CONTAINER

    Image-Operationen

    Anzeige

    docker images [OPTIONS]
    -a / --all Zeigt alle, auch Zwischencontainer, an
    -f / --filter Filtert die Liste

    Herunterladen / Aktualisieren

    docker pull [OPTIONS] [Registry]IMAGENAME
    Ist keine Registry angegeben, wird der Default i.d.R. Docker-Hub verwendet. Beim Aktualisieren bleibt das vorhandene Image erhalten.
    docker pull  myregistry.local:5000/myuser/myimage

    Löschen

    docker rmi [OPTIONS] 
    -f / --force Erzwingt das Löschen

    Erstellung aus Container

    docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    -a / --author Ersteller
    -m / --message Commit message

    Übertragung zur Registry

    docker push [OPTIONS] [Registry]IMAGENAME[:TAG] 
    Vor der Übertragung in den Dockerhub ist eine Authentifizierung erforderlich.

    Docker-File

    Ist eine Auszeichnungssprache (ML) für den Aufbau eines Docker-Images.
    Die Speicherung erfolgt als Textdatei.

    FROM Basisimage[:TAG]
       Imagename ggf. mit Tag auf welchem das eigene Image basieren soll

    FROM ubuntu:16.10

    LABEL maintainer Email
       E-Mail-Adresse des Autors

    LABEL maintainer "max@mustermann.de"

       Veraltet: MAINTAINER

    MAINTAINER Max Mustermann "max@mustermann.de"

    RUN COMMAND
       Befehl zur Ausführung im Container z.B. Installieren von Software.

    RUN apt-get update

    ENV VARIABLENNAME Wert
       Definiert Variablen z.B. die Version oder das Datum der Aktualisierung, die auch innerhalb der Befehle verwendet werden können.

    ENV REFRESHED_AT 2017-01-25

    EXPOSE Portnummer
       Definiert Ports, welche durch das Image bereitgestellt werden.

    EXPOSE 8080

    VOLUME Pfad
       Definiert Volume (Verzeichnis), welche durch das Image bereitgestellt wird.

    VOLUME ["/mydata"]

    COPY Quellpfad Zielpfad
       Kopiert Ordner / Dateien in das Image

    COPY /Publish /MyApp

    ADD Quellpfad / URL Zielpfad
       Kopiert Ordner / Dateien in das Image.
       Kann auch eine URL oder eine tar-Datei sein.

    ADD /Publish /MyApp

    WORKDIR Pfad
       Definiert den Einstiegspfad für die Ausführung innerhalb des Containers.

    WORKDIR /MyApp

    ENTRYPOINT [COMMAND, ARGS]
       Definiert den Startbefehl des Images inkl. Parameter.

    ENTRYPOINT ["npm", "rum", "testapp"]

    CMD COMMAND
       Definiert den Startbefehl des Images inkl. Parameter.
       Ein Überschreiben ist möglich.

    CMD ["npm", "rum", "testapp"]

    Beispiel

    FROM fpommerening/spartakiade2017-rabbitmq:core-base
    LABEL maintainer "frank@pommerening-online.de"
    ENV REFRESHED_AT 2017-01-31
    ENV Picflow_VERSION 0.0.1
    
    COPY /app /home/
    
    RUN set -x \
    	&& p7zip -d /home/picflow-webapp.7z \
    	&& mv /picflow-webapp/ /app/ \
    	&& apt-get purge -y --auto-remove ca-certificates wget p7zip
    
    WORKDIR /app/
    EXPOSE 5000
    ENTRYPOINT ["dotnet", "WebApp.dll"]
    						

    Empfehlungen

    • Installiere nur notwendige Pakete
    • Jeder Container hat nur einen Zweck
    • Minimiere die Anzahl der Ebenen
    • Sortiere Argumente
    • Nutze .dockerignore - File
    • apt-get update / apt-get install immer in einem Befehl
    • Verwende Pipes


    Hauptziele: Übersicht erhöhen / Imagegröße reduzieren

    Build .Net Core App

    Logo .net and docker

    Build inside

    Die Anwendung wird im Container während der Imageerstellung gebaut.

    Vorteile Nachteile
    • Buildserver nicht erforderlich
    • Weniger komplex
    • Quellcode und Buildabhängigkeiten ggf. im Image enthalten
    • Basisimage größer (SDK erforderlich)
    • i.d.R. entstehen größere Images
    • Buildfehler schwerer zu debuggen

    Build outside

    Die Anwendung wird unabhängig vom Container erstellt. Die entstandenen Artefakte werden bei der Imageerstellung kopiert.

    Vorteile Nachteile
    • i.d.R. kleinere Images und Basisimages
    • Build unabhängig von der Imageestellung
    • Quellcode und Buildabhängigkeiten nicht enthalten
    • Infrastruktur für Build erforderlich
    • Trennung erzeugt Komplexität

    Containerfertige .Net (Core) App

    Logo .net and docker

    Konfiguration / Einstellungen

    • Einfache Implementierung in .NET Anwendung
    • Gute Integration in Docker-Ökosystem
    • Plattformabhängigkeit
    • Support von verschiedenen Umgebungen: Entwicklung, Test und Produktion

      • Ungeeignet Alternativen
        Registry Zentrale Service-Discovery
        Config-Dateien Environment Variables

    Logging JA


    Datei NEIN
    Console JA
    aber formatiert

    Vorteile
    • Kein Problem mit verteilte Umgebung
    • Gute Integration ins Ökosystem
    • Einfach zu implementieren

    Networking

    Legacy container links

                                
    								$ docker run -d --name mongodb mongo
    								$ docker run -d --name apache link data:mongodb webapp
                                
                            

    VERALTET
    Das Networking löst das Konzept der Links zwischen Containern ab!

    Nach der Docker-Installation stehen die folgenden Netzwerke zur Verfügung
    • none (null)
    • host (host)
    • bridge (bridge)


    Neue Container (außer Swarm / Compose) werden, soweit nicht anders definiert, dem Netzwerk bridge zugeordnet.

    Netzwerktreiber (Driver)

    • null: kein Netzwerk
    • host: nur Verbindungen zwischen Containern und dem Host.
    • bright: Container wird Teil des physischen Netzwerks des Hosts. Er kann von außen erreicht werden.
    • overlay: Hostüberspannendes Netzwerk z.B. für Swarm

    Netzwerk anzeigen

    docker network ls [OPTIONS]

    Netzwerkdetails anzeigen

    docker network inspect [OPTIONS] NETWORK

    Netzwerk erstellen

    docker network create [OPTIONS] NETWORK
    -d/--drive Netzwerktreiber (none, host, bridge ...)
    --subnet Subnetz z.B. 192.168.235.0/24
    --ip-range Definiert den zu vergebenden IP Bereich
    -o/-opt Key / Value - Eintrag für spezielle Einstellung z.B. com.docker.network.driver.mtu": "1500"
    --label Metadaten für das Netzwerk
    --ipv6 aktiviert / deaktiviert IPv6

    Docker-Compose

    Zusammenfassung mehrerer Container zu einem Anwendungsstack

    Compose-File

    Eine yaml bzw. yml - Datei, welche die Struktur und Konfiguration des Anwendungsstacks definiert. Standard: docker-compose.yml
    Versionen / Formate: Ohne Angabe im Header gilt Version 1!
    Format / Version Docker-Version Hinweise
    3.0; 3.1 1.13.0+ Empfohlene Version (Erlaubt Verknüpfung mit Docker Swarm Mode)
    2.1 1.12.0+
    2.0 1.10.0+
    1.0 1.9.1+ in zukünftiger Version deprecated / veraltet

    Service-Definition

    Jeder Container des Anwendungsstacks ist ein Service. Deren Eigenschaften wie Name, Abhängigkeiten etc. werden im Bereich services beschrieben.

    Herkunft Images
    BUILD
      Image wird erst während des Starts erstellt.

    build:
    	context: ./webapp
    	dockerfile: Dockerfile.local
    	image: webbapp:latest

    Vorhandenes Image
      gleiches Format wie beim FROM-Klausel des Dockerfile

    image: user/web:latest

    Portfreigaben
       Port-Container:Port-Host

    ports:
    	- 5000:5000

    Hostname

    hostname:Webserver1

    Abhängigkeiten
      Es werden die (Alias)name der Services verwendet.

    depends_on:
    	- dbserver

    Umgebungsvariable / Einstellungen
      Format: KEY:VALUE

    environment:
    	- setting1:value1
    	- setting2:value2

    Datenspeicher
      Datenspeicher werden zusätzlich im Bereich volumes definiert.

    volumes:
    	- data1:/app/data

    Netzwerkzuordnung
      Netzwerke werden zusätzlich im Bereich networks definiert.

    networks:
    	- frontend

    Netzwerk-Definition

    Die Definition der Netzwerke erfolgt innerhalb des Bereichs networks.

    Treiber
      z.B. bridge oder overlay

    driver: overlay

    Optionen

    driver_opts:
    - opt1: "val1"

    Datenspeicher-Definition

    Die Definition der Datenspeicher erfolgt innerhalb des Bereichs volumes. Sie orientiert sich an der Volume-Defintion .

    Treiber
      i.d.R. Local

    driver: overlay

    Optionen

    driver_opts:
    - opt1: "val1"

    Beispiel

    version: "3"
    services:
        database:
            image: mongodb:3.2
            volumes:
                - data:/var/mongo/data
            networks:
                - backend
        webapp:
            build:
                context: ./webapp
            ports: 5000:80
            environment:
                - DbConnectingString=mongodb://database
            networks:
                - backend
                - frontend
    networks:
        backend:
        frontend:
    volumes:
        data:

    Anwendungsstack-Operationen

    docker-compose [SUBCOMMAND] [OPTIONS] 

    Subbefehl Optionen Hinweise
    pull Lädt die im Anwendungsstack enthalten Images herunter
    create --no-cache [SERVICE...] Erstellt das Image bzw. den alle Images des Stack
    up -d [SERVICE]
    --build
    Erstellt / Lädt herunter / Startet einen Service inkl. Abhängigkeiten oder den gesamten Stack
    start [SERVICE] Startet einen Service
    Subbefehl Optionen Hinweise
    stop -t (timeout in s) [SERVICE] Beendet einen Service
    down --rmi / -v Stoppt und entfernt Container, Netzwerke, images und Volumes
    rm -v Entfernt, nach Bestätigung, gestoppte Container und ggf. Volumes
    exec SERVICE COMMAND Führt den übergeben Befehl im Service aus
    top [SERVICE] Zeigt die Prozesse des Service bzw. des Anwendungsstack an

    Docker Swarm / Docker Swarm Mode

    Container-Cluster über mehrere Docker-Hosts

    Docker Swarm Visualizer

    Das Tool Docker Swarm Visualizer gestattet eine Übersicht der laufenden Services und Hosts.

    Lizenz: Apache GitHub

    Verfügbare Container:

    Docker Swarm

    Cluster / Swarm initalisieren

    docker swarm init [OPTIONS] 

    Nach erfolgreicher Erstellung werden der Token und Befehl zum Hinzufügen angezeigt.

    Knoten hinzufügen

    docker swarm join [OPTIONS] HOST:PORT

    -- token Zugriffstoken

    Knoten entfernen

    docker swarm leave [OPTIONS]

    --force, -f Erzwingt das Verlassung und ignoriert Warnungen WICHTIG: die Node muss noch mein Manager abgemeldet werden!

    Zugriffstoken anzeigen

    docker swarm join-token [OPTIONS] (worker|manager)

    Cluster / Swarm aktualsieren

    docker swarm Update [OPTIONS]

    Docker Node

    Knoten anzeigen

    docker node ls [OPTIONS]

    Detailierte Informationen zu / zum Knoten anzeigen

    docker node inspect [OPTIONS] self|NODE 

    Aufgaben / Prozesse eines Knoten anzeigen

    docker node ps [OPTIONS] [NODE] 

    Knoten aus dem Cluster entfernen

    docker node rm [OPTIONS] Node

    Knoten vom Worker zum Manager heraufstufen

    docker node promote NODE

    Knoten vom Manager zum Worker herabstufen

    docker node demote NODE

    Services / Anwendung

    Anwendungen die Cluster bereitgestellt werden, werden als Services bezeichnet. Um den Service auf mehreren Nodes bereitzustellen, muss das Image in einer Registry abgelegt sein.

    Service erstellen

    docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]
    --name Name für den Service
    --network Verwendetes Netzwerk
    --publish, -p Veröffentlicht den Port
    --replicas Zahl der gleichzeitig laufenden Instanzen

    Services entfernen

    docker service rm SERVICE

    Services anzeigen

    docker service ls [OPTIONS] 

    Details zu / zum Services anzeigen

    docker service inspect [OPTIONS] SERVICE

    Services hoch/runter skalieren

    docker service scale SERVICE=ANZAHL

    Logs eines Services anzeinge

    docker service logs [OPTIONS] SERVICE

    Empfehlungen / Links

    Demoumgebung Play with Docker
    Training Beginner ... Advanced
    Docker unter Windows Docker for Windows

    Quellen:

    https://commons.wikimedia.org/wiki/File:Windows_logo_-_2012.png
    https://commons.wikimedia.org/wiki/File:Tux.svg
    https://blog.docker.com/media/Rancher-Logo-Final-1.png
    http://design.ubuntu.com/wp-content/uploads/ubuntu-logo14.png
    https://www.archlinux.org/static/logos/archlinux-logo-dark-1200dpi.b42bd35d5916.png
    http://blog.d2-si.fr/2016/06/29/start-up-docker-swarm/
    https://blogs.msdn.microsoft.com/cesardelatorre/2016/11/16/free-ebook-on-containerized-docker-application-lifecycle-with-microsoft-tools-and-platform/
    http://www.willhoeft-it.com/2016/06/03/docker-compose.html
    https://www.docker.com/sites/default/files/oyster-registry-3.png
    http://blog.terranillius.com/post/composev3_swarm/

    Offtopics

    GitHub + Docker Hub

    Die Verknüpfung von GitHub und Docker Hub gestattet eine automatische Erstellung der Container mit jeder Codeänderung. schema flow github and dockerhub Voraussetzungen:
    • Accounts bei GitHub und Docker Hub existieren
    • Quellcode inkl. Dockerfile ist in einem Repository auf GitHub vorhanden

    Verbindung GitHub und Docker Hub

    1. Login bei Docker Hub
    2. Profil -> Setting -> Linked Accounts & Services
    1. Auswahl des Zugriffs

    1. Autorisierung des Zugriffs
    2. Bestätigung mit GitHub-Kennwort

    Automatischer Build

    1. Login bei Docker Hub
    2. Create -> Create Automated Build
    3. Auswahl Herkunft Quellcode (GitHub oder Bitbucket)

    1. Auswahl des Quell-Repository
    1. Konfiguration Docker Hub-Repository
      • Namespace (Fix: Benutzer)
      • Name (Default: Name des GitHub-Repository)
      • Sichtbarkeit (Default: Öffentlich)
      • Kurzbeschreibung (Pflichtfeld)

    1. Anpassung Build-Einstellungen (Build-Settings)
      • Pfad zum Dockerfile
      • Definition Tags
      • Verwendete Git-Branches
    1. Prüfung Build (Build Details)

    Docker auf Raspberry PI 3

    Installation

    Hypriot OS

    Hypriot OS ist eine spezielle Distribution für Docker auf ARM-Geräte. Sie war bereits vor dem offiziellen Support durch Docker verfügbar.

    Raspbian Jessie Lite

    Docker unterstützt nun die ARM-Plattform offiziell. Es kann deshalb auf der Distribution Raspbian der Raspberry Foundation installiert werden.
    curl -sSL get.docker.com | sh
    sudo usermod -aG docker pi
    sudo systemctl enable docker
    sudo systemctl start docker

    Build .net App

    Die Unterstützung der ARM-Plattform für .net core ist noch in Entwicklung. Deshalb sollte man aktuell auf Mono von Xamarin / Microsoft zurückgreifen.

    Images die auf x86/x64 erstellt wurden, sind auf dem Raspberry nicht lauffähig!

    Verwendung spezieller Basisimages erforderlich
    • resin/rpi-raspbian
    • resin/raspberrypi3-debian
    • yyolk/rpi-archlinuxarm
    • ioft/armhf-ubuntu

    Microservice mit .net

    • Verwendung eines gemeinsamen Basisimage
      • Gleiche Version von .net und Abhängigkeiten für alle Serviceimages
      • Geringere Build-Zeiten
    • Infrastruktur-Container ggf. trotz Abhängigkeit noch nicht verfügbar (Reliability / Retry)
    • Build outside bevorzugen
    • Linux-Container besser auf Linux statt Windows-Host erstellen

    Image-Workflow

    Beispiel PicFlow

    .Net Client API

    Eine .NET Client API wird offiziell von Microsoft gepflegt.
    Quellcode: GitHub
    Package: Nuget
    Hinweis: Die Pakete werden nicht synchron mit den Änderungen am Quellcode veröffentlicht. Bestimmte Funktionen z.B. die Unterstützung für Swarm steht nur als Quellcode bereit.

    Verbindungsaufbau

    Für den Aufbau der Verbindung können verschiedene Protokolle z.B. Http oder Linux-Sockets verwendet. Letztes erlaubt auch die Verwendung in einem Container.

    Windows (Docker for Windows)
    var client = new DockerClientConfiguration(new Uri(http://localhost:2375)).CreateClient();

    Linux (innerhalb eines Container)
    var client = new DockerClientConfiguration(new Uri(unix://var/run/docker.sock)).CreateClient();
    Bei Start benötigt der Container zusätzliche Rechte
    docker run -d --privileged user/myimage

    Abfrage Images

    var imageParams = new ImagesListParameters{ MatchName = "ubuntu" };
    var images = await client.Images.ListImagesAsync(imageParams);


    Abfrage Container

    var listParam = new ContainersListParameters
                {
                    Filters = new Dictionary<string, IDictionary<string, bool>>
                    {
                        {"name", new Dictionary<string, bool> {{"pingtest", true}}}
                    }
                };
    var result = await client.Containers.ListContainersAsync(listParam)

    Container erstellen

    Das Ergebnis der Erstellung enthält u.a. die vergebene Container-ID.
    Wichtig: Erstellte Container sind nicht gestartet.
    var createParam = new CreateContainerParameters
                {   Image = "ubuntu:latest",
                    Cmd = new List<string> {"echo", "hallo world"},
                    Name = "halloworldtest"     };
    var result =  await client.Containers.CreateContainerAsync(createParam);

    Container starten

    await client.Containers.StartContainerAsync(containerId, null);

    Container stoppen

    await client.Containers.StopContainerAsync(containerId, 
    	new ContainerStopParameters(), CancellationToken.None);
    Beispiel: Webhook für automatische Bereitstellung

    Konfiguration des Webhook

    1. Login beim Docker Hub
    2. Auswahl des Repository
    3. Webhooks -> Create a Webhook
    4. Name und Ziel-URL festlegen
    5. Speichern