@ -0,0 +1,112 @@ |
|||||||
|
variables: |
||||||
|
GIT_SUBMODULE_STRATEGY: recursive |
||||||
|
|
||||||
|
stages: |
||||||
|
- build |
||||||
|
|
||||||
|
build-pdf-introduction-aux-conteneurs: |
||||||
|
stage: build |
||||||
|
image: |
||||||
|
name: astefanutti/decktape:2.11.0 |
||||||
|
entrypoint: [""] |
||||||
|
only: |
||||||
|
- schedules |
||||||
|
tags: |
||||||
|
- sii |
||||||
|
- france |
||||||
|
script: |
||||||
|
# |
||||||
|
# 1. We change the size with --size due to a strange rendering bug |
||||||
|
# as decribed here: https://github.com/astefanutti/decktape/issues/151 |
||||||
|
# |
||||||
|
# 2. We also specify --chrome-arg=--disable-web-security to autorize |
||||||
|
# Cross origin requests in chrome as described here: |
||||||
|
# https://github.com/astefanutti/decktape/issues/157 |
||||||
|
# |
||||||
|
- node /decktape/decktape.js --chrome-path chromium-browser --chrome-arg=--no-sandbox --chrome-arg=--disable-web-security --size='1576x1182' 1.introduction-aux-conteneurs/index.html docker.introduction-aux-conteneurs.pdf |
||||||
|
artifacts: |
||||||
|
name: introduction-aux-conteneurs |
||||||
|
expire_in: 8 days |
||||||
|
paths: |
||||||
|
- docker.introduction-aux-conteneurs.pdf |
||||||
|
|
||||||
|
|
||||||
|
build-pdf-images-de-conteneurs: |
||||||
|
stage: build |
||||||
|
image: |
||||||
|
name: astefanutti/decktape:2.11.0 |
||||||
|
entrypoint: [""] |
||||||
|
only: |
||||||
|
- schedules |
||||||
|
tags: |
||||||
|
- sii |
||||||
|
- france |
||||||
|
script: |
||||||
|
# |
||||||
|
# 1. We change the size with --size due to a strange rendering bug |
||||||
|
# as decribed here: https://github.com/astefanutti/decktape/issues/151 |
||||||
|
# |
||||||
|
# 2. We also specify --chrome-arg=--disable-web-security to autorize |
||||||
|
# Cross origin requests in chrome as described here: |
||||||
|
# https://github.com/astefanutti/decktape/issues/157 |
||||||
|
# |
||||||
|
- node /decktape/decktape.js --chrome-path chromium-browser --chrome-arg=--no-sandbox --chrome-arg=--disable-web-security --size='1576x1182' 2.images-de-conteneurs/index.html docker.images-de-conteneurs.pdf |
||||||
|
artifacts: |
||||||
|
name: images-de-conteneurs |
||||||
|
expire_in: 8 days |
||||||
|
paths: |
||||||
|
- docker.images-de-conteneurs.pdf |
||||||
|
|
||||||
|
|
||||||
|
build-pdf-conteneurs-utilisation-avancee: |
||||||
|
stage: build |
||||||
|
image: |
||||||
|
name: astefanutti/decktape:2.11.0 |
||||||
|
entrypoint: [""] |
||||||
|
only: |
||||||
|
- schedules |
||||||
|
tags: |
||||||
|
- sii |
||||||
|
- france |
||||||
|
script: |
||||||
|
# |
||||||
|
# 1. We change the size with --size due to a strange rendering bug |
||||||
|
# as decribed here: https://github.com/astefanutti/decktape/issues/151 |
||||||
|
# |
||||||
|
# 2. We also specify --chrome-arg=--disable-web-security to autorize |
||||||
|
# Cross origin requests in chrome as described here: |
||||||
|
# https://github.com/astefanutti/decktape/issues/157 |
||||||
|
# |
||||||
|
- node /decktape/decktape.js --chrome-path chromium-browser --chrome-arg=--no-sandbox --chrome-arg=--disable-web-security --size='1576x1182' 3.conteneurs-utilisation-avancee/index.html docker.conteneurs-utilisation-avancee.pdf |
||||||
|
artifacts: |
||||||
|
name: conteneurs-utilisation-avancee |
||||||
|
expire_in: 8 days |
||||||
|
paths: |
||||||
|
- docker.conteneurs-utilisation-avancee.pdf |
||||||
|
|
||||||
|
|
||||||
|
build-pdf-swarm: |
||||||
|
stage: build |
||||||
|
image: |
||||||
|
name: astefanutti/decktape:2.11.0 |
||||||
|
entrypoint: [""] |
||||||
|
only: |
||||||
|
- schedules |
||||||
|
tags: |
||||||
|
- sii |
||||||
|
- france |
||||||
|
script: |
||||||
|
# |
||||||
|
# 1. We change the size with --size due to a strange rendering bug |
||||||
|
# as decribed here: https://github.com/astefanutti/decktape/issues/151 |
||||||
|
# |
||||||
|
# 2. We also specify --chrome-arg=--disable-web-security to autorize |
||||||
|
# Cross origin requests in chrome as described here: |
||||||
|
# https://github.com/astefanutti/decktape/issues/157 |
||||||
|
# |
||||||
|
- node /decktape/decktape.js --chrome-path chromium-browser --chrome-arg=--no-sandbox --chrome-arg=--disable-web-security --size='1576x1182' 5.swarm/index.html docker.swarm.pdf |
||||||
|
artifacts: |
||||||
|
name: swarm |
||||||
|
expire_in: 8 days |
||||||
|
paths: |
||||||
|
- docker.swarm.pdf |
@ -0,0 +1,4 @@ |
|||||||
|
[submodule "revealjs"] |
||||||
|
path = revealjs |
||||||
|
url = ../../template-revealjs-sii-theme.git |
||||||
|
|
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,72 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
||||||
|
|
||||||
|
<title>SII - Introduction</title> |
||||||
|
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||||
|
<link rel="stylesheet" href="revealjs/css/custom.css"> <!-- your custom styles --> |
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code --> |
||||||
|
<link rel="stylesheet" href="revealjs/lib/css/zenburn.css"> |
||||||
|
|
||||||
|
<!-- Printing and PDF exports --> |
||||||
|
<script> |
||||||
|
var link = document.createElement( 'link' ); |
||||||
|
link.rel = 'stylesheet'; |
||||||
|
link.type = 'text/css'; |
||||||
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||||
|
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div class="reveal"> |
||||||
|
<div class="slides"> |
||||||
|
<section data-markdown="introduction-formation.md" |
||||||
|
data-separator="^\n\n\n" |
||||||
|
data-separator-vertical="^\n\n" |
||||||
|
data-separator-notes="^Note:" |
||||||
|
data-charset="UTF-8"> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="revealjs/lib/js/head.min.js"></script> |
||||||
|
<script src="revealjs/js/reveal.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
// More info https://github.com/hakimel/reveal.js#configuration |
||||||
|
Reveal.initialize({ |
||||||
|
history: true, |
||||||
|
|
||||||
|
// Transition style |
||||||
|
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// Transition style for full page slide backgrounds |
||||||
|
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#dependencies |
||||||
|
dependencies: [ |
||||||
|
{ src: 'revealjs/plugin/markdown/marked.js' }, |
||||||
|
{ src: 'revealjs/plugin/markdown/markdown.js' }, |
||||||
|
{ src: 'revealjs/plugin/notes/notes.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } } |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
// Slide number formatting can be configured using these variables: |
||||||
|
// "h.v": horizontal . vertical slide number (default) |
||||||
|
// "h/v": horizontal / vertical slide number |
||||||
|
// "c": flattened slide number |
||||||
|
// "c/t": flattened slide number / total slides |
||||||
|
Reveal.configure({ slideNumber: 'c/t' }); |
||||||
|
Reveal.configure({ transition: 'none' }); |
||||||
|
</script> |
||||||
|
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||||
|
<p class="footer">SII • www.groupe-sii.com • janvier 2021</p> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,69 @@ |
|||||||
|
# Formation Docker |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Schema Docker Swarm](images/docker-wave-whale.svg "Schema Docker Swarm") |
||||||
|
|
||||||
|
Christian Tritten |
||||||
|
<small>ctritten@sii.fr</small> |
||||||
|
|
||||||
|
|
||||||
|
## Pré-requis |
||||||
|
|
||||||
|
* Savoir utiliser les commandes de base de Linux |
||||||
|
|
||||||
|
* Savoir utiliser `vim` ou `nano` |
||||||
|
|
||||||
|
|
||||||
|
## Formation à distance |
||||||
|
|
||||||
|
* Vous pouvez intervenir quand vous voulez... |
||||||
|
mais gardez votre micro coupé le reste du temps. |
||||||
|
|
||||||
|
* Lorsque vous intervenez n'hésitez pas à allumer |
||||||
|
votre caméra afin de permettre un échange plus convivial. |
||||||
|
|
||||||
|
* Sur Teams, vous pouvez la main en cas de problème. |
||||||
|
|
||||||
|
|
||||||
|
## Horaires |
||||||
|
|
||||||
|
||| |
||||||
|
|:-|-:| |
||||||
|
|démarrage|__9h30__| |
||||||
|
|pause|__~ 11h00__| |
||||||
|
|repas|__12h30__| |
||||||
|
|reprise|__14h00__| |
||||||
|
|pause|__~ 16h00__| |
||||||
|
|fin|__17h30__| |
||||||
|
|
||||||
|
|
||||||
|
# Badge |
||||||
|
|
||||||
|
Le port du badge SII de façon visible |
||||||
|
est obligatoire dans les locaux. |
||||||
|
|
||||||
|
|
||||||
|
# Tour de table |
||||||
|
|
||||||
|
* Qui êtes-vous ? |
||||||
|
|
||||||
|
* Connaissez-vous déjà Docker ? |
||||||
|
|
||||||
|
* Qu'attendez-vous de la formation ? |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# C'est parti !!! |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Ressources internes |
||||||
|
<!-- .slide: data-state="cheat-sheet" --> |
||||||
|
|
||||||
|
1. Formation Docker SII |
||||||
|
<small>[https://gitlab.sii.fr/sii-ouest/trainings/docker](https://gitlab.sii.fr/sii-ouest/trainings/docker)</small> |
||||||
|
|
||||||
|
2. Mattermost SII ouest |
||||||
|
<small>[https://mattermost.siinergy.net/ouest/channels/docker](https://mattermost.siinergy.net/ouest/channels/docker)</small> |
||||||
|
|
||||||
|
3. Mattermost SII France |
||||||
|
<small>[https://mattermost.siinergy.net/france/channels/community-docker](https://mattermost.siinergy.net/france/channels/community-docker)</small> |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 306 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 179 KiB |
After Width: | Height: | Size: 331 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 291 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 215 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 261 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 52 KiB |
@ -0,0 +1,88 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>SII - Introduction aux conteneurs</title> |
||||||
|
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||||
|
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code --> |
||||||
|
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||||
|
|
||||||
|
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||||
|
<style> |
||||||
|
.reveal .slides { |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
||||||
|
<!-- Printing and PDF exports --> |
||||||
|
<script> |
||||||
|
var link = document.createElement( 'link' ); |
||||||
|
link.rel = 'stylesheet'; |
||||||
|
link.type = 'text/css'; |
||||||
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||||
|
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||||
|
</script> |
||||||
|
|
||||||
|
<!--[if lt IE 9]> |
||||||
|
<script src="lib/js/html5shiv.js"></script> |
||||||
|
<![endif]--> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="reveal"> |
||||||
|
<div class="slides"> |
||||||
|
<section data-markdown="introduction-aux-conteneurs.md" |
||||||
|
data-separator="^\n\n\n" |
||||||
|
data-separator-vertical="^\n\n" |
||||||
|
data-separator-notes="^Note:" |
||||||
|
data-charset="UTF-8"> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="revealjs/js/reveal.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#configuration |
||||||
|
Reveal.initialize({ |
||||||
|
controls: true, |
||||||
|
progress: true, |
||||||
|
center: true, |
||||||
|
hash: true, |
||||||
|
|
||||||
|
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#dependencies |
||||||
|
dependencies: [ |
||||||
|
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
Reveal.configure({ |
||||||
|
slideNumber: 'c/t' |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||||
|
<p class="footer">SII • www.groupe-sii.com • janvier 2022</p> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1 @@ |
|||||||
|
../revealjs |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 291 KiB |
After Width: | Height: | Size: 101 KiB |
@ -0,0 +1,88 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>SII - Images de conteneurs</title> |
||||||
|
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||||
|
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code --> |
||||||
|
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||||
|
|
||||||
|
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||||
|
<style> |
||||||
|
.reveal .slides { |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
||||||
|
<!-- Printing and PDF exports --> |
||||||
|
<script> |
||||||
|
var link = document.createElement( 'link' ); |
||||||
|
link.rel = 'stylesheet'; |
||||||
|
link.type = 'text/css'; |
||||||
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||||
|
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||||
|
</script> |
||||||
|
|
||||||
|
<!--[if lt IE 9]> |
||||||
|
<script src="lib/js/html5shiv.js"></script> |
||||||
|
<![endif]--> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="reveal"> |
||||||
|
<div class="slides"> |
||||||
|
<section data-markdown="images-de-conteneurs.md" |
||||||
|
data-separator="^\n\n\n" |
||||||
|
data-separator-vertical="^\n\n" |
||||||
|
data-separator-notes="^Note:" |
||||||
|
data-charset="UTF-8"> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="revealjs/js/reveal.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#configuration |
||||||
|
Reveal.initialize({ |
||||||
|
controls: true, |
||||||
|
progress: true, |
||||||
|
center: true, |
||||||
|
hash: true, |
||||||
|
|
||||||
|
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#dependencies |
||||||
|
dependencies: [ |
||||||
|
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
Reveal.configure({ |
||||||
|
slideNumber: 'c/t' |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||||
|
<p class="footer">SII • www.groupe-sii.com • janvier 2022</p> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,737 @@ |
|||||||
|
# Docker |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Schema Docker Swarm](images/docker-wave-whale.svg "Schema Docker Swarm") |
||||||
|
|
||||||
|
**Les conteneurs - Utilisation avancée** |
||||||
|
|
||||||
|
Maxime Poullain • Christian Tritten |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Docker run |
||||||
|
|
||||||
|
Permet d'instancier un conteneur à partir d'une image |
||||||
|
|
||||||
|
|
||||||
|
### Docker run - options |
||||||
|
<!-- .slide: data-state="medium-table" --> |
||||||
|
|
||||||
|
Option | Description |
||||||
|
- | - |
||||||
|
`--detach`, `-d` | Mode _détaché_ : lance le conteneur à l'arrière plan |
||||||
|
`--name NAME` | Donne un nom au conteneur |
||||||
|
`--interactive`, `-i` | Conserve STDIN ouvert |
||||||
|
`--tty`, `-t` | Alloue un pseudo-TTY |
||||||
|
|
||||||
|
|
||||||
|
### Docker run - restart policies |
||||||
|
|
||||||
|
On utilise l'option `--restart` avec ces paramètres : |
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-table" --> |
||||||
|
Policy | Result |
||||||
|
-------------------------|--------------------------------------- |
||||||
|
`no` | Par défaut. Ne redémarre pas |
||||||
|
`on-failure[:max-retries]` | Redémarre seulement avec un _non-zero exit status_ |
||||||
|
`always` | Redémarre tout le temps et indéfiniment. Démarre aussi en même temps que le démon Docker |
||||||
|
`unless-stopped` | Redémarre tout le temps sauf si il a été coupé |
||||||
|
|
||||||
|
|
||||||
|
### Contraintes sur les ressources |
||||||
|
|
||||||
|
* Par défaut une application conteneurisée peut consommer l'intégralité de la mémoire disponible de l'hôte. |
||||||
|
|
||||||
|
* Lorsqu'il n'y a plus de mémoire disponible, le kernel Linux : |
||||||
|
|
||||||
|
1. lance une _Out Of Memory Exception_ (OOME), |
||||||
|
|
||||||
|
2. commence à [tuer des processus](https://www.kernel.org/doc/gorman/html/understand/understand016.html) pour libérer de la mémoire. |
||||||
|
|
||||||
|
|
||||||
|
Il est possible de limiter les ressources allouées à un conteneur grâce à la technologie des _control groups_. |
||||||
|
|
||||||
|
|
||||||
|
Option | Description |
||||||
|
-------------------------|--------------------------------------- |
||||||
|
`--memory` | Limite mémoire, minimum 4M |
||||||
|
`--memory-swap` | Limite mémoire totale, (memoire + swap) |
||||||
|
`--cpu` | Limite sur l'utilisation du cpu |
||||||
|
|
||||||
|
<small>https://docs.docker.com/config/containers/resource_constraints/</small> |
||||||
|
|
||||||
|
Sur un système en production il est recommandé d'appliquer systématiquement des limitations sur l'utilisation de la mémoire. |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Docker exec |
||||||
|
|
||||||
|
Permet d'éxécuter des commandes dans le conteneur en plus du processus de base. |
||||||
|
|
||||||
|
Notamment utile pour débugger. |
||||||
|
|
||||||
|
|
||||||
|
### Docker exec - options |
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-table" --> |
||||||
|
Option | Shorthand | Default | Description |
||||||
|
----------------|-------------|---------|------------------------------ |
||||||
|
`--detach` | `-d` | False | Detached mode: run command in the background |
||||||
|
`--interactive` | `-i` | False | Keep STDIN open even if not attached |
||||||
|
`--tty` | `-t` | False | Allocate a pseudo-TTY |
||||||
|
`--user` | `-u` | False | Username or UID |
||||||
|
|
||||||
|
|
||||||
|
### Docker exec - exemple |
||||||
|
|
||||||
|
* Ouvrir une console Bash dans le conteneur : |
||||||
|
`$ docker exec -it mon_conteneur /bin/bash` |
||||||
|
|
||||||
|
* Créer un fichier à l'intérieur du conteneur : |
||||||
|
`$ docker exec mon_conteneur touch /tmp/test` |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Docker cp |
||||||
|
|
||||||
|
Permet de copier des fichiers/dossiers depuis et vers un conteneur en cours d'exécution. |
||||||
|
|
||||||
|
* Copie un fichier de l'hôte vers le conteneur : |
||||||
|
`$ docker cp fichier nom-du-conteneur:/chemin/vers/fichier` |
||||||
|
|
||||||
|
* Créer un fichier du conteneur vers l'hôte : |
||||||
|
`$ docker cp nom-du-conteneur:/chemin/vers/fichier fichier` |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Docker diff |
||||||
|
|
||||||
|
Affiche les modifications effectuées sur le système de fichiers du conteneur. |
||||||
|
|
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
``` |
||||||
|
$ docker diff mon-conteneur |
||||||
|
C /var |
||||||
|
C /var/lib |
||||||
|
C /var/lib/apt |
||||||
|
C /var/lib/apt/lists |
||||||
|
A /var/lib/apt/lists/lock |
||||||
|
A /var/lib/apt/lists/auxfiles |
||||||
|
A /var/lib/apt/lists/deb.debian.org_debian_dists_bullseye_InRelease |
||||||
|
A /var/lib/apt/lists/partial |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Monitoring simple des conteneurs |
||||||
|
|
||||||
|
|
||||||
|
### Docker Stats |
||||||
|
|
||||||
|
Docker embarque un équivalent de la commande `top` permettant d'afficher les métriques des conteneurs en cours d'exécution. |
||||||
|
|
||||||
|
`docker stats` |
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```none |
||||||
|
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS |
||||||
|
5098617c3654 0.05% 0B / 0B 0.00% 648B / 0B 0B / 0B 2 |
||||||
|
b2d0efcb5151 1.00% 0B / 0B 0.00% 648B / 0B 0B / 0B 3 |
||||||
|
cbdb1069b241 0.10% 0B / 0B 0.00% 648B / 0B 0B / 0B 5 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
### ctop |
||||||
|
|
||||||
|
Métriques des conteneurs dans une interface à la `top`. |
||||||
|
|
||||||
|
![ctop](images/ctop.gif) |
||||||
|
|
||||||
|
<small>Source : [https://ctop.sh/](https://ctop.sh/)</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration d'une application |
||||||
|
|
||||||
|
|
||||||
|
### Variables d'environnement |
||||||
|
|
||||||
|
- Il est possible d'injecter des variables d'environnement dans le conteneur au moment de sa création. |
||||||
|
|
||||||
|
- L'option `--env` permet de spécifier une variable et sa valeur. |
||||||
|
|
||||||
|
- L'option `--env-file` permet de passer un fichier de variables. |
||||||
|
|
||||||
|
- Une fois injectées dans le conteneur ces variables sont accessibles par le premier processus lancé. |
||||||
|
|
||||||
|
|
||||||
|
#### Exemple |
||||||
|
|
||||||
|
- L'image de _MariaDB_ est conçue pour être configurée à l'exécution à l'aide de variables d'environnement. |
||||||
|
|
||||||
|
- Ces variables vont permettre d'initialiser une base avec un utilisateur et mot de passe personnalisés. |
||||||
|
|
||||||
|
```none |
||||||
|
$ docker run --name mariadb \ |
||||||
|
--env MYSQL_ROOT_PASSWORD=docker \ |
||||||
|
--env MYSQL_DATABASE=docker \ |
||||||
|
--env MYSQL_USER=docker \ |
||||||
|
--env MYSQL_PASSWORD=docker \ |
||||||
|
mariadb:10.7.1 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
#### Exemple avec --env-file |
||||||
|
|
||||||
|
`mariadb-vars` |
||||||
|
```none |
||||||
|
MYSQL_ROOT_PASSWORD=docker |
||||||
|
MYSQL_DATABASE=docker |
||||||
|
MYSQL_USER=docker |
||||||
|
MYSQL_PASSWORD=docker |
||||||
|
``` |
||||||
|
|
||||||
|
```none |
||||||
|
$ docker run --name mariadb \ |
||||||
|
--env-file=mariadb-vars \ |
||||||
|
mariadb:10.7.1 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
#### Mini TP : variables d'environnement |
||||||
|
|
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
|
||||||
|
Créer un conteneur basé sur l'image `xian310/who-is-there:21` avec la configuration suivante : |
||||||
|
|
||||||
|
- Lancer le conteneur au premier plan. |
||||||
|
|
||||||
|
- Publier le port d'écoute dans le conteneur (8080) vers le port de votre choix sur l'hôte. |
||||||
|
|
||||||
|
Accéder à l'application dans le navigateur web en précisant le chemin `/env` dans l'url. |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-background="#2E2E2E" data-state="medium-code" --> |
||||||
|
Créer le conteneur : |
||||||
|
```none |
||||||
|
$ docker run --rm --publish 8080:8080 xian310/who-is-there:21 |
||||||
|
``` |
||||||
|
|
||||||
|
Accéder à l'application : |
||||||
|
```none |
||||||
|
$ firefox http://127.0.0.1:8080/env |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
- Supprimer le conteneur. |
||||||
|
|
||||||
|
- Créer un nouveau conteneur en lui passant au moins 2 variables d'environnement de votre choix. |
||||||
|
|
||||||
|
- Recharger la page web. |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-background="#2E2E2E" data-state="medium-code" --> |
||||||
|
Créer un nouveau conteneur en lui passant des variables d'environnement : |
||||||
|
```none |
||||||
|
$ docker run --rm --publish 8080:8080 \ |
||||||
|
--env MA_VARIABLE=hello --env MON_AUTRE_VARIABLE="au revoir" \ |
||||||
|
xian310/who-is-there:21 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
- On peut configurer la couleur de fond de la page `/env` en passant la variable `COLOR` au conteneur. |
||||||
|
|
||||||
|
- Pour une liste des couleur possibles : |
||||||
|
https://fr.wikipedia.org/wiki/Couleur_du_Web |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-background="#2E2E2E" data-state="medium-code" --> |
||||||
|
Changer la couleur de fond de la page `/env` : |
||||||
|
```none |
||||||
|
$ docker run --rm --publish 8080:8080 \ |
||||||
|
--env COLOR=lightblue \ |
||||||
|
xian310/who-is-there:21 |
||||||
|
``` |
||||||
|
|
||||||
|
```none |
||||||
|
$ docker run --rm --publish 8080:8080 \ |
||||||
|
--env COLOR=pink \ |
||||||
|
xian310/who-is-there:21 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Gestion des données |
||||||
|
|
||||||
|
Persistance des données avec Docker |
||||||
|
|
||||||
|
|
||||||
|
### 3 mécanismes différents |
||||||
|
|
||||||
|
Docker offre trois mécanismes permettant de monter des données de l'hôte dans un conteneur : |
||||||
|
|
||||||
|
- volumes |
||||||
|
|
||||||
|
- bind mounts |
||||||
|
|
||||||
|
- tmpfs volumes |
||||||
|
|
||||||
|
Dans le doute les _volumes_ sont presque toujours le bon choix. |
||||||
|
|
||||||
|
|
||||||
|
![Type de montage](images/types-of-mounts.png) |
||||||
|
|
||||||
|
<small>Source : documentation officielle Docker</small> |
||||||
|
|
||||||
|
Quel que soit le type de montage utilisé, les données seront présentées de la même façon au conteneur, c'est à dire sous la forme d'un dossier ou d'un fichier unique. |
||||||
|
|
||||||
|
|
||||||
|
### Volumes |
||||||
|
|
||||||
|
![Type de montage](images/types-of-mounts-volume.png) |
||||||
|
|
||||||
|
- Les _volumes_ sont stockés sur le système de fichiers de l'hôte dans le dossier |
||||||
|
`/var/lib/docker/volumes/`. |
||||||
|
|
||||||
|
|
||||||
|
- Un volume est créé et _managé_ par Docker. |
||||||
|
|
||||||
|
- Les processus autres que Docker ne devraient donc pas y modifier directement les données. |
||||||
|
|
||||||
|
|
||||||
|
- Un volume peut être monté simultanément dans plusieurs conteneurs |
||||||
|
|
||||||
|
* en lecture/écriture ou lecture seule, |
||||||
|
|
||||||
|
* très utile pour partager des données entre conteneurs. |
||||||
|
|
||||||
|
|
||||||
|
- Un volume est indépendant des conteneurs. |
||||||
|
|
||||||
|
- Le contenu persiste même si aucun conteneur n'utilise le volume. |
||||||
|
|
||||||
|
- Un volume doit être explicitement supprimé. |
||||||
|
|
||||||
|
|
||||||
|
- un volume peut être nommé ou anonyme. |
||||||
|
<small>(Un volume anonyme se voit attribuer un identifiant unique sur l'hôte)</small> |
||||||
|
|
||||||
|
- Les volumes supportent la notion de _volume drivers_. |
||||||
|
<small>(pour stocker les données sur des hôtes distant ou dans le cloud par exemple)</small> |
||||||
|
|
||||||
|
- un volume peut être sauvegardé, restoré ou migré facilement d'un hôte Docker à l'autre. |
||||||
|
<small>(Stopper les conteneurs utilisant le volume, sauvegarder le dossier `/var/lib/docker/volumes/<volume-name>/`).</small> |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="cheat-sheet" --> |
||||||
|
|
||||||
|
1. Créer un volume |
||||||
|
`$ docker volume create VOLUME` |
||||||
|
|
||||||
|
2. Lister les volumes |
||||||
|
`$ docker volume ls` |
||||||
|
|
||||||
|
3. Inspecter un volume |
||||||
|
`$ docker volume inspect VOLUME` |
||||||
|
|
||||||
|
4. Supprimer un volume |
||||||
|
`$ docker volume rm VOLUME` |
||||||
|
|
||||||
|
5. Supprimer tous les volumes non-utilisés |
||||||
|
`$ docker volume prune` |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
```none |
||||||
|
$ docker volume create mon-volume |
||||||
|
``` |
||||||
|
```none |
||||||
|
$ docker volume inspect mon-volume |
||||||
|
``` |
||||||
|
```json |
||||||
|
[ |
||||||
|
{ |
||||||
|
"CreatedAt": "2018-01-16T10:15:51+01:00", |
||||||
|
"Driver": "local", |
||||||
|
"Labels": {}, |
||||||
|
"Mountpoint": "/var/lib/docker/volumes/mon-volume/_data", |
||||||
|
"Name": "mon-volume", |
||||||
|
"Options": {}, |
||||||
|
"Scope": "local" |
||||||
|
} |
||||||
|
] |
||||||
|
``` |
||||||
|
|
||||||
|
* `docker volume inspect` permet de connaître le chemin réel du volume sur le système hôte. |
||||||
|
|
||||||
|
|
||||||
|
### Bind mounts |
||||||
|
|
||||||
|
![Type de montage](images/types-of-mounts-bind.png) |
||||||
|
|
||||||
|
- Les _bind mounts_ permettent de "monter" n'importe quel fichier ou dossier du système hôte à l'intérieur du conteneur. |
||||||
|
|
||||||
|
|
||||||
|
- Exemples d'utilisation de Bind mount : |
||||||
|
|
||||||
|
* partager des fichiers de configuration entre l'hôte et des conteneurs. |
||||||
|
|
||||||
|
* partager du code source entre l'hôte et un conteneur (sur un poste de développement). |
||||||
|
|
||||||
|
- Le fichier ou le répertoire source peut ne pas exister au préalable sur l'hôte (il sera créé le cas échéant). |
||||||
|
|
||||||
|
|
||||||
|
- __Attention !__ |
||||||
|
|
||||||
|
Si un dossier ou fichier critique pour le système hôte est monté dans le conteneur, ce dernier peut y accéder sans restriction. |
||||||
|
|
||||||
|
|
||||||
|
### tmpfs mounts |
||||||
|
|
||||||
|
![Type de montage](images/types-of-mounts-tmpfs.png) |
||||||
|
|
||||||
|
- Les _tmpfs mounts_ sont stockés directement dans la mémoire de l'hôte. |
||||||
|
|
||||||
|
|
||||||
|
- Les données sont donc volatiles et détruites en même temps que le conteneur qui les utilise (ou en cas de reboot du système). |
||||||
|
|
||||||
|
- Les _tmpfs mounts_ ne peuvent pas être partagés entre plusieurs conteneurs. |
||||||
|
|
||||||
|
|
||||||
|
### Exemples de montages |
||||||
|
|
||||||
|
<!-- .slide: data-state="cheat-sheet small-code" --> |
||||||
|
|
||||||
|
1. Monte un volume nommé |
||||||
|
```none |
||||||
|
$ docker run --detach \ |
||||||
|
--name apache \ |
||||||
|
--publish 8080:80 \ |
||||||
|
--mount source=mon-volume,target=/var/www/mon-app \ |
||||||
|
httpd:2.4 |
||||||
|
``` |
||||||
|
|
||||||
|
2. Monte un répertoire local (bind mount) |
||||||
|
```none |
||||||
|
$ docker run --detach \ |
||||||
|
--name apache \ |
||||||
|
--publish 8080:80 \ |
||||||
|
--mount type=bind,source=/home/debian/mon-app,destination=/var/www/mon-app \ |
||||||
|
httpd:2.4 |
||||||
|
``` |
||||||
|
|
||||||
|
3. Monte un répertoire local (bind mount) en read-only |
||||||
|
```none |
||||||
|
$ docker run --detach \ |
||||||
|
--name apache \ |
||||||
|
--publish 8080:80 \ |
||||||
|
--mount type=bind,source=/home/debian/mon-app,destination=/var/www/mon-app,readonly \ |
||||||
|
httpd:2.4 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
### -v ou --mount ? |
||||||
|
|
||||||
|
- A l'origine , les options `-v` et `--volume` étaient utilisées pour les conteneurs _standalone_ et l'option `--mount` pour les _services_ Swarm. |
||||||
|
|
||||||
|
- On peut utiliser les 2 syntaxes. |
||||||
|
|
||||||
|
|
||||||
|
### Volumes et droits d'accès |
||||||
|
|
||||||
|
Attention : les accès sur les fichiers |
||||||
|
restent soumis aux droits Linux. |
||||||
|
|
||||||
|
|
||||||
|
### Travaux pratiques |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
<small>[TP Docker Volumes](../travaux-pratiques/slides/docker/tp-volumes.html)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Accéder à la racine du système de fichiers du conteneur |
||||||
|
<!-- .slide: data-state="cheat-sheet medium-code" --> |
||||||
|
|
||||||
|
```none |
||||||
|
# docker inspect -f '{{.State.Pid}}' mon-conteneur |
||||||
|
11384 |
||||||
|
|
||||||
|
# cd /proc/11384/root/ |
||||||
|
total 52 |
||||||
|
drwxr-xr-x 19 root root 4096 déc. 18 17:26 ./ |
||||||
|
drwxr-xr-x 19 root root 4096 déc. 18 17:26 ../ |
||||||
|
drwxr-xr-x 2 root root 12288 mars 9 2017 bin/ |
||||||
|
drwxr-xr-x 5 root root 360 déc. 18 17:08 dev/ |
||||||
|
-rwxr-xr-x 1 root root 0 déc. 18 17:08 .dockerenv* |
||||||
|
drwxr-xr-x 2 root root 4096 déc. 18 17:08 etc/ |
||||||
|
drwxr-xr-x 2 99 99 4096 mars 9 2017 home/ |
||||||
|
dr-xr-xr-x 263 root root 0 déc. 18 17:08 proc/ |
||||||
|
drwxr-xr-x 2 root root 4096 déc. 18 17:23 root/ |
||||||
|
dr-xr-xr-x 13 root root 0 déc. 18 17:11 sys/ |
||||||
|
drwxrwxrwt 2 root root 4096 mars 9 2017 tmp/ |
||||||
|
drwxr-xr-x 3 root root 4096 mars 9 2017 usr/ |
||||||
|
drwxr-xr-x 4 root root 4096 mars 9 2017 var/ |
||||||
|
``` |
||||||
|
<small>Spécification RunC : [https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md](https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Connaître l'espace disque utilisé par Docker |
||||||
|
|
||||||
|
`docker system df` |
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
```none |
||||||
|
$ docker system df |
||||||
|
TYPE TOTAL ACTIVE SIZE RECLAIMABLE |
||||||
|
Images 23 2 3.871GB 3.794GB (98%) |
||||||
|
Containers 11 0 2.989GB 2.989GB (100%) |
||||||
|
Local Volumes 4 0 94.22MB 94.22MB (100%) |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
### Nettoyer le système |
||||||
|
|
||||||
|
`docker system prune` |
||||||
|
|
||||||
|
* Supprime les conteneurs arrêtés |
||||||
|
|
||||||
|
* Supprimes les images qui n'ont plus de tag associé |
||||||
|
|
||||||
|
* avec `-a` supprime aussi les images non utilisées |
||||||
|
|
||||||
|
* Supprime les volumes orphelins |
||||||
|
|
||||||
|
* Supprime les réseaux vides |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Travaux pratiques |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
<small>[TP application complète Web + DB](../travaux-pratiques/slides/docker/tp-web-db.html)</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Docker Compose |
||||||
|
|
||||||
|
Application multi-conteneurs |
||||||
|
|
||||||
|
|
||||||
|
- _Compose_ est un outil permettant de configurer et déployer une application composée de plusieurs conteneurs. |
||||||
|
|
||||||
|
- _Compose_ n'est pas inclus dans Docker il faut donc l'installer en plus. |
||||||
|
|
||||||
|
<small>[https://docs.docker.com/compose/](https://docs.docker.com/compose/)</small> |
||||||
|
|
||||||
|
|
||||||
|
- L'application (mono-conteneur ou multi-conteneurs) est décrite dans un fichier texte au format _yml_. |
||||||
|
|
||||||
|
- Chaque service (conteneur) possède sa propre section de configuration. |
||||||
|
|
||||||
|
- Par défaut un réseau personnalisé de type Bridge est automatiquement créé pour que l'ensemble des conteneurs de l'application : |
||||||
|
|
||||||
|
* puissent communiquer entre eux, |
||||||
|
|
||||||
|
* être isolés des autres conteneurs. |
||||||
|
|
||||||
|
|
||||||
|
### docker-compose.yml |
||||||
|
|
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```yaml |
||||||
|
version: '3' |
||||||
|
services: |
||||||
|
web: |
||||||
|
build: . # ici l'image sera construite à partir d'un Dockerfile |
||||||
|
ports: |
||||||
|
- "5000:5000" |
||||||
|
volumes: |
||||||
|
- .:/code |
||||||
|
- logvolume01:/var/log |
||||||
|
healthcheck: |
||||||
|
test: ["CMD", "curl", "-f", "http://localhost"] |
||||||
|
interval: 1m30s |
||||||
|
timeout: 10s |
||||||
|
retries: 3 |
||||||
|
redis: |
||||||
|
image: redis # ici on reprend une image déjà existante |
||||||
|
volumes: |
||||||
|
logvolume01: {} |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-table" --> |
||||||
|
Directive | Description |
||||||
|
-------------------------|--------------------------------------- |
||||||
|
`image` | Spécifie l'image Docker à utiliser |
||||||
|
`build` | Spécifie le chemin pour build l'image |
||||||
|
`ports` | Configure la publication de ports |
||||||
|
`depends_on` | Exprime la dépendance entre plusieurs services et ainsi l'ordre de lancement |
||||||
|
`restart` | Spécifie le configuration de redémarrage du conteneur |
||||||
|
`healthcheck` | Configure une vérification de la santé du service |
||||||
|
`...` | https://docs.docker.com/compose/compose-file/ |
||||||
|
|
||||||
|
|
||||||
|
Derrière un proxy : |
||||||
|
```yaml |
||||||
|
version: "3" |
||||||
|
services: |
||||||
|
my-service: |
||||||
|
build: |
||||||
|
context: my-folder/ |
||||||
|
args: |
||||||
|
- http_proxy=http:///my.proxy.url:3128 |
||||||
|
- https_proxy=https:///my.proxy.url:3128 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Pour vérifier la syntaxe du fichier docker-compose.yml : |
||||||
|
|
||||||
|
`$ docker-compose config` |
||||||
|
|
||||||
|
|
||||||
|
Pour déployer la stack applicative |
||||||
|
en une seule commande : |
||||||
|
|
||||||
|
`$ docker-compose up -d` |
||||||
|
|
||||||
|
|
||||||
|
Pour arrêter la stack sans supprimer les conteneurs : |
||||||
|
|
||||||
|
`$ docker-compose stop` |
||||||
|
|
||||||
|
|
||||||
|
Pour supprimer complètement la stack : |
||||||
|
|
||||||
|
`$ docker-compose down` |
||||||
|
|
||||||
|
Cela entraîne la suppression des conteneurs et des réseaux associés. |
||||||
|
|
||||||
|
|
||||||
|
Pour afficher les logs |
||||||
|
de tous les conteneurs de la stack : |
||||||
|
|
||||||
|
`$ docker-compose logs` |
||||||
|
|
||||||
|
|
||||||
|
### Le fichier `.env` |
||||||
|
|
||||||
|
* Permet de déclarer des variables dont la valeur sera automatiquement substituée lors du traitement du fichier _docker-compose.yml_. |
||||||
|
|
||||||
|
* Est localisé dans le même dossier que _docker-compose.yml_. |
||||||
|
|
||||||
|
* `docker-compose config` permet de visualiser le fichier final. |
||||||
|
|
||||||
|
|
||||||
|
`.env` |
||||||
|
```bash |
||||||
|
MA_VARIABLE=hello-world |
||||||
|
MON_AUTRE_VARIABLE=bonjour |
||||||
|
``` |
||||||
|
|
||||||
|
`docker-compose.yml` |
||||||
|
```yaml |
||||||
|
version: '3' |
||||||
|
|
||||||
|
services: |
||||||
|
hello: |
||||||
|
image: ${MA_VARIABLE} |
||||||
|
environment: |
||||||
|
- env_var_name=${MON_AUTRE_VARIABLE} |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
### Travaux pratiques |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
<small>[TP Docker Compose](../travaux-pratiques/slides/docker/tp-compose.html)</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Docker CMD --format |
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
Permet d'utiliser des templates Go pour personnaliser l'affichage |
||||||
|
|
||||||
|
```none |
||||||
|
$ docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" |
||||||
|
``` |
||||||
|
```none |
||||||
|
IMAGE ID REPOSITORY TAG |
||||||
|
1afc387274f5 cheatsheet latest |
||||||
|
258031686918 node 8.1.2 |
||||||
|
a2ff708b7413 debian latest |
||||||
|
00f017a8c2a6 busybox latest |
||||||
|
00f017a8c2a6 10.6.30.30:5000/mpoullain/busybox latest |
||||||
|
``` |
||||||
|
|
||||||
|
<small>[https://docs.docker.com/engine/admin/formatting/](https://docs.docker.com/engine/admin/formatting/)</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## API du démon Docker |
||||||
|
|
||||||
|
* Le démon Docker fourni une API qui permet de : |
||||||
|
|
||||||
|
- récupérer des informations sur le démon et les objets Docker |
||||||
|
|
||||||
|
- lancer des commandes |
||||||
|
|
||||||
|
* Documentation : [https://docs.docker.com/develop/sdk/](https://docs.docker.com/develop/sdk/) |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
Lister les conteneurs : |
||||||
|
```none |
||||||
|
$ curl --unix-socket /var/run/docker.sock http://1.24/containers/json | jq . |
||||||
|
``` |
||||||
|
```json |
||||||
|
[ |
||||||
|
{ |
||||||
|
"Id": "4ab7c5898ac9a594b42406c0afc2250b1b7da36e8966348c09e32fde84515608", |
||||||
|
"Names": [ |
||||||
|
"/determined_bohr" |
||||||
|
], |
||||||
|
"Image": "debian:stretch", |
||||||
|
"ImageID": "sha256:8626492fecd368469e92258dfcafe055f636c21a5865a98a0a6...", |
||||||
|
"Command": "bash" |
||||||
|
} |
||||||
|
... |
||||||
|
] |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
Démarrer un conteneur : |
||||||
|
```none |
||||||
|
$ curl --unix-socket /var/run/docker.sock -X POST \ |
||||||
|
http://1.24/containers/4ab7c5898ac9/start |
||||||
|
``` |
||||||
|
|
||||||
|
Afficher les logs d'un conteneur : |
||||||
|
```none |
||||||
|
$ curl --unix-socket /var/run/docker.sock \ |
||||||
|
http://1.24/containers/4ab7c5898ac9/logs?stdout=1 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
## Mode debug |
||||||
|
|
||||||
|
Il est possible d'activer le mode debug |
||||||
|
du démon Docker : |
||||||
|
|
||||||
|
```none |
||||||
|
root@node1: # sudo cat /etc/docker/daemon.json |
||||||
|
{"debug":true} |
||||||
|
``` |
||||||
|
|
||||||
|
```none |
||||||
|
root@node1: # systemctl reload docker |
||||||
|
``` |
||||||
|
|
||||||
|
```none |
||||||
|
root@node1: # tail -f /var/log/syslog |
||||||
|
c'est beaucoup plus verbeux !! |
||||||
|
``` |
After Width: | Height: | Size: 676 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,88 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>SII - Conteneurs : utilisation avancée</title> |
||||||
|
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||||
|
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code --> |
||||||
|
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||||
|
|
||||||
|
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||||
|
<style> |
||||||
|
.reveal .slides { |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
||||||
|
<!-- Printing and PDF exports --> |
||||||
|
<script> |
||||||
|
var link = document.createElement( 'link' ); |
||||||
|
link.rel = 'stylesheet'; |
||||||
|
link.type = 'text/css'; |
||||||
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||||
|
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||||
|
</script> |
||||||
|
|
||||||
|
<!--[if lt IE 9]> |
||||||
|
<script src="lib/js/html5shiv.js"></script> |
||||||
|
<![endif]--> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="reveal"> |
||||||
|
<div class="slides"> |
||||||
|
<section data-markdown="conteneurs-utilisation-avancee.md" |
||||||
|
data-separator="^\n\n\n" |
||||||
|
data-separator-vertical="^\n\n" |
||||||
|
data-separator-notes="^Note:" |
||||||
|
data-charset="UTF-8"> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="revealjs/js/reveal.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#configuration |
||||||
|
Reveal.initialize({ |
||||||
|
controls: true, |
||||||
|
progress: true, |
||||||
|
center: true, |
||||||
|
hash: true, |
||||||
|
|
||||||
|
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#dependencies |
||||||
|
dependencies: [ |
||||||
|
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
Reveal.configure({ |
||||||
|
slideNumber: 'c/t' |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||||
|
<p class="footer">SII • www.groupe-sii.com • janvier 2022</p> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1 @@ |
|||||||
|
../revealjs |
@ -0,0 +1,366 @@ |
|||||||
|
# Docker |
||||||
|
|
||||||
|
![Schema Docker Swarm](images/docker-wave-whale.svg "Schema Docker Swarm") |
||||||
|
|
||||||
|
__Les hôtes Docker__ |
||||||
|
|
||||||
|
Maxime Poullain • Christian Tritten |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Où déployer ses conteneurs ? |
||||||
|
|
||||||
|
|
||||||
|
* Bare-metal |
||||||
|
|
||||||
|
|
||||||
|
* IaaS - cloud public |
||||||
|
|
||||||
|
* Amazon Web Services (AWS) |
||||||
|
|
||||||
|
* Google Cloud Engine (GCE) |
||||||
|
|
||||||
|
* Microsoft Azure |
||||||
|
|
||||||
|
* ... |
||||||
|
|
||||||
|
|
||||||
|
* IaaS - cloud privé |
||||||
|
|
||||||
|
* OpenStack |
||||||
|
|
||||||
|
|
||||||
|
* CaaS |
||||||
|
|
||||||
|
* Google Kubernetes Engine |
||||||
|
|
||||||
|
* Amazon Elastic Container Service for Kubernetes |
||||||
|
|
||||||
|
* ... |
||||||
|
|
||||||
|
|
||||||
|
## Offres CaaS |
||||||
|
|
||||||
|
|
||||||
|
### Google Kubernetes Engine |
||||||
|
|
||||||
|
* Google gère l'infrastructure multi-masters de kubernetes. |
||||||
|
|
||||||
|
* Kubernetes Engine est certifié conforme Kubernetes : compatibilité complète avec l'écosystème Kubernetes. |
||||||
|
|
||||||
|
* Monitoring complet du cluster. |
||||||
|
|
||||||
|
* Les applications Kubernetes standard sont entièrement compatibles et peuvent facilement être migrées vers Google Kubernetes Engine. |
||||||
|
|
||||||
|
* C'est l'offre la plus complète du marché. |
||||||
|
|
||||||
|
* [https://cloud.google.com/kubernetes-engine/](https://cloud.google.com/kubernetes-engine/) |
||||||
|
|
||||||
|
|
||||||
|
### Amazon Elastic Container Service for Kubernetes |
||||||
|
|
||||||
|
* Amazon gère l'infrastructure multi-masters de Kubernetes. |
||||||
|
|
||||||
|
* Amazon EKS est certifié conforme Kubernetes : compatibilité complète avec l'écosystème Kubernetes. |
||||||
|
|
||||||
|
* Les applications Kubernetes standard sont entièrement compatibles et peuvent facilement être migrées vers Amazon EKS. |
||||||
|
|
||||||
|
* [https://aws.amazon.com/fr/eks/](https://aws.amazon.com/fr/eks/) |
||||||
|
|
||||||
|
|
||||||
|
## Distributions classiques |
||||||
|
|
||||||
|
Toutes les grandes distributions incluent désormais Docker dans leurs dépôts de paquets : |
||||||
|
|
||||||
|
* Debian |
||||||
|
|
||||||
|
* Ubuntu |
||||||
|
|
||||||
|
* RedHat |
||||||
|
|
||||||
|
* CentOS |
||||||
|
|
||||||
|
|
||||||
|
Toutefois les versions de Docker proposées dans ces dépôts peuvent dater. |
||||||
|
|
||||||
|
Pour pallier cela Docker Inc. maintient ses propres dépôts avec les versions à jour de ses produits : |
||||||
|
|
||||||
|
* http://apt.dockerproject.org |
||||||
|
|
||||||
|
* http://yum.dockerproject.org |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Systèmes d'exploitation spécialisés |
||||||
|
|
||||||
|
* Systèmes légers, conçus et optimisés pour les conteneurs |
||||||
|
|
||||||
|
* Peuvent intégrer nativement des fonctionnalités avancées |
||||||
|
|
||||||
|
* Peuvent présenter une sécurité accrue |
||||||
|
|
||||||
|
|
||||||
|
### RedHat Atomic |
||||||
|
|
||||||
|
![Logo Atomic](images/logo-atomic.png) |
||||||
|
|
||||||
|
* Développé par RedHat |
||||||
|
* Système Linux léger et immutable (read only OS) |
||||||
|
* Basé sur systemd |
||||||
|
* Intègre une IHM dédiée : Cockpit |
||||||
|
* Orchestration possible via Kubernetes |
||||||
|
|
||||||
|
|
||||||
|
### CoreOS |
||||||
|
|
||||||
|
![Logo CoreOS](images/logo-coreos.jpg) |
||||||
|
|
||||||
|
* Basé sur systemd, etcd, rkt, fleet, flannel |
||||||
|
* Peut faire tourner des conteneurs rkt et docker |
||||||
|
* Fleet est un système d'init distribué basé sur systemd qui permet l'orchestration de conteneurs sur plusieurs hôtes. |
||||||
|
* Intégration facile avec Kubernetes |
||||||
|
* Production ready |
||||||
|
|
||||||
|
|
||||||
|
### RancherOS |
||||||
|
|
||||||
|
![Logo Rancher](images/logo-rancher.jpg) |
||||||
|
|
||||||
|
* Système Linux minimaliste (20Mb) basé sur Docker |
||||||
|
* Docker tourne directement au dessus du kernel, avec le PID 1 (en remplacement de... sysVinit / systemd) |
||||||
|
* Tous les services habituels du "user-space" sont fournis sous forme de conteneurs Docker |
||||||
|
* Les conteneurs applicatifs utilisent un daemon Docker séparé |
||||||
|
|
||||||
|
|
||||||
|
#### Architecture de RancherOS |
||||||
|
|
||||||
|
![Architecture RancherOS](images/rancheros-architecture.png) |
||||||
|
|
||||||
|
|
||||||
|
### VMware Photon OS |
||||||
|
|
||||||
|
![Logo Photon](images/logo-photon.jpg) |
||||||
|
|
||||||
|
* Développé par VMware en opensource |
||||||
|
* Système Linux léger optimisé pour les plateformes VMware |
||||||
|
* Intégration avec vSphere et vCloud Air |
||||||
|
* Supporte les conteneurs Docker et rkt |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Comment Déployer ? |
||||||
|
|
||||||
|
- À la main ;-) |
||||||
|
|
||||||
|
- Infrastructure as code |
||||||
|
* Ansible |
||||||
|
* Heat |
||||||
|
* Terraform |
||||||
|
* ... |
||||||
|
|
||||||
|
|
||||||
|
### Infrastructure as Code |
||||||
|
|
||||||
|
L'infrastructure cible est décrite dans des fichiers de configuration à l'aide d'une syntaxe spécifique. |
||||||
|
|
||||||
|
Il devient possible gérer et versionner les modifications apportées à l'infrastructure. |
||||||
|
|
||||||
|
Reconstruire, modifier partiellement ou dupliquer une infrastructure s'en trouve d'autant simplifié. |
||||||
|
|
||||||
|
|
||||||
|
#### Exemple de workflow de déploiement |
||||||
|
|
||||||
|
- Authentification auprès du fournisseur |
||||||
|
- Allocation des ressources stockage et d'adressage IP |
||||||
|
- Création du réseau |
||||||
|
- Déploiement des VMs |
||||||
|
- Configuration OS |
||||||
|
- Installation et configuration du démon Docker (et/ou Swarm) |
||||||
|
|
||||||
|
|
||||||
|
#### Ansible |
||||||
|
|
||||||
|
![Ansible](images/logo-ansible.png) |
||||||
|
|
||||||
|
_Ansible_ est un outil de gestion de configuration très populaire. |
||||||
|
|
||||||
|
Sa force réside dans un écosystème riche de centaines de modules permettant de gérer à peu près tous les aspects d'une infrastructure ou d'un système. |
||||||
|
|
||||||
|
|
||||||
|
A l'origine conçu comme outil de gestion de configuration pour les systèmes Linux, il peut désormais s'interfacer avec les cloud les plus populaires : |
||||||
|
* AWS, |
||||||
|
* GCP, |
||||||
|
* Azure, |
||||||
|
* OpenStack, |
||||||
|
* VMware, |
||||||
|
* et bien d'autres ... |
||||||
|
|
||||||
|
|
||||||
|
Par exemple les modules Ansible pour OpenStack offrent les fonctionnalités suivantes : |
||||||
|
|
||||||
|
* Keystone: users, groups, roles, projects |
||||||
|
* Nova: servers, keypairs, security-groups, flavors |
||||||
|
* Neutron: ports, network, subnets, routers, floating IPs |
||||||
|
* Ironic: nodes, introspection |
||||||
|
* Swift Objects |
||||||
|
* Cinder volumes |
||||||
|
* Glance images |
||||||
|
|
||||||
|
|
||||||
|
Il offre également une gestion partielle de Docker via des modules dédiés : |
||||||
|
|
||||||
|
* docker (D) - manage docker containers |
||||||
|
* docker_container - manage docker containers |
||||||
|
* docker_image - Manage docker images. |
||||||
|
* docker_image_facts - Inspect docker images |
||||||
|
* docker_login - Log into a Docker registry. |
||||||
|
* docker_network - Manage Docker networks |
||||||
|
* docker_service - Manage docker services and containers. |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
``` |
||||||
|
--- |
||||||
|
# Ansible and OpenStack automation |
||||||
|
- name: VM deployment |
||||||
|
hosts: docker-cluster |
||||||
|
tasks: |
||||||
|
... |
||||||
|
- name: Create the network |
||||||
|
os_network: |
||||||
|
state: present |
||||||
|
name: testnet |
||||||
|
external: False |
||||||
|
shared: False |
||||||
|
register: testnet_network |
||||||
|
|
||||||
|
- name: Create the test subnet |
||||||
|
os_subnet: |
||||||
|
state: present |
||||||
|
network_name: "{{ testnet_network.id }}" |
||||||
|
name: testnet_sub |
||||||
|
ip_version: 4 |
||||||
|
cidr: 192.168.0.0/24 |
||||||
|
gateway_ip: 192.168.0.1 |
||||||
|
enable_dhcp: yes |
||||||
|
dns_nameservers: |
||||||
|
- 8.8.8.8 |
||||||
|
register: testnet_sub |
||||||
|
|
||||||
|
- name: Create server instance |
||||||
|
os_server: |
||||||
|
state: present |
||||||
|
name: testServer |
||||||
|
image: debian |
||||||
|
flavor: m1.small |
||||||
|
security_groups: secgr |
||||||
|
key_name: ansible_key |
||||||
|
nics: |
||||||
|
- net-id: "{{ testnet_network.id }}" |
||||||
|
register: testServer |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
#### Heat |
||||||
|
|
||||||
|
![Terraform](images/logo-heat.jpg) |
||||||
|
|
||||||
|
_Heat_ est un outil d'orchestration spécifiquement conçu pour gérer des déploiements dans un environnement OpenStack. |
||||||
|
|
||||||
|
Il permet le déploiement de l’infrastructure initiale puis de son évolution à l'aide de fichiers "Templates" qui décrivent les ressources à produire. |
||||||
|
|
||||||
|
|
||||||
|
##### Exemple de template Heat |
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
``` |
||||||
|
description: Deploys a Docker Swarm |
||||||
|
parameters: |
||||||
|
... |
||||||
|
docker_node: |
||||||
|
type: OS::Nova::Server |
||||||
|
properties: |
||||||
|
name: {get_param: hostname} |
||||||
|
image: { get_param: instance_image } |
||||||
|
flavor: { get_param: instance_flavor } |
||||||
|
key_name: { get_param: ssh_key } |
||||||
|
networks: |
||||||
|
- port: { get_resource: docker_node_port } |
||||||
|
user_data_format: RAW |
||||||
|
user_data: | |
||||||
|
#!/bin/bash |
||||||
|
apt-get update |
||||||
|
apt-get -y upgrade |
||||||
|
wget -q https://test.docker.com/ -O /root/install_docker.sh |
||||||
|
chmod 755 /root/install_docker.sh |
||||||
|
/bin/bash /root/install_docker.sh |
||||||
|
docker swarm join 10.0.2.21:2377 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
#### Terraform |
||||||
|
|
||||||
|
![Terraform](images/logo-terraform.jpg) |
||||||
|
|
||||||
|
_Terraform_ est un outil pour construire, modifier, versionner une infrastructure de manière sécurisé et efficiente. |
||||||
|
|
||||||
|
|
||||||
|
Il gère les fournisseurs les plus populaires : |
||||||
|
* IaaS (AWS, GCP, Microsoft Azure, OpenStack, ...) |
||||||
|
* PaaS (Heroku, ...) |
||||||
|
* SaaS services (Terraform Enterprise, DNSimple, CloudFlare, ...) |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
`variables.tf` |
||||||
|
``` |
||||||
|
variable "network" { |
||||||
|
type = "string" |
||||||
|
default = "training-docker" |
||||||
|
} |
||||||
|
|
||||||
|
variable "nodes" { |
||||||
|
default = 3 |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
`formation.tf` |
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
``` |
||||||
|
resource "openstack_compute_instance_v2" "formation" { |
||||||
|
|
||||||
|
name = "training-${count.index + 1}" |
||||||
|
count = "${var.nodes}" |
||||||
|
flavor_name = "m1.tiny" |
||||||
|
key_pair = "training-keypair" |
||||||
|
region = "RegionOne" |
||||||
|
block_device { |
||||||
|
uuid = "724d7bd0-2ea3-4e39-b3d8-dd394ea933f1" |
||||||
|
source_type = "image" |
||||||
|
volume_size = 8 |
||||||
|
boot_index = 0 |
||||||
|
destination_type = "volume" |
||||||
|
delete_on_termination = true |
||||||
|
} |
||||||
|
|
||||||
|
network { |
||||||
|
name = "${var.network}" |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
`formation.tf (suite)` |
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
``` |
||||||
|
provisioner "remote-exec" { |
||||||
|
inline = [ |
||||||
|
"sudo apt update -y", |
||||||
|
"sudo apt upgrade -y", |
||||||
|
"sudo apt install -y curl", |
||||||
|
"sudo curl -fsSL https://get.docker.com/ | sh", |
||||||
|
] |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
``` |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 207 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 101 KiB |
@ -0,0 +1,72 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
||||||
|
|
||||||
|
<title>SII - Hôtes Docker</title> |
||||||
|
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||||
|
<link rel="stylesheet" href="revealjs/css/custom.css"> <!-- your custom styles --> |
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code --> |
||||||
|
<link rel="stylesheet" href="revealjs/lib/css/zenburn.css"> |
||||||
|
|
||||||
|
<!-- Printing and PDF exports --> |
||||||
|
<script> |
||||||
|
var link = document.createElement( 'link' ); |
||||||
|
link.rel = 'stylesheet'; |
||||||
|
link.type = 'text/css'; |
||||||
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||||
|
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div class="reveal"> |
||||||
|
<div class="slides"> |
||||||
|
<section data-markdown="hotes-docker.md" |
||||||
|
data-separator="^\n\n\n" |
||||||
|
data-separator-vertical="^\n\n" |
||||||
|
data-separator-notes="^Note:" |
||||||
|
data-charset="UTF-8"> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="revealjs/lib/js/head.min.js"></script> |
||||||
|
<script src="revealjs/js/reveal.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
// More info https://github.com/hakimel/reveal.js#configuration |
||||||
|
Reveal.initialize({ |
||||||
|
history: true, |
||||||
|
|
||||||
|
// Transition style |
||||||
|
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// Transition style for full page slide backgrounds |
||||||
|
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#dependencies |
||||||
|
dependencies: [ |
||||||
|
{ src: 'revealjs/plugin/markdown/marked.js' }, |
||||||
|
{ src: 'revealjs/plugin/markdown/markdown.js' }, |
||||||
|
{ src: 'revealjs/plugin/notes/notes.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } } |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
// Slide number formatting can be configured using these variables: |
||||||
|
// "h.v": horizontal . vertical slide number (default) |
||||||
|
// "h/v": horizontal / vertical slide number |
||||||
|
// "c": flattened slide number |
||||||
|
// "c/t": flattened slide number / total slides |
||||||
|
Reveal.configure({ slideNumber: 'c/t' }); |
||||||
|
Reveal.configure({ transition: 'none' }); |
||||||
|
</script> |
||||||
|
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||||
|
<p class="footer">SII • www.groupe-sii.com • septembre 2018</p> |
||||||
|
</body> |
||||||
|
</html> |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 354 KiB |
@ -0,0 +1,88 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>SII - Docker Swarm</title> |
||||||
|
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||||
|
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||||
|
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code --> |
||||||
|
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||||
|
|
||||||
|
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||||
|
<style> |
||||||
|
.reveal .slides { |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
||||||
|
<!-- Printing and PDF exports --> |
||||||
|
<script> |
||||||
|
var link = document.createElement( 'link' ); |
||||||
|
link.rel = 'stylesheet'; |
||||||
|
link.type = 'text/css'; |
||||||
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||||
|
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||||
|
</script> |
||||||
|
|
||||||
|
<!--[if lt IE 9]> |
||||||
|
<script src="lib/js/html5shiv.js"></script> |
||||||
|
<![endif]--> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="reveal"> |
||||||
|
<div class="slides"> |
||||||
|
<section data-markdown="swarm.md" |
||||||
|
data-separator="^\n\n\n" |
||||||
|
data-separator-vertical="^\n\n" |
||||||
|
data-separator-notes="^Note:" |
||||||
|
data-charset="UTF-8"> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="revealjs/js/reveal.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#configuration |
||||||
|
Reveal.initialize({ |
||||||
|
controls: true, |
||||||
|
progress: true, |
||||||
|
center: true, |
||||||
|
hash: true, |
||||||
|
|
||||||
|
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||||
|
|
||||||
|
// More info https://github.com/hakimel/reveal.js#dependencies |
||||||
|
dependencies: [ |
||||||
|
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||||
|
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||||
|
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
Reveal.configure({ |
||||||
|
slideNumber: 'c/t' |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||||
|
<p class="footer">SII • www.groupe-sii.com • janvier 2022</p> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,750 @@ |
|||||||
|
# Docker |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Schema Docker Swarm](images/docker-wave-whale.svg "Schema Docker Swarm") |
||||||
|
|
||||||
|
**Swarm** |
||||||
|
|
||||||
|
Maxime Poullain • Christian Tritten |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-background="images/container-mess.jpg" data-state="nologo-slide" --> |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-background="images/container-mess.jpg" data-state="nologo-slide" style="text-align: center" --> |
||||||
|
Le passage à l'échelle d'une infrastructure Docker |
||||||
|
nécessite des outils adaptés.<!-- .element: style="color:white; background-color: black" --> |
||||||
|
|
||||||
|
|
||||||
|
## Orchestrateur de conteneurs |
||||||
|
|
||||||
|
Un orchestrateur de conteneurs permet |
||||||
|
de construire (facilement) un système distribué. |
||||||
|
|
||||||
|
|
||||||
|
### Fonctionnalités d'un orchestrateur (1/2) |
||||||
|
|
||||||
|
- Gestion d'un ensemble de machines (cluster) |
||||||
|
<small>Extension horizontale de la capacité du système par l'ajout de nouvelles machines</small> |
||||||
|
|
||||||
|
- Gestion des déploiements de conteneurs (scheduler) |
||||||
|
<small>Selon des critères : label, affinité, charge, ...</small> |
||||||
|
|
||||||
|
- Gestion de la résilience |
||||||
|
<small>Via des tests de santé périodique sur les conteneurs et les hôtes</small> |
||||||
|
|
||||||
|
|
||||||
|
### Fonctionnalités d'un orchestrateur (2/2) |
||||||
|
|
||||||
|
- Gestion d'un réseau distribué |
||||||
|
<small>Qui s'étend sur l'ensemble des machines du cluster</small> |
||||||
|
|
||||||
|
- Gestion de la haute disponibilité des applications |
||||||
|
<small>En créant plusieurs instances d'une même application sur des hôtes différents</small> |
||||||
|
|
||||||
|
- Gestion de la découverte de services |
||||||
|
<small>Pour détecter automatiquement les nouvelles instances d'une application</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Principe d'un orchestrateur |
||||||
|
|
||||||
|
![Schema de principe](images/orchestration-principle.jpg) |
||||||
|
|
||||||
|
|
||||||
|
### Les principaux orchestrateurs |
||||||
|
|
||||||
|
- Swarm (Docker) |
||||||
|
|
||||||
|
- Kubernetes (Google) |
||||||
|
|
||||||
|
- OpenShift (RedHat) |
||||||
|
|
||||||
|
- Mesos/Marathon (Apache) |
||||||
|
|
||||||
|
- Nomad (HashiCorp) |
||||||
|
|
||||||
|
- Rancher |
||||||
|
|
||||||
|
- ... |
||||||
|
|
||||||
|
|
||||||
|
## Docker Swarm |
||||||
|
![Logo Docker Swarm](images/swarm.png) <!-- .element: width="200px" --> |
||||||
|
- Orchestrateur maison de Docker Inc. |
||||||
|
- Très bien intégré dans Docker (rien à installer) |
||||||
|
- Facile à prendre en main |
||||||
|
- Solution idéale pour les petits environnements |
||||||
|
|
||||||
|
|
||||||
|
## Swarm - Fonctionnalités |
||||||
|
|
||||||
|
|
||||||
|
- Gestion du cluster |
||||||
|
|
||||||
|
- Ajout/retrait de machines |
||||||
|
|
||||||
|
- Maintient opérationnel de l'état du cluster |
||||||
|
|
||||||
|
- Chiffrement des transactions entre les noeuds (control plane) |
||||||
|
|
||||||
|
- Orchestration des déploiements |
||||||
|
|
||||||
|
- Placement des conteneurs |
||||||
|
|
||||||
|
- Stratégies / Filtres |
||||||
|
|
||||||
|
|
||||||
|
- Gestion d'applications multi-conteneurs (Stack) |
||||||
|
|
||||||
|
- Réseau distribué (Overlay) |
||||||
|
|
||||||
|
- Mise à l'échelle |
||||||
|
|
||||||
|
- Équilibrage de charge |
||||||
|
|
||||||
|
- Gestion de la résilience |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Concepts |
||||||
|
|
||||||
|
La terminologie Swarm |
||||||
|
|
||||||
|
* node |
||||||
|
|
||||||
|
* task |
||||||
|
|
||||||
|
* service |
||||||
|
|
||||||
|
* stack |
||||||
|
|
||||||
|
* network |
||||||
|
|
||||||
|
* secret / config |
||||||
|
|
||||||
|
|
||||||
|
### Node |
||||||
|
|
||||||
|
* Un noeud (_node_) est une instance de Docker Engine intégrée dans le cluster Docker Swarm. |
||||||
|
|
||||||
|
* On peut joindre autant de noeuds que nécessaire au cluster. |
||||||
|
|
||||||
|
* On peut également retirer des noeuds si besoin. |
||||||
|
|
||||||
|
|
||||||
|
Deux types de noeuds : |
||||||
|
|
||||||
|
* __Manager__ |
||||||
|
- Maintient l'état du cluster |
||||||
|
- Orchestre les tâches (_tasks_) sur les noeuds actifs |
||||||
|
|
||||||
|
* __Worker__ |
||||||
|
- Reçoit les tâches (_tasks_) envoyées par les noeuds manager |
||||||
|
- Exécute les tâches localement |
||||||
|
|
||||||
|
|
||||||
|
* Par défaut les noeuds de type _manager_ sont aussi des _worker_. |
||||||
|
|
||||||
|
* Il est possible de configurer un noeud manager pour qu'il fasse seulement office de manager (`drain`). |
||||||
|
|
||||||
|
* Un noeud peut changer de rôle au cours de son existence en passant de worker à manager ou inversement (`promote/demote`). |
||||||
|
|
||||||
|
|
||||||
|
![Schema Docker Swarm](images/swarm2.png) <!-- .element: width="800px" --> |
||||||
|
|
||||||
|
|
||||||
|
Un noeud _Manager_ peut être dans l'un des états suivants : |
||||||
|
|
||||||
|
* _Leader_ : noeud manager primaire du système, il prend les décisions d'orchestration au sein du cluster. |
||||||
|
|
||||||
|
* _Reachable_ : noeud pouvant devenir leader en cas de défaillance de l'actuel noeud leader. |
||||||
|
|
||||||
|
* _Unavailable_ : noeud non joignable d'un point de vue réseau. |
||||||
|
|
||||||
|
|
||||||
|
* Afin d'augmenter la résilience du cluster, il est recommandé d'opter pour un nombre impair de noeuds de type _manager_ : |
||||||
|
|
||||||
|
* Avec _3_ noeuds managers, le système peut survivre à une perte maximum d'_1 manager_. |
||||||
|
|
||||||
|
* Avec _5_ noeuds managers, le système peut survivre à une perte maximum de _2 managers_. |
||||||
|
|
||||||
|
* L'augmentation du nombre de noeuds manager ne procure pas de meilleures performances au système global. |
||||||
|
|
||||||
|
|
||||||
|
Managers | Majorité Quorum | Tolérence de perte |
||||||
|
:-------:|:---------------:|:-----------------: |
||||||
|
1 | 1 | 0 |
||||||
|
2 | 2 | 0 |
||||||
|
3 | 2 | 1 |
||||||
|
4 | 3 | 1 |
||||||
|
5 | 3 | 2 |
||||||
|
6 | 4 | 2 |
||||||
|
7 | 4 | 3 |
||||||
|
8 | 5 | 3 |
||||||
|
9 | 5 | 4 |
||||||
|
|
||||||
|
|
||||||
|
Niveaux de disponibilité d'un noeud : |
||||||
|
|
||||||
|
- Active |
||||||
|
|
||||||
|
- Pause |
||||||
|
|
||||||
|
- Drain |
||||||
|
|
||||||
|
|
||||||
|
Niveau _Active_ : |
||||||
|
|
||||||
|
* Le noeud peut recevoir de nouvelles tâches de la part de l'orchestrateur. |
||||||
|
|
||||||
|
* C'est le niveau de fonctionnement normal. |
||||||
|
|
||||||
|
|
||||||
|
Niveau _Pause_ : |
||||||
|
|
||||||
|
* Le noeud ne peut plus recevoir de nouvelles tâches de la part de l'orchestrateur. |
||||||
|
|
||||||
|
* Les éventuelles tâches en cours d'exécution sur ce noeud continuent d'être exécutées sur ce noeud. |
||||||
|
|
||||||
|
|
||||||
|
Niveau _Drain_ : |
||||||
|
|
||||||
|
* Le noeud ne peut plus recevoir de nouvelles tâches de la part de l'orchestrateur. |
||||||
|
|
||||||
|
* Les éventuelles tâches en cours d'exécution sur ce noeud sont automatiquement basculées sur un noeud actif. |
||||||
|
|
||||||
|
* Ce mode est prévu pour la maintenance de l'hôte. |
||||||
|
|
||||||
|
|
||||||
|
### Task |
||||||
|
|
||||||
|
* Une tâche (_task_) est l'unité atomique directement orchestrable au sein du cluster Swarm. |
||||||
|
|
||||||
|
* Une tâche correspond à l'exécution d'_un conteneur_ sur _un noeud_ du cluster. |
||||||
|
|
||||||
|
|
||||||
|
* Les noeuds de type _manager_ assignent les _tâches_ directement aux noeuds de niveau _active_ selon le mode de mise à l'échelle défini pour le service (_replicated/global_). |
||||||
|
|
||||||
|
* Si l'exécution d'une tâche échoue, l'orchestrateur la supprime et en créé une nouvelle en remplacement. |
||||||
|
|
||||||
|
|
||||||
|
### Service |
||||||
|
|
||||||
|
* Un service est la formalisation de tâches (_tasks_) qui seront exécutées par les noeuds de niveau active. |
||||||
|
|
||||||
|
* Un service peut donc avoir plusieurs tâches. |
||||||
|
|
||||||
|
|
||||||
|
2 modes pour la scalabilité d'un service : |
||||||
|
|
||||||
|
* _Replicated_ : le manager génère des tâches de type réplica pour le service jusqu'à atteindre le nombre de réplicas souhaité et les distribue sur les noeuds active du cluster. |
||||||
|
|
||||||
|
* _Global_ : le manager lance une tâche du service sur chaque noeud disponible dans le cluster, ce qui peut se révéler pratique dans le cas d'agents de monitoring par exemple. |
||||||
|
|
||||||
|
|
||||||
|
La montée de version pour un _service_ donné peut être gérée de façon séquentielle (une tâche remplacée après l'autre) ou parallèle n tâches du service remplacées en même temps). |
||||||
|
|
||||||
|
|
||||||
|
### Overlay Network |
||||||
|
|
||||||
|
* Un réseau de type `overlay` est distribué sur l'ensemble des noeuds du cluster swarm. |
||||||
|
|
||||||
|
* Il permet de connecter un ou plusieurs services à l'intérieur du cluster Swarm sans avoir besoin de publier des ports réseau sur les hôtes. |
||||||
|
|
||||||
|
|
||||||
|
* La technologie `VXLAN` est utilisée pour créer les réseaux overlay au dessus du réseau existant. |
||||||
|
|
||||||
|
* Par défaut tout le trafic transitant sur un réseau overlay est en clair (pour des raisons de performance). |
||||||
|
|
||||||
|
* Il est possible de chiffrer un réseau overlay donné (Kernel `IPSEC` encryption) via l'ajout d'une option lors de sa création. |
||||||
|
|
||||||
|
|
||||||
|
Le tunnel ainsi créé permet aux conteneurs |
||||||
|
de communiquer même s'ils sont placés |
||||||
|
sur des hôtes différents. |
||||||
|
|
||||||
|
![Réseau Overlay](images/docker-networking-overlay.jpg) <!-- .element: width="650px" --> |
||||||
|
|
||||||
|
|
||||||
|
Chaque conteneur démarré sur un réseau overlay se voit attribuer deux adresses IP : une pour la communication entre les conteneurs du réseau <small>(10.0.0.x)</small> et une pour la VXLAN Tunnel End Point address (VTEP) <small>(172.18.0.x)</small>. |
||||||
|
|
||||||
|
![Réseau Overlay](images/docker-networking-overlay-addresses.jpg) <!-- .element: width="650px" --> |
||||||
|
|
||||||
|
|
||||||
|
Swarm permet de publier des services à l'extérieur en assignant un _PublishedPort_ à un service donné. |
||||||
|
|
||||||
|
Un port ainsi publié est ouvert sur tous les noeuds du cluster. Les requêtes sont routées automatiquement. |
||||||
|
|
||||||
|
|
||||||
|
![Réseau Overlay](images/docker-networking-overlay-routing.jpg) <!-- .element: width="650px" --> |
||||||
|
|
||||||
|
|
||||||
|
#### VIP et DNS |
||||||
|
|
||||||
|
* Par défaut une adresse IP virtuelle (VIP) et une entrée DNS sont créées pour chaque service géré par Swarm, le rendant ainsi disponible par son nom aux conteneurs présents sur le même réseau overlay. |
||||||
|
|
||||||
|
* Swarm intègre un service de _DNS interne_ permettant de résoudre facilement le nom d'un service. |
||||||
|
|
||||||
|
|
||||||
|
#### Load Balancing interne |
||||||
|
|
||||||
|
Swarm utilise un mécanisme interne de répartition de charge pour distribuer les requêtes aux services. |
||||||
|
|
||||||
|
![Réseau Ingress](images/swarm-network-ingress-routing-mesh.png) |
||||||
|
|
||||||
|
|
||||||
|
#### Load Balancing externe |
||||||
|
|
||||||
|
Des composants externes tels des _load balancers_ peuvent être placés en amont du cluster Swarm et accéder à un service sur le port publié (_PublishedPort_) à partir de n'importe quel noeud du cluster. |
||||||
|
|
||||||
|
|
||||||
|
Reverse Proxy et Load Balancing HAProxy |
||||||
|
|
||||||
|
![Réseau Ingress](images/swarm-network-ingress-lb.png) |
||||||
|
|
||||||
|
|
||||||
|
Swarm se charge ensuite de router de façon transparente les requêtes à destination du service sur l'un des noeuds exécutant une tâche correspondant au service demandé. |
||||||
|
|
||||||
|
|
||||||
|
### Stack |
||||||
|
|
||||||
|
* Une _stack_ est la formalisation d'une application composée d'un ou plusieurs services. |
||||||
|
|
||||||
|
* Elle se présente sous la forme d'un fichier de description `docker-compose.yml` |
||||||
|
|
||||||
|
* Il devient ainsi possible de déployer une application complexe sur l'ensemble du cluster. |
||||||
|
|
||||||
|
|
||||||
|
#### Stack = Swarm + Compose |
||||||
|
|
||||||
|
![Schema Docker Swarm](images/swarm3.png) <!-- .element: width="800px" --> |
||||||
|
|
||||||
|
|
||||||
|
### Secret |
||||||
|
|
||||||
|
Gestion sécurisée des données sensibles. |
||||||
|
|
||||||
|
|
||||||
|
* Exemples de données sensibles : |
||||||
|
|
||||||
|
- Nom d'utilisateur |
||||||
|
|
||||||
|
- Mot de passe |
||||||
|
|
||||||
|
- Certificats et clés TLS |
||||||
|
|
||||||
|
- Clés SSH |
||||||
|
|
||||||
|
- Nom d'une base de données |
||||||
|
|
||||||
|
- nom d'un serveur interne |
||||||
|
|
||||||
|
- Chaines de caractères ou fichier binaire (< 500 Kb) |
||||||
|
|
||||||
|
|
||||||
|
* Limitation : les secrets sont _utilisables seulement avec les services Swarm_. |
||||||
|
|
||||||
|
* Les secrets sont chiffrés et stokés par Swarm. |
||||||
|
|
||||||
|
* Les secrets sont distribués aux différents noeuds du cluster et transmis seulement aux services qui en font la demande. |
||||||
|
|
||||||
|
|
||||||
|
* Les secrets sont présentés aux conteneurs d'un service sous la formation d'un dossier en mémoire RAM monté dans `/run/secrets`. Ce dossier contient les secrets déchiffrés. |
||||||
|
|
||||||
|
* A partir de Docker 17.06 il est possible de définir l'emplacement où un secret doit être monté à l'intérieur du conteneur. |
||||||
|
|
||||||
|
|
||||||
|
### Config |
||||||
|
|
||||||
|
* Le concept de `config` est disponible à partir de Docker 17.06. |
||||||
|
|
||||||
|
* Il s'agit de l'équivalent des secrets mais pour des données non sensibles (par exemple un fichier de configuration). |
||||||
|
|
||||||
|
* Limitation : les configs sont _utilisables seulement avec les services Swarm_. |
||||||
|
|
||||||
|
|
||||||
|
* Le but des configs est d'éviter : |
||||||
|
- les montages de type `bind-mount` pour faire de la configuration, |
||||||
|
- l'utilisation de variables d'environnement. |
||||||
|
|
||||||
|
* Les données des configs ne sont pas chiffrées et sont montées directement dans système de fichiers du conteneur (sans utilisation de RAM disks). |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Manipuler Swarm |
||||||
|
|
||||||
|
Les fondamentaux |
||||||
|
|
||||||
|
|
||||||
|
### Initialisation du cluster |
||||||
|
|
||||||
|
Sur l'hôte Docker qui sera le premier _manager_ du cluster |
||||||
|
|
||||||
|
`$ docker swarm init --advertise-addr MANAGER-IP` |
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```nohighlight |
||||||
|
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager. |
||||||
|
|
||||||
|
To add a worker to this swarm, run the following command: |
||||||
|
|
||||||
|
docker swarm join \ |
||||||
|
--token SWMTKN-1-2scvxnrfa53pxfcf7w1qvdm25ofv6lg776tszvnjbtg727ozau \ |
||||||
|
192.168.99.100:2377 |
||||||
|
|
||||||
|
To add a manager to this swarm, run 'docker swarm join-token manager' and follow |
||||||
|
the instructions.Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) |
||||||
|
is now a manager. |
||||||
|
|
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Pour ajouter un _worker_ ou un _manager_ au cluster une seule commande suffit. |
||||||
|
|
||||||
|
<!-- .slide: data-state="cheat-sheet small-code" --> |
||||||
|
1. On peut retrouver cette commande depuis le premier manager : |
||||||
|
`$ docker swarm join-token worker` |
||||||
|
```nohighlight |
||||||
|
To add a worker to this swarm, run the following command: |
||||||
|
|
||||||
|
docker swarm join \ |
||||||
|
--token SWMTKN-1-2scvxnrfa53pxfcf7w1qvdm25ofv6lg776tszvnjbtg727ozau \ |
||||||
|
192.168.99.100:2377 |
||||||
|
``` |
||||||
|
`$ docker swarm join-token manager` |
||||||
|
```nohighlight |
||||||
|
To add a manager to this swarm, run the following command: |
||||||
|
|
||||||
|
docker swarm join \ |
||||||
|
--token SWMTKN-1-2scvxnrfa53pxfcf7w1qvdm25ofv6lg776tszvnjbtg727ozau \ |
||||||
|
192.168.99.100:2377 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Par exemple, on ajoute un _worker_ en jouant la commande récupérée précédemment. |
||||||
|
|
||||||
|
Sur le futur noeud _worker_ : |
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```nohighlight |
||||||
|
$ docker swarm join \ |
||||||
|
--token SWMTKN-1-2scvxnrfa53pxfcf7w1qvdm25ofv6lg776tszvnjbtg727ozau \ |
||||||
|
172.16.2.11:2377 |
||||||
|
This node joined a swarm as a worker. |
||||||
|
|
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Pour administrer les noeuds du Swarm on doit exécuter les commandes depuis un _manager_. |
||||||
|
|
||||||
|
|
||||||
|
Pour afficher les liste des noeuds : |
||||||
|
|
||||||
|
`$ docker node ls` |
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```nohighlight |
||||||
|
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS |
||||||
|
3raehvrbi5u0rz4y2kaqreakr * docker-node-1 Ready Active Leader |
||||||
|
jel9o08m2tcfmpyryt1d3nr59 docker-node-2 Ready Active Reachable |
||||||
|
lennvj9r57wgl6cwi5k7ac0cb docker-node-5 Ready Active |
||||||
|
om4pm2xcc9fl4uyehzeuwfklm docker-node-3 Ready Active Reachable |
||||||
|
ynj6x2tblko0ulvaz6ojrxueu docker-node-4 Ready Active |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="cheat-sheet" --> |
||||||
|
1. Pour transformer un noeud _worker_ en _manager_ : |
||||||
|
`$ docker node promote NODE` |
||||||
|
|
||||||
|
2. Et inversement : |
||||||
|
`$ docker node demote NODE` |
||||||
|
|
||||||
|
3. Pour supprimer un noeud du Swarm: |
||||||
|
`$ docker node rm NODE` |
||||||
|
|
||||||
|
|
||||||
|
#### Travaux pratiques |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
<small>[TP Initialisation d'un cluster Swarm](../travaux-pratiques/slides/swarm/tp-swarm-init.html)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Services |
||||||
|
<!-- .slide: data-state="medium-code" --> |
||||||
|
Pour lancer un service sur le cluster Swarm : |
||||||
|
`docker service create` |
||||||
|
```nohighlight |
||||||
|
$ docker service create --name busybox busybox sleep 600 |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
`docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]` |
||||||
|
|
||||||
|
Créer un nouveau service |
||||||
|
|
||||||
|
<!-- .slide: data-state="medium-table" --> |
||||||
|
Option | Description |
||||||
|
-------------------------|--------------------------------------- |
||||||
|
`--constraint` | Placement constraints |
||||||
|
`--network` | Network attachments |
||||||
|
`--name` | Service name |
||||||
|
`--publish` | Publish a port as a node port |
||||||
|
`--replicas` | Number of tasks |
||||||
|
`...` | <small>[https://docs.docker.com/engine/reference/ commandline/service_create/](https://docs.docker.com/engine/reference/commandline/service_create/)</small> |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="cheat-sheet" data-state="small-code" --> |
||||||
|
1. Lister les services du cluster : |
||||||
|
`$ docker service ls` |
||||||
|
```nohighlight |
||||||
|
ID NAME MODE REPLICAS IMAGE |
||||||
|
uutgao0sp6qi busybox replicated 1/1 busybox:latest |
||||||
|
``` |
||||||
|
|
||||||
|
2. Supprimer un service : |
||||||
|
`$ docker service rm SERVICE` |
||||||
|
|
||||||
|
3. Mettre à jour un service avec : |
||||||
|
`$ docker service update [OPTIONS] SERVICE` |
||||||
|
|
||||||
|
4. Pour revenir à la version précédente de la configuration d'un service : |
||||||
|
`$ docker service rollback SERVICE` |
||||||
|
|
||||||
|
|
||||||
|
Par exemple, il est possible d'ajouter une contrainte sur un service pour qu'il ne démarre que sur un noeud spécifique. |
||||||
|
|
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```bash |
||||||
|
$ docker service update --constraint-add 'node.hostname == <NODE.HOSTNAME>' busybox |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
On peut revenir à la configuration précédente en utilisant la fonctionnalité de rollback. |
||||||
|
```nohighlight |
||||||
|
$ docker service rollback busybox |
||||||
|
``` |
||||||
|
|
||||||
|
Attention, on ne peut pas revenir en arrière plusieurs fois d'affilé. |
||||||
|
|
||||||
|
|
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
Pour voir en détail les _tasks_ d'un service : |
||||||
|
`docker service ps SERVICE` |
||||||
|
```nohighlight |
||||||
|
$ docker service ps busybox |
||||||
|
ID NAME IMAGE NODE DESIRED STATE |
||||||
|
uzb1ovvp4tnx busybox.1 busybox:latest docker-node-1 Running |
||||||
|
cs5vud4gpq1n \_ busybox.1 busybox:latest docker-node-2 Shutdown |
||||||
|
``` |
||||||
|
```nohighlight |
||||||
|
$ docker service ps busybox --filter desired-state=Running |
||||||
|
ID NAME IMAGE NODE DESIRED STATE |
||||||
|
uzb1ovvp4tnx busybox.1 busybox:latest docker-node-1 Running |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Pour mettre à l'échelle un service : |
||||||
|
`docker service scale SERVICE=REPLICAS` |
||||||
|
<!-- .slide: data-state="small-code" --> |
||||||
|
```nohighlight |
||||||
|
$ docker service scale busybox=3 |
||||||
|
busybox scaled to 3 |
||||||
|
|
||||||
|
$ docker service ps busybox |
||||||
|
ID NAME IMAGE NODE DESIRED STATE |
||||||
|
uzb1ovvp4tnx busybox.1 busybox:latest docker-node-1 Running |
||||||
|
cs5vud4gpq1n \_ busybox.1 busybox:latest docker-node-2 Shutdown |
||||||
|
pmdpmocyf106 busybox.2 busybox:latest docker-node-1 Running |
||||||
|
hzk9x2ak8win busybox.3 busybox:latest docker-node-1 Running |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Pour déployer une _stack_ |
||||||
|
|
||||||
|
`docker stack deploy [OPTIONS] STACK` |
||||||
|
|
||||||
|
* Une multitude de nouvelles options a été ajouté dans le version 3 du format _docker-compose.yml_. |
||||||
|
|
||||||
|
* https://docs.docker.com/compose/compose-file/ |
||||||
|
|
||||||
|
|
||||||
|
`docker stack COMMAND` |
||||||
|
|
||||||
|
Gère une stack Docker |
||||||
|
|
||||||
|
Commande | Description |
||||||
|
- | - |
||||||
|
`deploy` | Déploie une nouvelle stack ou met à jour une stack existante |
||||||
|
`ls` | Liste les stacks |
||||||
|
`services` | Liste les services de la stack |
||||||
|
`ps` | Liste les tasks de la stack |
||||||
|
`rm` | Supprime la stack |
||||||
|
|
||||||
|
|
||||||
|
### Travaux pratiques |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
<small>[TP Déploiement d'applications sur Swarm](../travaux-pratiques/slides/swarm/tp-swarm.html)</small> |
||||||
|
|
||||||
|
<small>[TP Docker Secret](../travaux-pratiques/slides/swarm/tp-secrets.html)</small> |
||||||
|
|
||||||
|
<small>[TP Rolling Update](../travaux-pratiques/slides/swarm/tp-rolling-update.html)</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Dépannage |
||||||
|
|
||||||
|
Se sortir de situations difficiles |
||||||
|
|
||||||
|
|
||||||
|
### Dépannage Manager |
||||||
|
|
||||||
|
Si un noeud `Manager` est défaillant, la solution peut être de lui faire quitter puis rejoindre le cluster. |
||||||
|
|
||||||
|
1. Rétrograder le Manager en worker : |
||||||
|
`docker node demote <MANAGER>` |
||||||
|
|
||||||
|
2. Supprimer le Node du cluster : |
||||||
|
`docker node rm <NODE>`. |
||||||
|
|
||||||
|
3. Re-joindre le Node au cluster : |
||||||
|
`docker swarm join`. |
||||||
|
|
||||||
|
<small>Source : [https://docs.docker.com/engine/swarm/admin_guide/#troubleshoot-a-manager-node](https://docs.docker.com/engine/swarm/admin_guide/#troubleshoot-a-manager-node)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Sauvegarde de l'état d'un Manager |
||||||
|
|
||||||
|
1. Si l'auto-lock est activé, le désactiver. |
||||||
|
|
||||||
|
2. Stopper Docker sur l'hôte cible. |
||||||
|
|
||||||
|
3. Sauvegarder le répertoire `/var/lib/docker/swarm` |
||||||
|
|
||||||
|
4. Redémarrer Docker. |
||||||
|
|
||||||
|
<small>Source : [https://docs.docker.com/engine/swarm/admin_guide/#back-up-the-swarm](https://docs.docker.com/engine/swarm/admin_guide/#back-up-the-swarm)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Restaurer l'état d'un Manager |
||||||
|
|
||||||
|
1. Stopper Docker sur l'hôte cible. |
||||||
|
|
||||||
|
2. Supprimer le dossier `/var/lib/docker/swarm` |
||||||
|
|
||||||
|
3. Restaurer le dossier `/var/lib/docker/swarm` depuis une sauvegarde. |
||||||
|
|
||||||
|
4. Démarrer Docker sur le nouveau noeud, et réinitialiser le noeud avec |
||||||
|
`docker swarm init --force-new-cluster` |
||||||
|
|
||||||
|
5. Vérifier l'état du swarm. |
||||||
|
|
||||||
|
<small>Source : [https://docs.docker.com/engine/swarm/admin_guide/#recover-from-disaster](https://docs.docker.com/engine/swarm/admin_guide/#recover-from-disaster)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Logging |
||||||
|
|
||||||
|
Les logs des démons Docker et Swarm se situent : |
||||||
|
<!-- .slide: data-state="small-table" --> |
||||||
|
|
||||||
|
Operating system | Location |
||||||
|
-----------------------|------------------------ |
||||||
|
RHEL, Oracle Linux | `/var/log/messages` |
||||||
|
Debian | `/var/log/daemon.log` |
||||||
|
Ubuntu 16.04+, CentOS | Use the command `journalctl -u docker.service` |
||||||
|
Ubuntu 14.10- | `/var/log/upstart/docker.log` |
||||||
|
macOS | `~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/console-ring` |
||||||
|
Windows | `AppData\Local` |
||||||
|
|
||||||
|
|
||||||
|
### Enable Debugging |
||||||
|
|
||||||
|
Pour activer le debugging du démon Docker, éditer le fichier `/etc/docker/daemon.json` pour y ajouter : |
||||||
|
|
||||||
|
``` |
||||||
|
{ |
||||||
|
"debug": true |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Rédémarrer le démon ou recharger sa configuration. |
||||||
|
|
||||||
|
<small>Source : [https://docs.docker.com/engine/admin/](https://docs.docker.com/engine/admin/#force-a-stack-trace-to-be-logged)</small> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Reverse Proxy |
||||||
|
|
||||||
|
Accéder au cluster Swarm depuis l'extérieur |
||||||
|
|
||||||
|
|
||||||
|
### Traefik |
||||||
|
|
||||||
|
https://traefik.io/ |
||||||
|
|
||||||
|
* Reverse Proxy HTTP & Load Balancer |
||||||
|
|
||||||
|
* Rapide |
||||||
|
|
||||||
|
* Supporte une grande variété de backends |
||||||
|
(Docker, Swarm, Kubernetes, Mesos/Marathon, Consul, Etcd, Rest API, file...) |
||||||
|
|
||||||
|
|
||||||
|
* Configuration dynamique pour simplifier l'accès aux applications orientées micro-services |
||||||
|
|
||||||
|
* Gestion automatique des certificats TLS avec Let's Encrypt |
||||||
|
|
||||||
|
* Interface web de supervision |
||||||
|
|
||||||
|
|
||||||
|
### Fonctionnement |
||||||
|
|
||||||
|
* Traefik se lance dans un conteneur sur le cluster et se connecte à la socket Docker pour écouter les évènements du cluster. |
||||||
|
|
||||||
|
* Les conteneurs applicatifs déclarent des _labels traefik.*_ afin de se signaler auprès de Traefik. |
||||||
|
|
||||||
|
|
||||||
|
### Schéma de principe |
||||||
|
|
||||||
|
![Schema Traefik](images/traefik.png) |
||||||
|
|
||||||
|
|
||||||
|
### Travaux pratiques |
||||||
|
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||||
|
![Travaux pratiques](images/tp.gif) |
||||||
|
|
||||||
|
<small>[TP Traefik](../travaux-pratiques/slides/swarm/tp-traefik.html)</small> |
||||||
|
|
||||||
|
|
||||||
|
### Plus de détails sur Traefik v2 |
||||||
|
|
||||||
|
* https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d |
||||||
|
* https://blog.containo.us/traefik-2-tls-101-23b4fbee81f1 |
||||||
|
|
||||||
|
|
||||||
|
## Stockage distribué |
||||||
|
|
||||||
|
GlusterFS |
||||||
|
|
||||||
|
|
||||||
|
Lorsque des applications sont déployées sur plusieurs noeuds, il devient nécessaire de : |
||||||
|
|
||||||
|
* Rendre certaines données accessibles sur tous les noeuds du cluster Swarm. |
||||||
|
|
||||||
|
* Rendre possible la persistance des données des conteneurs sur n'importe quel noeud. |
||||||
|
|
||||||
|
|
||||||
|
* GlusterFS est un système de fichiers libre distribué, qui permet de stocker jusqu'à plusieurs pétaoctets. |
||||||
|
|
||||||
|
* GlusterFS réplique automatiquement les données sur tous les noeuds du cluster de stockage. |
||||||
|
|
||||||
|
|
||||||
|
GlusterFS repose sur un modèle client-serveur. |
||||||
|
|
||||||
|
* Les serveurs sont déployés comme des "briques de stockage", chaque serveur exécutant un daemon qui exporte un système de fichier local comme un _volume_. |
||||||
|
|
||||||
|
* Les clients sont sans état, et ne communiquent pas entre eux. Ils peuvent monter les volumes exportés par les serveurs. |
||||||
|
|
||||||
|
|
||||||
|
![GlusterFS](images/glusterfs.png) |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 35 KiB |