From 0feda940544b3df5c00a04d6f4cc6777f461b7c4 Mon Sep 17 00:00:00 2001 From: Marco Verleun Date: Tue, 6 Jun 2023 13:54:40 +0200 Subject: [PATCH] New HTML --- slides/intro-container-security.yml.html | 6 +- slides/intro-fd-docker.yml.html | 1165 +- slides/intro-fd-k8s-deployments.yml.html | 6 +- slides/intro-fd-k8s.yml.html | 6 +- slides/intro-fullday.yml.html | 6 +- slides/intro-selfpaced.yml.html | 6 +- slides/intro-triodos-1-day.yml.html | 12233 --------------------- 7 files changed, 293 insertions(+), 13135 deletions(-) diff --git a/slides/intro-container-security.yml.html b/slides/intro-container-security.yml.html index 3a9b0c7..759351a 100644 --- a/slides/intro-container-security.yml.html +++ b/slides/intro-container-security.yml.html @@ -31,13 +31,11 @@ i share: Introduction Container Security and Hardening
``` M slides/airgapped/Importing_Images.md M slides/intro-container-security.yml.html - M slides/swarm-halfday.yml.html - M slides/swarm-selfpaced.yml.html - M slides/swarm-video.yml.html + M slides/intro-fd-docker.yml ``` -These slides have been built from commit: 65fec64 +These slides have been built from commit: 1e1b023 [shared/title.md](""/tree/main/slides/shared/title.md)] diff --git a/slides/intro-fd-docker.yml.html b/slides/intro-fd-docker.yml.html index 3c602c8..71fcf26 100644 --- a/slides/intro-fd-docker.yml.html +++ b/slides/intro-fd-docker.yml.html @@ -31,14 +31,12 @@ Introduction to Containers in an Airgapped Environment
``` M slides/airgapped/Importing_Images.md M slides/intro-container-security.yml.html + M slides/intro-fd-docker.yml M slides/intro-fd-docker.yml.html - M slides/swarm-halfday.yml.html - M slides/swarm-selfpaced.yml.html - M slides/swarm-video.yml.html ``` -These slides have been built from commit: 65fec64 +These slides have been built from commit: 1e1b023 [shared/title.md](""/tree/main/slides/shared/title.md)] @@ -554,8 +552,6 @@ name: toc-part-4 - [Local development workflow with Docker](#toc-local-development-workflow-with-docker) -- [Compose for development stacks](#toc-compose-for-development-stacks) - .debug[(auto-generated TOC)] --- @@ -563,7 +559,7 @@ name: toc-part-5 ## Part 5 -- [Our sample application](#toc-our-sample-application) +- [Logging](#toc-logging) - [Links and resources](#toc-links-and-resources) @@ -4395,7 +4391,7 @@ class: title | [Back to table of contents](#toc-part-4) | -[Next part](#toc-compose-for-development-stacks) +[Next part](#toc-logging) ] .debug[(automatically generated title slide)] @@ -4885,551 +4881,14 @@ class: pic --- -name: toc-compose-for-development-stacks +name: toc-logging class: title - Compose for development stacks + Logging .nav[ [Previous part](#toc-local-development-workflow-with-docker) | -[Back to table of contents](#toc-part-4) -| -[Next part](#toc-our-sample-application) -] - -.debug[(automatically generated title slide)] - ---- -# Compose for development stacks - -Dockerfile = great to build *one* container image. - -What if we have multiple containers? - -What if some of them require particular `docker run` parameters? - -How do we connect them all together? - -... Compose solves these use-cases (and a few more). - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Life before Compose - -Before we had Compose, we would typically write custom scripts to: - -- build container images, - -- run containers using these images, - -- connect the containers together, - -- rebuild, restart, update these images and containers. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Life with Compose - -Compose enables a simple, powerful onboarding workflow: - -1. Checkout our code. - -2. Run `docker-compose up`. - -3. Our app is up and running! - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -class: pic - -![composeup](images/composeup.gif) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Life after Compose - -(Or: when do we need something else?) - -- Compose is *not* an orchestrator - -- It isn't designed to need to run containers on multiple nodes - - (it can, however, work with Docker Swarm Mode) - -- Compose isn't ideal if we want to run containers on Kubernetes - - - it uses different concepts (Compose services ≠ Kubernetes services) - - - it needs a Docker Engine (although containerd support might be coming) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## First rodeo with Compose - -1. Write Dockerfiles - -2. Describe our stack of containers in a YAML file called `docker-compose.yml` - -3. `docker-compose up` (or `docker-compose up -d` to run in the background) - -4. Compose pulls and builds the required images, and starts the containers - -5. Compose shows the combined logs of all the containers - - (if running in the background, use `docker-compose logs`) - -6. Hit Ctrl-C to stop the whole stack - - (if running in the background, use `docker-compose stop`) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Iterating - -After making changes to our source code, we can: - -1. `docker-compose build` to rebuild container images - -2. `docker-compose up` to restart the stack with the new images - -We can also combine both with `docker-compose up --build` - -Compose will be smart, and only recreate the containers that have changed. - -When working with interpreted languages: - -- don't rebuild each time - -- leverage a `volumes` section instead - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Launching Our First Stack with Compose - -First step: clone the source code for the app we will be working on. - -```bash -git clone https://github.com/jpetazzo/trainingwheels -cd trainingwheels -``` - -Second step: start the app. - -```bash -docker-compose up -``` - -Watch Compose build and run the app. - -That Compose stack exposes a web server on port 8000; try connecting to it. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Launching Our First Stack with Compose - -We should see a web page like this: - -![composeapp](images/composeapp.png) - -Each time we reload, the counter should increase. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Stopping the app - -When we hit Ctrl-C, Compose tries to gracefully terminate all of the containers. - -After ten seconds (or if we press `^C` again) it will forcibly kill them. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## The `docker-compose.yml` file - -Here is the file used in the demo: - -.small[ -```yaml -version: "3" - -services: - www: - build: www - ports: - - ${PORT-8000}:5000 - user: nobody - environment: - DEBUG: 1 - command: python counter.py - volumes: - - ./www:/src - - redis: - image: redis -``` -] - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Compose file structure - -A Compose file has multiple sections: - -* `version` is mandatory. (Typically use "3".) - -* `services` is mandatory. Each service corresponds to a container. - -* `networks` is optional and indicates to which networks containers should be connected. -
(By default, containers will be connected on a private, per-compose-file network.) - -* `volumes` is optional and can define volumes to be used and/or shared by the containers. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Compose file versions - -* Version 1 is legacy and shouldn't be used. - - (If you see a Compose file without `version` and `services`, it's a legacy v1 file.) - -* Version 2 added support for networks and volumes. - -* Version 3 added support for deployment options (scaling, rolling updates, etc). - -* Typically use `version: "3"`. - -The [Docker documentation](https://docs.docker.com/compose/compose-file/) -has excellent information about the Compose file format if you need to know more about versions. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Containers in `docker-compose.yml` - -Each service in the YAML file must contain either `build`, or `image`. - -* `build` indicates a path containing a Dockerfile. - -* `image` indicates an image name (local, or on a registry). - -* If both are specified, an image will be built from the `build` directory and named `image`. - -The other parameters are optional. - -They encode the parameters that you would typically add to `docker run`. - -Sometimes they have several minor improvements. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Container parameters - -* `command` indicates what to run (like `CMD` in a Dockerfile). - -* `ports` translates to one (or multiple) `-p` options to map ports. -
You can specify local ports (i.e. `x:y` to expose public port `x`). - -* `volumes` translates to one (or multiple) `-v` options. -
You can use relative paths here. - -For the full list, check: https://docs.docker.com/compose/compose-file/ - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Environment variables - -- We can use environment variables in Compose files - - (like `$THIS` or `${THAT}`) - -- We can provide default values, e.g. `${PORT-8000}` - -- Compose will also automatically load the environment file `.env` - - (it should contain `VAR=value`, one per line) - -- This is a great way to customize build and run parameters - - (base image versions to use, build and run secrets, port numbers...) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Configuring a Compose stack - -- Follow [12-factor app configuration principles][12factorconfig] - - (configure the app through environment variables) - -- Provide (in the repo) a default environment file suitable for development - - (no secret or sensitive value) - -- Copy the default environment file to `.env` and tweak it - - (or: provide a script to generate `.env` from a template) - -[12factorconfig]: https://12factor.net/config - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Running multiple copies of a stack - -- Copy the stack in two different directories, e.g. `front` and `frontcopy` - -- Compose prefixes images and containers with the directory name: - - `front_www`, `front_www_1`, `front_db_1` - - `frontcopy_www`, `frontcopy_www_1`, `frontcopy_db_1` - -- Alternatively, use `docker-compose -p frontcopy` - - (to set the `--project-name` of a stack, which default to the dir name) - -- Each copy is isolated from the others (runs on a different network) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Checking stack status - -We have `ps`, `docker ps`, and similarly, `docker-compose ps`: - -```bash -$ docker-compose ps -Name Command State Ports ----------------------------------------------------------------------------- -trainingwheels_redis_1 /entrypoint.sh red Up 6379/tcp -trainingwheels_www_1 python counter.py Up 0.0.0.0:8000->5000/tcp -``` - -Shows the status of all the containers of our stack. - -Doesn't show the other containers. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Cleaning up (1) - -If you have started your application in the background with Compose and -want to stop it easily, you can use the `kill` command: - -```bash -$ docker-compose kill -``` - -Likewise, `docker-compose rm` will let you remove containers (after confirmation): - -```bash -$ docker-compose rm -Going to remove trainingwheels_redis_1, trainingwheels_www_1 -Are you sure? [yN] y -Removing trainingwheels_redis_1... -Removing trainingwheels_www_1... -``` - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Cleaning up (2) - -Alternatively, `docker-compose down` will stop and remove containers. - -It will also remove other resources, like networks that were created for the application. - -```bash -$ docker-compose down -Stopping trainingwheels_www_1 ... done -Stopping trainingwheels_redis_1 ... done -Removing trainingwheels_www_1 ... done -Removing trainingwheels_redis_1 ... done -``` - -Use `docker-compose down -v` to remove everything including volumes. - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Special handling of volumes - -- When an image gets updated, Compose automatically creates a new container - -- The data in the old container is lost... - -- ...Except if the container is using a *volume* - -- Compose will then re-attach that volume to the new container - - (and data is then retained across database upgrades) - -- All good database images use volumes - - (e.g. all official images) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Gotchas with volumes - -- Unfortunately, Docker volumes don't have labels or metadata - -- Compose tracks volumes thanks to their associated container - -- If the container is deleted, the volume gets orphaned - -- Example: `docker-compose down && docker-compose up` - - - the old volume still exists, detached from its container - - - a new volume gets created - -- `docker-compose down -v`/`--volumes` deletes volumes - - (but **not** `docker-compose down && docker-compose down -v`!) - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Managing volumes explicitly - -Option 1: *named volumes* - -```yaml -services: - app: - volumes: - - data:/some/path -volumes: - data: -``` - -- Volume will be named `_data` - -- It won't be orphaned with `docker-compose down` - -- It will correctly be removed with `docker-compose down -v` - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Managing volumes explicitly - -Option 2: *relative paths* - -```yaml -services: - app: - volumes: - - ./data:/some/path -``` - -- Makes it easy to colocate the app and its data - - (for migration, backups, disk usage accounting...) - -- Won't be removed by `docker-compose down -v` - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Managing complex stacks - -- Compose provides multiple features to manage complex stacks - - (with many containers) - -- `-f`/`--file`/`$COMPOSE_FILE` can be a list of Compose files - - (separated by `:` and merged together) - -- Services can be assigned to one or more *profiles* - -- `--profile`/`$COMPOSE_PROFILE` can be a list of comma-separated profiles - - (see [Using service profiles][profiles] in the Compose documentation) - -- These variables can be set in `.env` - -[profiles]: https://docs.docker.com/compose/profiles/ - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -## Dependencies - -- A service can have a `depends_on` section - - (listing one or more other services) - -- This is used when bringing up individual services - - (e.g. `docker-compose up blah` or `docker-compose run foo`) - -⚠️ It doesn't make a service "wait" for another one to be up! - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -class: extra-details - -## A bit of history and trivia - -- Compose was initially named "Fig" - -- Compose is one of the only components of Docker written in Python - - (almost everything else is in Go) - -- In 2020, Docker introduced "Compose CLI": - - - `docker compose` command to deploy Compose stacks to some clouds - - - progressively getting feature parity with `docker-compose` - - - also provides numerous improvements (e.g. leverages BuildKit by default) - -??? - -:EN:- Using compose to describe an environment -:EN:- Connecting services together with a *Compose file* - -:FR:- Utiliser Compose pour décrire son environnement -:FR:- Écrire un *Compose file* pour connecter les services entre eux - -.debug[[containers/Compose_For_Dev_Stacks.md](""/tree/main/slides/containers/Compose_For_Dev_Stacks.md)] ---- - -class: pic - -.interstitial[![Image separating from the next part](https://gallant-turing-d0d520.netlify.com/containers/wall-of-containers.jpeg)] - ---- - -name: toc-our-sample-application -class: title - - Our sample application - -.nav[ -[Previous part](#toc-compose-for-development-stacks) -| [Back to table of contents](#toc-part-5) | [Next part](#toc-links-and-resources) @@ -5438,385 +4897,327 @@ class: title .debug[(automatically generated title slide)] --- -# Our sample application +# Logging -- We will clone the GitHub repository onto our `node1` +In this chapter, we will explain the different ways to send logs from containers. -- The repository also contains scripts and tools that we will use through the workshop +We will then show one particular method in action, using ELK and Docker's logging drivers. -.lab[ +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] +--- - -- Clone the repository on `node1`: - ```bash - git clone https://github.com/jpetazzo/container.training - ``` - -] - -(You can also fork the repository on GitHub and clone your fork if you prefer that.) - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] --- -## Downloading and running the application +## Demo: sending logs to ELK -Let's start this before we look around, as downloading will take a little time... +- We are going to deploy an ELK stack. -.lab[ +- It will accept logs over a GELF socket. -- Go to the `dockercoins` directory, in the cloned repository: - ```bash - cd ~/container.training/dockercoins - ``` +- We will run a few containers with the `gelf` logging driver. -- Use Compose to build and run all containers: - ```bash - docker-compose up - ``` +- 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!* -] - -Compose tells Docker to build all container images (pulling -the corresponding base images), then starts all containers, -and displays aggregated logs. - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] --- -## What's this application? +## What's in an ELK stack? --- +- ELK is three components: -- It is a DockerCoin miner! 💰🐳📦🚢 + - ElasticSearch (to store and index log entries) --- + - Logstash (to receive log entries from various + sources, process them, and forward them to various + destinations) -- No, you can't buy coffee with DockerCoin + - Kibana (to view/search log entries with a nice UI) --- +- The only component that we will configure is Logstash -- How dockercoins works: +- We will accept log entries using the GELF protocol - - generate a few random bytes +- Log entries will be stored in ElasticSearch, +
and displayed on Logstash's stdout for debugging - - hash these bytes - - - increment a counter (to keep track of speed) - - - repeat forever! - --- - -- DockerCoin is *not* a cryptocurrency - - (the only common points are "randomness," "hashing," and "coins" in the name) - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] --- -## DockerCoin in the microservices era +## Running ELK -- The dockercoins app is made of 5 services: +- We are going to use a Compose file describing the ELK stack. - - `rng` = web service generating random bytes +- The Compose file is in the container.training repository on GitHub. - - `hasher` = web service computing hash of POSTed data +```bash +$ git clone https://github.com/jpetazzo/container.training +$ cd container.training +$ cd elk +$ docker-compose up +``` - - `worker` = background process calling `rng` and `hasher` +- Let's have a look at the Compose file while it's deploying. - - `webui` = web interface to watch progress - - - `redis` = data store (holds a counter updated by `worker`) - -- These 5 services are visible in the application's Compose file, - [docker-compose.yml]( - https://github.com/jpetazzo/container.training/blob/master/dockercoins/docker-compose.yml) - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] --- -## How dockercoins works +## Our basic ELK deployment -- `worker` invokes web service `rng` to generate random bytes +- We are using images from the Docker Hub: `elasticsearch`, `logstash`, `kibana`. -- `worker` invokes web service `hasher` to hash these bytes +- We don't need to change the configuration of ElasticSearch. -- `worker` does this in an infinite loop +- We need to tell Kibana the address of ElasticSearch: -- every second, `worker` updates `redis` to indicate how many loops were done + - it is set with the `ELASTICSEARCH_URL` environment variable, -- `webui` queries `redis`, and computes and exposes "hashing speed" in our browser + - by default it is `localhost:9200`, we change it to `elasticsearch:9200`. -*(See diagram on next slide!)* +- We need to configure Logstash: -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] + - 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. + +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] +--- + +## 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 +``` + +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] +--- + +## Viewing the logs in ELK + +- Connect to the Kibana interface. + +- It is exposed on port 5601. + +- Browse http://X.X.X.X:5601. + +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] +--- + +## "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. + +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] +--- + +## 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]( +https://jpetazzo.github.io/2017/01/20/docker-logging-gelf/). + +.debug[[containers/Logging.md](""/tree/main/slides/containers/Logging.md)] --- class: pic -![Diagram showing the 5 containers of the applications](images/dockercoins-diagram.png) - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -## Service discovery in container-land - -How does each service find out the address of the other ones? - --- - -- We do not hard-code IP addresses in the code - -- We do not hard-code FQDNs in the code, either - -- We just connect to a service name, and container-magic does the rest - - (And by container-magic, we mean "a crafty, dynamic, embedded DNS server") - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -## Example in `worker/worker.py` - -```python -redis = Redis("`redis`") - - -def get_random_bytes(): - r = requests.get("http://`rng`/32") - return r.content - - -def hash_bytes(data): - r = requests.post("http://`hasher`/", - data=data, - headers={"Content-Type": "application/octet-stream"}) -``` - -(Full source code available [here]( -https://github.com/jpetazzo/container.training/blob/8279a3bce9398f7c1a53bdd95187c53eda4e6435/dockercoins/worker/worker.py#L17 -)) - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -class: extra-details - -## Links, naming, and service discovery - -- Containers can have network aliases (resolvable through DNS) - -- Compose file version 2+ makes each container reachable through its service name - -- Compose file version 1 required "links" sections to accomplish this - -- Network aliases are automatically namespaced - - - you can have multiple apps declaring and using a service named `database` - - - containers in the blue app will resolve `database` to the IP of the blue database - - - containers in the green app will resolve `database` to the IP of the green database - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -## Show me the code! - -- You can check the GitHub repository with all the materials of this workshop: -
https://github.com/jpetazzo/container.training - -- The application is in the [dockercoins]( - https://github.com/jpetazzo/container.training/tree/master/dockercoins) - subdirectory - -- The Compose file ([docker-compose.yml]( - https://github.com/jpetazzo/container.training/blob/master/dockercoins/docker-compose.yml)) - lists all 5 services - -- `redis` is using an official image from the Docker Hub - -- `hasher`, `rng`, `worker`, `webui` are each built from a Dockerfile - -- Each service's Dockerfile and source code is in its own directory - - (`hasher` is in the [hasher](https://github.com/jpetazzo/container.training/blob/master/dockercoins/hasher/) directory, - `rng` is in the [rng](https://github.com/jpetazzo/container.training/blob/master/dockercoins/rng/) - directory, etc.) - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -class: extra-details - -## Compose file format version - -*This is relevant only if you have used Compose before 2016...* - -- Compose 1.6 introduced support for a new Compose file format (aka "v2") - -- Services are no longer at the top level, but under a `services` section - -- There has to be a `version` key at the top level, with value `"2"` (as a string, not an integer) - -- Containers are placed on a dedicated network, making links unnecessary - -- There are other minor differences, but upgrade is easy and straightforward - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -## Our application at work - -- On the left-hand side, the "rainbow strip" shows the container names - -- On the right-hand side, we see the output of our containers - -- We can see the `worker` service making requests to `rng` and `hasher` - -- For `rng` and `hasher`, we see HTTP access logs - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -## Connecting to the web UI - -- "Logs are exciting and fun!" (No-one, ever) - -- The `webui` container exposes a web dashboard; let's view it - -.lab[ - -- With a web browser, connect to `node1` on port 8000 - -- Remember: the `nodeX` aliases are valid only on the nodes themselves - -- In your browser, you need to enter the IP address of your node - - - -] - -A drawing area should show up, and after a few seconds, a blue -graph will appear. - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -class: self-paced, extra-details - -## If the graph doesn't load - -If you just see a `Page not found` error, it might be because your -Docker Engine is running on a different machine. This can be the case if: - -- you are using the Docker Toolbox - -- you are using a VM (local or remote) created with Docker Machine - -- you are controlling a remote Docker Engine - -When you run DockerCoins in development mode, the web UI static files -are mapped to the container using a volume. Alas, volumes can only -work on a local environment, or when using Docker Desktop for Mac or Windows. - -How to fix this? - -Stop the app with `^C`, edit `dockercoins.yml`, comment out the `volumes` section, and try again. - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -class: extra-details - -## Why does the speed seem irregular? - -- It *looks like* the speed is approximately 4 hashes/second - -- Or more precisely: 4 hashes/second, with regular dips down to zero - -- Why? - --- - -class: extra-details - -- The app actually has a constant, steady speed: 3.33 hashes/second -
- (which corresponds to 1 hash every 0.3 seconds, for *reasons*) - -- Yes, and? - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -class: extra-details - -## The reason why this graph is *not awesome* - -- The worker doesn't update the counter after every loop, but up to once per second - -- The speed is computed by the browser, checking the counter about once per second - -- Between two consecutive updates, the counter will increase either by 4, or by 0 - -- The perceived speed will therefore be 4 - 4 - 4 - 0 - 4 - 4 - 0 etc. - -- What can we conclude from this? - --- - -class: extra-details - -- "I'm clearly incapable of writing good frontend code!" 😀 — Jérôme - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -## Stopping the application - -- If we interrupt Compose (with `^C`), it will politely ask the Docker Engine to stop the app - -- The Docker Engine will send a `TERM` signal to the containers - -- If the containers do not exit in a timely manner, the Engine sends a `KILL` signal - -.lab[ - -- Stop the application by hitting `^C` - - - -] - --- - -Some containers exit immediately, others take longer. - -The containers that do not handle `SIGTERM` end up being killed after a 10s timeout. If we are very impatient, we can hit `^C` a second time! - - -.debug[[shared/sampleapp.md](""/tree/main/slides/shared/sampleapp.md)] ---- - -class: pic - -.interstitial[![Image separating from the next part](https://gallant-turing-d0d520.netlify.com/containers/catene-de-conteneurs.jpg)] +.interstitial[![Image separating from the next part](https://gallant-turing-d0d520.netlify.com/containers/wall-of-containers.jpeg)] --- @@ -5826,7 +5227,7 @@ class: title Links and resources .nav[ -[Previous part](#toc-our-sample-application) +[Previous part](#toc-logging) | [Back to table of contents](#toc-part-5) | diff --git a/slides/intro-fd-k8s-deployments.yml.html b/slides/intro-fd-k8s-deployments.yml.html index d2f32d0..d2e215e 100644 --- a/slides/intro-fd-k8s-deployments.yml.html +++ b/slides/intro-fd-k8s-deployments.yml.html @@ -31,15 +31,13 @@ Introduction to Helm and friends
``` M slides/airgapped/Importing_Images.md M slides/intro-container-security.yml.html + M slides/intro-fd-docker.yml M slides/intro-fd-docker.yml.html M slides/intro-fd-k8s-deployments.yml.html - M slides/swarm-halfday.yml.html - M slides/swarm-selfpaced.yml.html - M slides/swarm-video.yml.html ``` -These slides have been built from commit: 65fec64 +These slides have been built from commit: 1e1b023 [shared/title.md](""/tree/main/slides/shared/title.md)] diff --git a/slides/intro-fd-k8s.yml.html b/slides/intro-fd-k8s.yml.html index ca869c9..9db0ad6 100644 --- a/slides/intro-fd-k8s.yml.html +++ b/slides/intro-fd-k8s.yml.html @@ -31,16 +31,14 @@ Introduction to Kubernetes
``` M slides/airgapped/Importing_Images.md M slides/intro-container-security.yml.html + M slides/intro-fd-docker.yml M slides/intro-fd-docker.yml.html M slides/intro-fd-k8s-deployments.yml.html M slides/intro-fd-k8s.yml.html - M slides/swarm-halfday.yml.html - M slides/swarm-selfpaced.yml.html - M slides/swarm-video.yml.html ``` -These slides have been built from commit: 65fec64 +These slides have been built from commit: 1e1b023 [shared/title.md](""/tree/main/slides/shared/title.md)] diff --git a/slides/intro-fullday.yml.html b/slides/intro-fullday.yml.html index f01feaf..4276e94 100644 --- a/slides/intro-fullday.yml.html +++ b/slides/intro-fullday.yml.html @@ -31,17 +31,15 @@ Introduction
to Containers
``` M slides/airgapped/Importing_Images.md M slides/intro-container-security.yml.html + M slides/intro-fd-docker.yml M slides/intro-fd-docker.yml.html M slides/intro-fd-k8s-deployments.yml.html M slides/intro-fd-k8s.yml.html M slides/intro-fullday.yml.html - M slides/swarm-halfday.yml.html - M slides/swarm-selfpaced.yml.html - M slides/swarm-video.yml.html ``` -These slides have been built from commit: 65fec64 +These slides have been built from commit: 1e1b023 [shared/title.md](""/tree/main/slides/shared/title.md)] diff --git a/slides/intro-selfpaced.yml.html b/slides/intro-selfpaced.yml.html index de9e834..7346925 100644 --- a/slides/intro-selfpaced.yml.html +++ b/slides/intro-selfpaced.yml.html @@ -31,18 +31,16 @@ Introduction
to Containers
``` M slides/airgapped/Importing_Images.md M slides/intro-container-security.yml.html + M slides/intro-fd-docker.yml M slides/intro-fd-docker.yml.html M slides/intro-fd-k8s-deployments.yml.html M slides/intro-fd-k8s.yml.html M slides/intro-fullday.yml.html M slides/intro-selfpaced.yml.html - M slides/swarm-halfday.yml.html - M slides/swarm-selfpaced.yml.html - M slides/swarm-video.yml.html ``` -These slides have been built from commit: 65fec64 +These slides have been built from commit: 1e1b023 [shared/title.md](""/tree/main/slides/shared/title.md)] diff --git a/slides/intro-triodos-1-day.yml.html b/slides/intro-triodos-1-day.yml.html index 34d050a..e69de29 100644 --- a/slides/intro-triodos-1-day.yml.html +++ b/slides/intro-triodos-1-day.yml.html @@ -1,12233 +0,0 @@ - - - - Triodos Introduction to Containers and orchestration with Kubernetes - - - - - - - - - - - - - - -