Docker Platform 101

Build, Ship, Run

Nicolas Steinmetz / Septembre 2016

Origines

Dotscale 2013 : Vidéo - Slides

Conteneur : la solution universelle

  • Licence Apache 2
  • Mars 2013 - 0.9 / Open Source
  • Juillet 2016 - 1.12
  • Go
  • Basé sur : cgroups, namespaces, union file systems (layers), libcontainer (format)
  • Platforme : Linux 64 bits, Windows (TP), ARM (Exp)

Architecture

Mes premiers containers

# Télécharger une image
docker pull debian:jessie
# Exécuter un container et lui passer une commande :
docker run --rm docker/whalesay cowsay boo-boo
# Interagir avec un container
docker run -t -i debian /bin/bash
# Lancer un container en mode daemon
docker run -d debian /bin/sh -c "while true; do echo hello world; sleep 1; done"

Premières commandes 1/2

# Récupérer une image docker
docker pull [image]
# Créer un container à partir d'une image
docker run [image]
# Voir les logs du container :					
docker logs [container]
# Voir les container actifs :
docker ps
# Voir tous les containers (actifs ou pas) :
docker ps -a
# Voir les images de l'hôte :
docker images

Premières commandes 2/2

# Arrêter / Démarrer un container
docker stop/start [container]
# Supprimer un container / une image
docker rm [container]
docker rmi [image]
# Copier un fichier dans/depuis un container
docker cp file [container]:/path/to/file
docker cp [container]:/path/to/file file
# Inspecter un container
docker inspect [container]

Première application Web

docker run -d -p 80:5000 training/webapp python app.py

Commandes supplémentaires

# Tailer les logs
docker logs -f [container]
# Entrer dans un container
docker exec -ti [container] bash
# Exécuter une commande
docker exec -ti [container] /path/to/command args
# Avoir le top du container 
docker top [container]
# Avoir des stats CPU/RAM/... du container
docker stats [container]

Containers vs VM

Appartement vs Maison

Containers are not VMs

Layers & Image

Layers & containers

Layers mutualisés

Principes du container

  • Immuable
  • Ephémère
  • 1 container = 1 process / service

Volumes pour les données persistantes & partageable

# Crée un volume docker (! jamais purgé !)
docker run -d -P --name web -v /webapp training/webapp python app.py
# Crée un volume mappé sur un répertoire de la machine hôte
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
# Idem mais en lecture seule (secrets, certificats, conf)
docker run -d -P --name web -v /src/project/webapp:/opt/webapp:ro training/webapp python app.py
# On peut aussi monter un fichier (et pas uniquement un dossier)
docker run -d -P --name web -v /src/project/ssl/mycert.pem:/etc/ssl/mycert.pem:ro training/webapp python app.py

Réseau

# Lister les réseaux
docker network ls
# Créer un réseau
docker network create -d bridge my-bridge-network
# Démarrer un container et l'attacher à un réseau
docker run -d --network=my-bridge-network --name db training/postgres
# (Dé)connecter un container à un réseau
docker network (dis)connect [network] [container]

Composons nos premiers containers

Dockerfile

FROM nginx:stable-alpine
MAITAINER Nicolas Steinmetz 
VOLUME ["/usr/share/nginx/html"]
EXPOSE 8080
...

Dockerfile reference

FROM node:5
MAINTAINER Nicolas Steinmetz <nicolas.steinmetz@jcdecaux.com>
EXPOSE 1111
RUN groupadd -r mynodeapp &&\
    useradd -r -g mynodeapp -d /usr/src/app -M mynodeapp
RUN npm install -g bower forever
ADD app.tar.gz /usr/src/
RUN mkdir /var/log/mynodeapp && \
    chown mynodeapp:mynodeapp -R /usr/src/app /var/log/mynodeapp
USER mynodeapp
VOLUME ["/var/log/mynodeapp"]
COPY jsonenv /usr/src/app/.jsonenv
RUN chown mynodeapp:mynodeapp /usr/src/app/.jsonenv
WORKDIR /usr/src/app
RUN npm install
WORKDIR /usr/src/app/public
RUN bower install
WORKDIR	/usr/src/app
ENTRYPOINT ["forever","--fifo","app.js"]	

Docker-Compose

Composer vos applications

  • Un fichier docker-compose.yml
  • Un binaire docker-compose
  • Et voilà !

docker-compose.yml - Wordpress

version: '2'
services:
  db:
    image: mysql:5.7
    volumes:
      - "./.data/db:/var/lib/mysql"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    links:
      - db
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_PASSWORD: wordpress							
						

Commandes docker-compose

# Construire les images de container
docker-compose build
# Créer et démarrer les containers
docker-compose up
# Idem en mode daemon :
docker-compose up -d
# Tout arréter et détruire
docker-compose down
# Killer les containers
docker-compose kill
# Scaler le nombre de container
docker-compose scale [service]=XXX
# Et globalement, les mêmes commandes que docker
docker-compose ps, log, exec, stop, start, etc		
						

Avec un container à builder

Organisation projet :

.
├── build
│   ├── app.tar.gz
│   ├── Dockerfile
│   └── jsonenv
├── docker-compose.yml

Avec docker-compose.yml

mynodeapp:
    build: ./build/
    ports:
        - "1111:1111"
    volumes:
        - "/srv/app/mynodeapp/log:/var/log/mynodeapp"

Et en production ?

Systemd / docker

[Unit]
Description=ElasticSearch container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a [container]
ExecStop=/usr/bin/docker stop -t 2 [container]

[Install]
WantedBy=multi-user.target

Systemd / compose

[Unit]
Description=%p-%i

# Requirements
Requires=docker.service

# Dependency ordering
After=docker.service

[Service]
Restart=always
RestartSec=10
TimeoutStartSec=60
TimeoutStopSec=15
EnvironmentFile=-/data/domains/%i/env
WorkingDirectory=/data/domains/%i/
ExecStartPre=-/opt/bin/docker-compose rm -f
ExecStart=/bin/bash -euxc "VIRTUAL_HOST=%i /opt/bin/docker-compose up"
ExecStop=/opt/bin/docker-compose stop

[Install]
WantedBy=multi-user.target

Docker Swarm

Docker Swarm provides native clustering capabilities to turn a group of Docker engines into a single, virtual Docker Engine

Topologie (Docker v 1.12+)

Vers un vrai cluster...

Swarm

  • Manager node(s)
  • Worker node(s)
  • Services
  • Ingress

Encore plus loin dans l'orchestration

  • Rancher
  • Kubernetes (Google)
  • Openshift (Redhat)

Alternative(s)

  • Rkt (CoreOS)
  • Apache Mesos

Traefik

Le Reverse Proxy "container aware"

Bonnes pratiques

  • Sécurité
  • Gestion des logs
  • ...

Question(s) ?

Merci ! :-)