diff --git a/www/htdocs/index.html b/www/htdocs/index.html
index 27bc523c..30f54b0d 100644
--- a/www/htdocs/index.html
+++ b/www/htdocs/index.html
@@ -1640,11 +1640,11 @@ Moreover, it would significantly alter the code path for `docker run`, even in c
## Run the application
-- First, start the redis service; that one is using a Docker Hub image
+- First, create the `redis` service; that one is using a Docker Hub image
.exercise[
-- Create the redis service:
+- Create the `redis` service:
```bash
docker service create --network dockercoins --name redis redis
```
@@ -2690,13 +2690,13 @@ After ~15 seconds, you should see the log messages in Kibana.
## Building a stateful service experiment
-- We will use a redis service
+- We will use Redis for this example
- We will expose it on port 10000 to access it easily
.exercise[
-- Start the redis service:
+- Start the Redis service:
```bash
docker service create --name stateful -p 10000:6379 redis
```
@@ -2710,7 +2710,7 @@ After ~15 seconds, you should see the log messages in Kibana.
---
-## Accessing our redis service easily
+## Accessing our Redis service easily
- Typing that whole command is going to be tedious
@@ -2730,7 +2730,7 @@ After ~15 seconds, you should see the log messages in Kibana.
---
-## Basic redis commands
+## Basic Redis commands
.exercise[
@@ -2832,9 +2832,9 @@ After ~15 seconds, you should see the log messages in Kibana.
---
-## Making sure that redis correctly persists data
+## Making sure that Redis correctly persists data
-- Before going further, we need to make sure that redis correctly saves to disk
+- Before going further, we need to make sure that Redis correctly saves to disk
.exercise[
@@ -2857,7 +2857,7 @@ After ~15 seconds, you should see the log messages in Kibana.
---
-## Instructing redis to save data on restarts
+## Instructing Redis to save data on restarts
- The default configuration that comes with the `redis` image doesn't save on shutdown
@@ -2867,7 +2867,7 @@ After ~15 seconds, you should see the log messages in Kibana.
.exercise[
-- Add `--appendonly yes` to redis starting flags:
+- Add `--appendonly yes` to Redis starting flags:
```bash
docker service update stateful --args "--appendonly yes"
```
@@ -2876,7 +2876,7 @@ After ~15 seconds, you should see the log messages in Kibana.
Note: we can achieve the same result by enabling RDB snapshots instead.
-See http://redis.io/topics/persistence for more details about redis persistence.
+See http://redis.io/topics/persistence for more details about Redis persistence.
---
@@ -3121,6 +3121,168 @@ You can also directly use the file `docker-compose.yml-images`.
# Docker Application Bundles
+- The previous section showed us how to streamline image build and push
+
+- We will now see how to streamline service creation
+
+ (i.e. get rid of the `for SERVICE in ...; do docker service create ...` part)
+
+.warning[This is experimental and subject to change!]
+
+---
+
+## What is a Docker Application Bundle?
+
+- Conceptually similar to a Compose file, but for Swarm clusters
+
+- A Docker Application Bundle is a JSON payload describing the services
+
+- It's typically stored as `.dab`
+
+- It's JSON because you're not supposed to edit it manually
+
+- It can be generated by Compose, and consumed by Docker (experimental branch)
+
+- In addition to image names, it contains their exact SHA256
+
+---
+
+## Generating a DAB
+
+- This is done with the Compose `bundle` command
+
+.exercise[
+
+- Create the DAB for the DockerCoins application:
+ ```bash
+ docker-compose bundle
+ ```
+
+- Inspect the resulting file:
+ ```bash
+ cat dockercoins.dab
+ ```
+
+]
+
+---
+
+## Using a DAB
+
+- This is done with `docker stack deploy `
+
+.exercise[
+
+- Try to deploy the DAB:
+ ```bash
+ docker stack deploy dockercoins
+ ```
+
+]
+
+--
+
+Oh, right, we need the *experimental* build of Docker!
+
+---
+
+## Installing Docker experimental CLI
+
+- We don't need to upgrade our Docker Engines; we just need an upgraded CLI
+
+- We will download and extract it in a separate directory (to keep the original intact)
+
+.exercise[
+
+- Download and unpack the latest experimental build of Docker:
+ ```bash
+ curl -sSL \
+ https://experimental.docker.com/builds/$(uname -s)/$(uname -m)/docker-latest.tgz \
+ | tar -C ~ -zxf-
+ ```
+
+]
+
+---
+
+## Using Docker experimental CLI
+
+- Just invoke `~/docker/docker` instead of `docker`
+
+.exercise[
+
+- Deploy our app using the DAB file:
+ ```bash
+ ~/docker/docker stack deploy dockercoins
+ ```
+
+- Check the stack deployment:
+ ```bash
+ ~/docker/docker stack ps dockercoins
+ ```
+
+]
+
+---
+
+## Look at the newly deployed stack
+
+.exercise[
+
+- Let's find out which port was allocated for `webui`:
+ ```bash
+ docker service inspect dockercoins_webui \
+ --format '{{ (index .Endpoint.Ports 0).PublishedPort }}'
+ ```
+
+- Point your navigator to any node on that port
+
+]
+
+Note: we can use the "normal" CLI for everything else.
+
+We only need it for `docker stack`.
+
+---
+
+## Clean up
+
+- Unsurprisingly, there is a `docker stack rm` command
+
+.exercise[
+
+- Clean up the stack we just deployed:
+ ```bash
+ ~/docker/docker stack rm dockercoins
+ ```
+
+]
+
+---
+
+## Scoping
+
+- All resources (service names, network names...) are prefixed with the stack name
+
+- This allows us to stage up multiple instances side by side
+
+ (Just like before with Compose's project name parameter)
+
+---
+
+## Some features are not fully supported yet
+
+- Global scheduling
+
+- Scaling
+
+- Fixed port numbers
+
+- Logging options
+
+- ... and much more
+
+You can specify *most* of them in the DAB itself, but Compose can't generate it (yet).
---
@@ -3150,6 +3312,10 @@ More resources on this topic:
- In Swarm mode, bind-mounting the control socket gives you access to the whole cluster
+- You can tell Docker to place a given service on a manager node, using constraints:
+ ```bash
+ docker service create --name autoscaler --constraint node.role==manager ...
+ ```
---