Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Docker, Ceci N'Est Pas Une Introduction (APIHour #12)

Docker, Ceci N'Est Pas Une Introduction (APIHour #12)

Docker, l'une des technologies les plus en vogue ces derniers temps, permet de créer des conteneurs logiciels. Retour sur mon utilisation pour le développement mais également pour la production, avec en ligne de mire : une architecture micro-services, quelques principes 12 Factors et un déploiement en (presque) zéro-downtime.

Sources: https://github.com/willdurand-slides/docker-clermontech

William Durand

December 15, 2014

More Decks by William Durand

Other Decks in Programming


  1. (Ceci N'Est Pas Une Introduction) William Durand ‑ December 16th,

  2. Docker In A Nutshell

  3. Containers A container is an operating‑system level virtualization method that

    provides a completely isolated environment, simulating a closed system running on a single host. chroot, OpenVZ, Jail, LXC, etc.
  4. Containers vs VMs

  5. Docker Developed by Docker.inc (formerly DotCloud) Open platform for developing,

    shipping, and running applications Use as execution driver libcontainer
  6. Docker's Architecture Host Container 1 Container 2 Container 3 Container

    ... Docker Client docker pull docker run docker ... Docker Index Docker Daemon
  7. The Plan Simple solution to deploy my application Idempotent and

    reliable process No need for rollbacks Targetting zero downtime Single host
  8. How?

  9. Methodology

  10. Twelve Factors One codebase tracked in revision control, many deploys

    Store config in the environment Keep development, staging, and production as similar as possible by The Twelve‑Factor App @aymericbrisse
  11. Infrastructure

  12. Services Reverse proxy: (+ ) Backend: + + application Sessions

    are stored into Database (at some point...) Hipache Redis Nginx HHVM memcached
  13. Overall Architecture

  14. Application's fig.yml web: build: . # No support for `env-file`

    yet... # See: https://github.com/docker/fig/pull/665 environment: - SYMFONY_ENV=dev - SYMFONY_DEBUG=1 - SYMFONY__MEMCACHED_HOST=memcached - SYMFONY__MEMCACHED_PORT=11211 - SYMFONY__SESSION_MEMCACHED_PREFIX=session - SYMFONY__SESSION_MEMCACHED_EXPIRE=604800 links: - memcached - database
  15. Application's Dockerfile FROM debian:wheezy MAINTAINER William Durand <[email protected]> ENV DEBIAN_FRONTEND

    noninteractive # Let APT know about HHVM repo... RUN apt-get update -y RUN apt-get install -y nginx hhvm supervisor # Configure Nginx, HHVM, Supervisor here... ADD . /app WORKDIR /app EXPOSE 80 CMD [ "/usr/bin/supervisord" ]
  16. DNS example.org w www.example.org Configured at the DNS level. Faster

    than making this redirection using the load balancer.
  17. SSL Hipache listens on ports 80 and 443. Patched version

    of Hipache to redirect HTTP traffic to HTTPS. Sort of SSL offloading. ® willdurand/docker‑hipache
  18. Deploy

  19. 1. Build Artifact git archive --format tar --prefix myapp/ <SHA>

    | (cd /tmp && tar xf -) Protip: use a Docker container to run build tools: cd /tmp/myapp docker run --rm -v `pwd`:/srv buildtools composer install docker run --rm -v `pwd`:/srv buildtools bundle install docker run --rm -v `pwd`:/srv buildtools bower install rm <USELESS/TEMP FILES>
  20. 2. Build Container (From Artifact) docker build -t myapp:latest .

  21. 3. Push It docker push q Or whatever that makes

    the image available on the production server.
  22. 4. Retrieve Running Containers RUNNING_CIDS=$(docker ps | grep web |

    cut -d ' ' -f 1)
  23. 5. Run The New Container fig run -d --no-deps --rm

    web † Booting the container may take a few seconds, wait.
  24. 6. Register It As Backend IP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}'

    <CID>) fig run --rm rediscli rpush frontend:www.example.com "http://$IP:80" # fig.yml rediscli: image: redis entrypoint: [ redis-cli, -h, redis ] links: - redis
  25. 7. Unregister Previous Backends For each container id CID in

    $RUNNING_CIDS, do: IP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' <CID>) fig run --rm rediscli lrem frontend:www.example.com 0 "http://$IP:80" † New backend is up and serves requests. However, previous backends may still process requests. Wait.
  26. 8. Stop Previous Containers For each container id CID in

    $RUNNING_CIDS, do: docker stop <CID>
  27. 9. Tag A Release (And Profit!)

  28. Testing

  29. Like , but better! Apache Bench ® tarekziade/boom

  30. 1. Run boom boom https://www.example.org/ -n 2000 -c 50 Server

    Software: nginx/1.2.1 Running GET https://www.example.org/ Running 2000 times per 50 workers. [================================================================>.] 99% Done -------- Results -------- Successful calls 2000 Total time 137.1827 s Average 6.7114 s Fastest 2.3701 s Slowest 9.4738 s Amplitude 7.1037 s -------- Status codes -------- Code 200 2000 times.
  31. 2. Deploy fab deploy --hide=running,stdout,stderr ---> Deploying branch "awesome-feature" --->

    Building artifact ---> Artifact id is: "build-8fe47fc" ---> Pushing artifact to the server ---> Building container ---> Finding running containers ---> Starting new container ---> Waiting while container is booting ---> Registering new backend to Hipache ---> Unregistering the previous backends from Hipache ---> Waiting before stopping the previous backends Done. q I use . Fabric
  32. 3. Monitor Elasticsearch, Logstash, Kibana + Logstash Forwarder (lumberjack) ®

    willdurand/docker‑elk ® willdurand/docker‑logstash‑forwarder
  33. None
  34. Thank You. Questions? ¾ ® ¬ williamdurand.fr github.com/willdurand twitter.com/couac

  35. Bonus

  36. Fig & Environments Keep development, staging, and production as similar

    as possible X. Dev/prod parity — 12 Factors # fig.yml.dist web: # In PRODUCTION, the line below MUST be COMMENTED: build: . # In PRODUCTION, the line below must be UNCOMMENTED: # image: myapp # ...
  37. Data Only Containers Data, logs, etc. MUST live in data

    only containers: # fig.yml redis: image: redis volumes_from: - dataredis dataredis: image: busybox volumes: - /data Wanna backup? ė docker run --rm \ --volumes-from dataredis \ -v $(pwd):/backup \ busybox \ tar cvf /backup/dataredis.tgz /data