diff --git a/slides/intro-fullday.yml b/slides/intro-fullday.yml
index b7767674..80e365e9 100644
--- a/slides/intro-fullday.yml
+++ b/slides/intro-fullday.yml
@@ -44,6 +44,7 @@ chapters:
- intro/Docker_Machine.md
- intro/Advanced_Dockerfiles.md
- intro/Application_Configuration.md
+ - intro/Logging.md
- - intro/Namespaces_Cgroups.md
- intro/Copy_On_Write.md
#- intro/Containers_From_Scratch.md
diff --git a/slides/intro-selfpaced.yml b/slides/intro-selfpaced.yml
index 43c50840..883184f5 100644
--- a/slides/intro-selfpaced.yml
+++ b/slides/intro-selfpaced.yml
@@ -16,7 +16,7 @@ chapters:
- common/about-slides.md
- common/toc.md
- - intro/Docker_Overview.md
- #- intro/Docker_History.md
+ - intro/Docker_History.md
- intro/Training_Environment.md
- intro/Installing_Docker.md
- intro/First_Containers.md
@@ -31,6 +31,7 @@ chapters:
- intro/Publishing_To_Docker_Hub.md
- intro/Dockerfile_Tips.md
- - intro/Naming_And_Inspecting.md
+ - intro/Labels.md
- intro/Getting_Inside.md
- intro/Container_Networking_Basics.md
- intro/Network_Drivers.md
@@ -40,6 +41,15 @@ chapters:
- - intro/Local_Development_Workflow.md
- intro/Working_With_Volumes.md
- intro/Compose_For_Dev_Stacks.md
+ - intro/Docker_Machine.md
- intro/Advanced_Dockerfiles.md
+ - intro/Application_Configuration.md
+ - intro/Logging.md
+- - intro/Namespaces_Cgroups.md
+ - intro/Copy_On_Write.md
+ #- intro/Containers_From_Scratch.md
+ - intro/Container_Engines.md
+ - intro/Ecosystem.md
+ - intro/Orchestration_Overview.md
- common/thankyou.md
- intro/links.md
diff --git a/slides/intro/Logging.md b/slides/intro/Logging.md
new file mode 100644
index 00000000..c5b463c3
--- /dev/null
+++ b/slides/intro/Logging.md
@@ -0,0 +1,273 @@
+# Logging
+
+In this chapter, we will explain the different ways to send logs from containers.
+
+We will then show one particular method in action, using ELK and Docker's logging drivers.
+
+---
+
+## There are many ways to send logs
+
+- The simplest method is to write on the standard output and error.
+
+- Applications can write their logs to local files.
+
+ (The files are usually periodically rotated and compressed.)
+
+- It is also very common (on UNIX systems) to use syslog.
+
+ (The logs are collected by syslogd or an equivalent like journald.)
+
+- In large applications with many components, it is common to use a logging service.
+
+ (The code uses a library to send messages to the logging service.)
+
+*All these methods are available with containers.*
+
+---
+
+## Writing on stdout/stderr
+
+- The standard output and error of containers is managed by the container engine.
+
+- This means that each line written by the container is received by the engine.
+
+- The engine can then do "whatever" with these log lines.
+
+- With Docker, the default configuration is to write the logs to local files.
+
+- The files can then be queried with e.g. `docker logs` (and the equivalent API request).
+
+- This can be customized, as we will see later.
+
+---
+
+## Writing to local files
+
+- If we write to files, it is possible to access them but cumbersome.
+
+ (We have to use `docker exec` or `docker cp`.)
+
+- Furthermore, if the container is stopped, we cannot use `docker exec`.
+
+- If the container is deleted, the logs disappear.
+
+- What should we do for programs who can only log to local files?
+
+--
+
+- There are multiple solutions.
+
+---
+
+## Using a volume or bind mount
+
+- Instead of writing logs to a normal directory, we can place them on a volume.
+
+- The volume can be accessed by other containers.
+
+- We can run a program like `filebeat` in another container accessing the same volume.
+
+ (`filebeat` reads local log files continuously, like `tail -f`, and sends them
+ to a centralized system like ElasticSearch.)
+
+- We can also use a bind mount, e.g. `-v /var/log/containers/www:/var/log/tomcat`.
+
+- The container will write log files to a directory mapped to a host directory.
+
+- The log files will appear on the host and be consumable directly from the host.
+
+---
+
+## Using logging services
+
+- We can use logging frameworks (like log4j or the Python `logging` package).
+
+- These frameworks require some code and/or configuration in our application code.
+
+- These mechanisms can be used identically inside or outside of containers.
+
+- Sometimes, we can leverage containerized networking to simplify their setup.
+
+- For instance, our code can send log messages to a server named `log`.
+
+- The name `log` will resolve to different addresses in development, production, etc.
+
+---
+
+## Using syslog
+
+- What if our code (or the program we are running in containers) uses syslog?
+
+- One possibility is to run a syslog daemon in the container.
+
+- Then that daemon can be setup to write to local files or forward to the network.
+
+- Under the hood, syslog clients connect to a local UNIX socket, `/dev/log`.
+
+- We can expose a syslog socket to the container (by using a volume or bind-mount).
+
+- Then just create a symlink from `/dev/log` to the syslog socket.
+
+- VoilĂ !
+
+---
+
+## Using logging drivers
+
+- If we log to stdout and stderr, the container engine receives the log messages.
+
+- The Docker Engine has a modular logging system with many plugins, including:
+
+ - json-file (the default one)
+ - syslog
+ - journald
+ - gelf
+ - fluentd
+ - splunk
+ - etc.
+
+- Each plugin can process and forward the logs to another process or system.
+
+---
+
+## Demo: sending logs to ELK
+
+- We are going to deploy an ELK stack.
+
+- It will accept logs over a GELF socket.
+
+- We will run a few containers with the `gelf` logging driver.
+
+- We will then see our logs in Kibana, the web interface provided by ELK.
+
+*Important foreword: this is not an "official" or "recommended"
+setup; it is just an example. We used ELK in this demo because
+it's a popular setup and we keep being asked about it; but you
+will have equal success with Fluent or other logging stacks!*
+
+---
+
+## What's in an ELK stack?
+
+- ELK is three components:
+
+ - ElasticSearch (to store and index log entries)
+
+ - Logstash (to receive log entries from various
+ sources, process them, and forward them to various
+ destinations)
+
+ - Kibana (to view/search log entries with a nice UI)
+
+- The only component that we will configure is Logstash
+
+- We will accept log entries using the GELF protocol
+
+- Log entries will be stored in ElasticSearch,
+
and displayed on Logstash's stdout for debugging
+
+---
+
+## Running ELK
+
+- We are going to use a Compose file describing the ELK stack.
+
+```bash
+$ cd ~/container.training/stacks
+$ docker-compose -f elk.yml up -d
+```
+
+- Let's have a look at the Compose file while it's deploying.
+
+---
+
+## Our basic ELK deployment
+
+- We are using images from the Docker Hub: `elasticsearch`, `logstash`, `kibana`.
+
+- We don't need to change the configuration of ElasticSearch.
+
+- We need to tell Kibana the address of ElasticSearch:
+
+ - it is set with the `ELASTICSEARCH_URL` environment variable,
+
+ - by default it is `localhost:9200`, we change it to `elastichsearch:9200`.
+
+- We need to configure Logstash:
+
+ - we pass the entire configuration file through command-line arguments,
+
+ - this is a hack so that we don't have to create an image just for the config.
+
+---
+
+## Sending logs to ELK
+
+- The ELK stack accepts log messages through a GELF socket.
+
+- The GELF socket listens on UDP port 12201.
+
+- To send a message, we need to change the logging driver used by Docker.
+
+- This can be done globally (by reconfiguring the Engine) or on a per-container basis.
+
+- Let's override the logging driver for a single container:
+
+```bash
+$ docker run --log-driver=gelf --log-opt=gelf-address=udp://localhost:12201 \
+ alpine echo hello world
+```
+
+---
+
+## Viewing the logs in ELK
+
+- Connect to the Kibana interface.
+
+- It is exposed on port 5601.
+
+- Browse http://X.X.X.X:5601.
+
+---
+
+## "Configuring" Kibana
+
+- Kibana should offer you to "Configure an index pattern":
+
in the "Time-field name" drop down, select "@timestamp", and hit the
+ "Create" button.
+
+- Then:
+
+ - click "Discover" (in the top-left corner),
+ - click "Last 15 minutes" (in the top-right corner),
+ - click "Last 1 hour" (in the list in the middle),
+ - click "Auto-refresh" (top-right corner),
+ - click "5 seconds" (top-left of the list).
+
+- You should see a series of green bars (with one new green bar every minute).
+
+- Our 'hello world' message should be visible there.
+
+---
+
+## Important afterword
+
+**This is not a "production-grade" setup.**
+
+It is just an educational example. Since we have only
+one node , we did set up a single
+ElasticSearch instance and a single Logstash instance.
+
+In a production setup, you need an ElasticSearch cluster
+(both for capacity and availability reasons). You also
+need multiple Logstash instances.
+
+And if you want to withstand
+bursts of logs, you need some kind of message queue:
+Redis if you're cheap, Kafka if you want to make sure
+that you don't drop messages on the floor. Good luck.
+
+If you want to learn more about the GELF driver,
+have a look at [this blog post](
+http://jpetazzo.github.io/2017/01/20/docker-logging-gelf/).