From 8decf1852f1ddd45ae7be6f44cdb6c0c63c600a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Petazzoni?= Date: Tue, 7 Nov 2017 19:43:42 -0800 Subject: [PATCH] Refactor build-tag-push We now have two clean classes: btp-manual and btp-auto Exclude one or the other depending on whether you want to show the full process of building and pushing images, or if you want to shortcut and use stack files directly. --- slides/swarm-fullday.yml | 7 +- slides/swarm-halfday.yml | 8 +- slides/swarm-selfpaced.yml | 6 + slides/swarm/btp-manual.md | 282 +++++++++++ slides/swarm/compose2swarm.md | 373 ++++++++++++++ slides/swarm/hostingregistry.md | 39 ++ slides/swarm/ourapponswarm.md | 864 +------------------------------- slides/swarm/pickregistry.md | 0 slides/swarm/swarmready.md | 64 +++ slides/swarm/testingregistry.md | 38 ++ 10 files changed, 816 insertions(+), 865 deletions(-) create mode 100644 slides/swarm/btp-manual.md create mode 100644 slides/swarm/compose2swarm.md create mode 100644 slides/swarm/hostingregistry.md create mode 100644 slides/swarm/pickregistry.md create mode 100644 slides/swarm/swarmready.md create mode 100644 slides/swarm/testingregistry.md diff --git a/slides/swarm-fullday.yml b/slides/swarm-fullday.yml index fccae24a..fde4f883 100644 --- a/slides/swarm-fullday.yml +++ b/slides/swarm-fullday.yml @@ -8,7 +8,7 @@ chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)" exclude: - self-paced - snap -- auto-btp +- btp-auto - benchmarking - elk-manual - prom-manual @@ -29,6 +29,11 @@ chapters: - swarm/morenodes.md - - swarm/firstservice.md - swarm/ourapponswarm.md + - swarm/hostingregistry.md + - swarm/testingregistry.md + - swarm/btp-manual.md + - swarm/swarmready.md + - swarm/compose2swarm.md - swarm/updatingservices.md #- swarm/rollingupdates.md - swarm/healthchecks.md diff --git a/slides/swarm-halfday.yml b/slides/swarm-halfday.yml index 84c8986b..f4693e1f 100644 --- a/slides/swarm-halfday.yml +++ b/slides/swarm-halfday.yml @@ -8,7 +8,7 @@ chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)" exclude: - self-paced - snap -- auto-btp +- btp-manual - benchmarking - elk-manual - prom-manual @@ -25,9 +25,15 @@ chapters: - common/declarative.md - swarm/swarmmode.md - swarm/creatingswarm.md + #- swarm/machine.md - swarm/morenodes.md - - swarm/firstservice.md - swarm/ourapponswarm.md + #- swarm/hostingregistry.md + #- swarm/testingregistry.md + #- swarm/btp-manual.md + #- swarm/swarmready.md + - swarm/compose2swarm.md - swarm/updatingservices.md #- swarm/rollingupdates.md #- swarm/healthchecks.md diff --git a/slides/swarm-selfpaced.yml b/slides/swarm-selfpaced.yml index da35f049..eafac53c 100644 --- a/slides/swarm-selfpaced.yml +++ b/slides/swarm-selfpaced.yml @@ -6,6 +6,7 @@ chat: "[Slack](https://dockercommunity.slack.com/messages/C7GKACWDV)" exclude: - in-person +- btp-auto chapters: - common/title.md @@ -29,6 +30,11 @@ chapters: - swarm/morenodes.md - - swarm/firstservice.md - swarm/ourapponswarm.md + - swarm/hostingregistry.md + - swarm/testingregistry.md + - swarm/btp-manual.md + - swarm/swarmready.md + - swarm/compose2swarm.md - | name: part-2 diff --git a/slides/swarm/btp-manual.md b/slides/swarm/btp-manual.md new file mode 100644 index 00000000..bdf011b4 --- /dev/null +++ b/slides/swarm/btp-manual.md @@ -0,0 +1,282 @@ +## Build, tag, and push our application container images + +- Compose has named our images `dockercoins_XXX` for each service + +- We need to retag them (to `127.0.0.1:5000/XXX:v1`) and push them + +.exercise[ + +- Set `REGISTRY` and `TAG` environment variables to use our local registry +- And run this little for loop: + ```bash + cd ~/container.training/dockercoins + REGISTRY=127.0.0.1:5000 TAG=v1 + for SERVICE in hasher rng webui worker; do + docker tag dockercoins_$SERVICE $REGISTRY/$SERVICE:$TAG + docker push $REGISTRY/$SERVICE + done + ``` + +] + +--- + +## Overlay networks + +- SwarmKit integrates with overlay networks + +- Networks are created with `docker network create` + +- Make sure to specify that you want an *overlay* network +
(otherwise you will get a local *bridge* network by default) + +.exercise[ + +- Create an overlay network for our application: + ```bash + docker network create --driver overlay dockercoins + ``` + +] + +--- + +## Viewing existing networks + +- Let's confirm that our network was created + +.exercise[ + +- List existing networks: + ```bash + docker network ls + ``` + +] + +--- + +## Can you spot the differences? + +The networks `dockercoins` and `ingress` are different from the other ones. + +Can you see how? + +-- + + +- They are using a different kind of ID, reflecting the fact that they + are SwarmKit objects instead of "classic" Docker Engine objects. + +- Their *scope* is `swarm` instead of `local`. + +- They are using the overlay driver. + +--- + +class: extra-details + +## Caveats + +.warning[In Docker 1.12, you cannot join an overlay network with `docker run --net ...`.] + +Starting with version 1.13, you can, if the network was created with the `--attachable` flag. + +*Why is that?* + +Placing a container on a network requires allocating an IP address for this container. + +The allocation must be done by a manager node (worker nodes cannot update Raft data). + +As a result, `docker run --net ...` requires collaboration with manager nodes. + +It alters the code path for `docker run`, so it is allowed only under strict circumstances. + +--- + +## Run the application + +- First, create the `redis` service; that one is using a Docker Hub image + +.exercise[ + +- Create the `redis` service: + ```bash + docker service create --network dockercoins --name redis redis + ``` + +] + +--- + +## Run the other services + +- Then, start the other services one by one + +- We will use the images pushed previously + +.exercise[ + +- Start the other services: + ```bash + REGISTRY=127.0.0.1:5000 + TAG=v1 + for SERVICE in hasher rng webui worker; do + docker service create --network dockercoins --detach=true \ + --name $SERVICE $REGISTRY/$SERVICE:$TAG + done + ``` + +] + +--- + +## Expose our application web UI + +- We need to connect to the `webui` service, but it is not publishing any port + +- Let's reconfigure it to publish a port + +.exercise[ + +- Update `webui` so that we can connect to it from outside: + ```bash + docker service update webui --publish-add 8000:80 --detach=false + ``` + +] + +Note: to "de-publish" a port, you would have to specify the container port. +
(i.e. in that case, `--publish-rm 80`) + +--- + +## What happens when we modify a service? + +- Let's find out what happened to our `webui` service + +.exercise[ + +- Look at the tasks and containers associated to `webui`: + ```bash + docker service ps webui + ``` +] + +-- + +The first version of the service (the one that was not exposed) has been shutdown. + +It has been replaced by the new version, with port 80 accessible from outside. + +(This will be discussed with more details in the section about stateful services.) + +--- + +## Connect to the web UI + +- The web UI is now available on port 8000, *on all the nodes of the cluster* + +.exercise[ + +- If you're using Play-With-Docker, just click on the `(8000)` badge + +- Otherwise, point your browser to any node, on port 8000 + +] + +--- + +## Scaling the application + +- We can change scaling parameters with `docker update` as well + +- We will do the equivalent of `docker-compose scale` + +.exercise[ + +- Bring up more workers: + ```bash + docker service update worker --replicas 10 --detach=false + ``` + +- Check the result in the web UI + +] + +You should see the performance peaking at 10 hashes/s (like before). + +--- + +# Global scheduling + +- We want to utilize as best as we can the entropy generators + on our nodes + +- We want to run exactly one `rng` instance per node + +- SwarmKit has a special scheduling mode for that, let's use it + +- We cannot enable/disable global scheduling on an existing service + +- We have to destroy and re-create the `rng` service + +--- + +## Scaling the `rng` service + +.exercise[ + +- Remove the existing `rng` service: + ```bash + docker service rm rng + ``` + +- Re-create the `rng` service with *global scheduling*: + ```bash + docker service create --name rng --network dockercoins --mode global \ + --detach=false $REGISTRY/rng:$TAG + ``` + +- Look at the result in the web UI + +] + +--- + +class: extra-details + +## Why do we have to re-create the service to enable global scheduling? + +- State reconciliation is handled by a *controller* + +- The controller knows how to "converge" a scaled service spec to another + +- It doesn't know how to "transform" a scaled service into a global one +
+ (or vice versa) + +- This might change in the future (after all, it was possible in 1.12 RC!) + +- As of Docker Engine 17.05, other parameters requiring to `rm`/`create` the service are: + + - service name + + - hostname + + - network + +--- + +## Removing everything + +- Before moving on, let's get a clean slate + +.exercise[ + +- Remove *all* the services: + ```bash + docker service ls -q | xargs docker service rm + ``` + +] diff --git a/slides/swarm/compose2swarm.md b/slides/swarm/compose2swarm.md new file mode 100644 index 00000000..c1a6cd00 --- /dev/null +++ b/slides/swarm/compose2swarm.md @@ -0,0 +1,373 @@ +class: btp-manual + +## Integration with Compose + +- We saw how to manually build, tag, and push images to a registry + +- But ... + +-- + +class: btp-manual + +*"I'm so glad that my deployment relies on ten nautic miles of Shell scripts"* + +*(No-one, ever)* + +-- + +class: btp-manual + +- Let's see how we can streamline this process! + +--- + +# Integration with Compose + +- Compose is great for local development + +- It can also be used to manage image lifecycle + + (i.e. build images and push them to a registry) + +- Compose files *v2* are great for local development + +- Compose files *v3* can also be used for production deployments! + +--- + +## Compose file version 3 + +(New in Docker Engine 1.13) + +- Almost identical to version 2 + +- Can be directly used by a Swarm cluster through `docker stack ...` commands + +- Introduces a `deploy` section to pass Swarm-specific parameters + +- Resource limits are moved to this `deploy` section + +- See [here](https://github.com/aanand/docker.github.io/blob/8524552f99e5b58452fcb1403e1c273385988b71/compose/compose-file.md#upgrading) for the complete list of changes + +- Supersedes *Distributed Application Bundles* + + (JSON payload describing an application; could be generated from a Compose file) + +--- + +## Our first stack + +We need a registry to move images around. + +Without a stack file, it would be deployed with the following command: + +```bash +docker service create --publish 5000:5000 registry:2 +``` + +Now, we are going to deploy it with the following stack file: + +```yaml +version: "3" + +services: + registry: + image: registry:2 + ports: + - "5000:5000" +``` + +--- + +## Checking our stack files + +- All the stack files that we will use are in the `stacks` directory + +.exercise[ + +- Go to the `stacks` directory: + ```bash + cd ~/container.training/stacks + ``` + +- Check `registry.yml`: + ```bash + cat registry.yml + ``` + +] + +--- + +## Deploying our first stack + +- All stack manipulation commands start with `docker stack` + +- Under the hood, they map to `docker service` commands + +- Stacks have a *name* (which also serves as a namespace) + +- Stacks are specified with the aforementioned Compose file format version 3 + +.exercise[ + +- Deploy our local registry: + ```bash + docker stack deploy registry --compose-file registry.yml + ``` + +] + +--- + +## Inspecting stacks + +- `docker stack ps` shows the detailed state of all services of a stack + +.exercise[ + +- Check that our registry is running correctly: + ```bash + docker stack ps registry + ``` + +- Confirm that we get the same output with the following command: + ```bash + docker service ps registry_registry + ``` + +] + +--- + +class: btp-manual + +## Specifics of stack deployment + +Our registry is not *exactly* identical to the one deployed with `docker service create`! + +- Each stack gets its own overlay network + +- Services of the task are connected to this network +
(unless specified differently in the Compose file) + +- Services get network aliases matching their name in the Compose file +
(just like when Compose brings up an app specified in a v2 file) + +- Services are explicitly named `_` + +- Services and tasks also get an internal label indicating which stack they belong to + +--- + +class: btp-auto + +## Testing our local registry + +- Connecting to port 5000 *on any node of the cluster* routes us to the registry + +- Therefore, we can use `localhost:5000` or `127.0.0.1:5000` as our registry + +.exercise[ + +- Issue the following API request to the registry: + ```bash + curl 127.0.0.1:5000/v2/_catalog + ``` + +] + +It should return: + +```json +{"repositories":[]} +``` + +If that doesn't work, retry a few times; perhaps the container is still starting. + +--- + +class: btp-auto + +## Pushing an image to our local registry + +- We can retag a small image, and push it to the registry + +.exercise[ + +- Make sure we have the busybox image, and retag it: + ```bash + docker pull busybox + docker tag busybox 127.0.0.1:5000/busybox + ``` + +- Push it: + ```bash + docker push 127.0.0.1:5000/busybox + ``` + +] + +--- + +class: btp-auto + +## Checking what's on our local registry + +- The registry API has endpoints to query what's there + +.exercise[ + +- Ensure that our busybox image is now in the local registry: + ```bash + curl http://127.0.0.1:5000/v2/_catalog + ``` + +] + +The curl command should now output: +```json +"repositories":["busybox"]} +``` + +--- + +## Building and pushing stack services + +- When using Compose file version 2 and above, you can specify *both* `build` and `image` + +- When both keys are present: + + - Compose does "business as usual" (uses `build`) + + - but the resulting image is named as indicated by the `image` key +
+ (instead of `_:latest`) + + - it can be pushed to a registry with `docker-compose push` + +- Example: + + ```yaml + webfront: + build: www + image: myregistry.company.net:5000/webfront + ``` + +--- + +## Using Compose to build and push images + +.exercise[ + +- Try it: + ```bash + docker-compose -f dockercoins.yml build + docker-compose -f dockercoins.yml push + ``` + +] + +Let's have a look at the `dockercoins.yml` file while this is building and pushing. + +--- + +```yaml +version: "3" + +services: + rng: + build: dockercoins/rng + image: ${REGISTRY-127.0.0.1:5000}/rng:${TAG-latest} + deploy: + mode: global + ... + redis: + image: redis + ... + worker: + build: dockercoins/worker + image: ${REGISTRY-127.0.0.1:5000}/worker:${TAG-latest} + ... + deploy: + replicas: 10 +``` + +--- + +## Deploying the application + +- Now that the images are on the registry, we can deploy our application stack + +.exercise[ + +- Create the application stack: + ```bash + docker stack deploy dockercoins --compose-file dockercoins.yml + ``` + +] + +We can now connect to any of our nodes on port 8000, and we will see the familiar hashing speed graph. + +--- + +## Maintaining multiple environments + +There are many ways to handle variations between environments. + +- Compose loads `docker-compose.yml` and (if it exists) `docker-compose.override.yml` + +- Compose can load alternate file(s) by setting the `-f` flag or the `COMPOSE_FILE` environment variable + +- Compose files can *extend* other Compose files, selectively including services: + + ```yaml + web: + extends: + file: common-services.yml + service: webapp + ``` + +See [this documentation page](https://docs.docker.com/compose/extends/) for more details about these techniques. + +--- + +class: extra-details + +## Good to know ... + +- Compose file version 3 adds the `deploy` section + +- Further versions (3.1, ...) add more features (secrets, configs ...) + +- You can re-run `docker stack deploy` to update a stack + +- You can make manual changes with `docker service update` ... + +- ... But they will be wiped out each time you `docker stack deploy` + + (That's the intended behavior, when one thinks about it!) + +- `extends` doesn't work with `docker stack deploy` + + (But you can use `docker-compose config` to "flatten" your configuration) + +--- + +## Summary + +- We've seen how to set up a Swarm + +- We've used it to host our own registry + +- We've built our app container images + +- We've used the registry to host those images + +- We've deployed and scaled our application + +- We've seen how to use Compose to streamline deployments + +- Awesome job, team! diff --git a/slides/swarm/hostingregistry.md b/slides/swarm/hostingregistry.md new file mode 100644 index 00000000..e3675306 --- /dev/null +++ b/slides/swarm/hostingregistry.md @@ -0,0 +1,39 @@ +# Hosting our own registry + +- We need to run a `registry:2` container +
(make sure you specify tag `:2` to run the new version!) + +- It will store images and layers to the local filesystem +
(but you can add a config file to use S3, Swift, etc.) + +- Docker *requires* TLS when communicating with the registry + + - unless for registries on `127.0.0.0/8` (i.e. `localhost`) + + - or with the Engine flag `--insecure-registry` + + + +- Our strategy: publish the registry container on port 5000, +
so that it's available through `127.0.0.1:5000` on each node + +--- + +## Deploying the registry + +- We will create a single-instance service, publishing its port + on the whole cluster + +.exercise[ + +- Create the registry service: + ```bash + docker service create --name registry --publish 5000:5000 registry:2 + ``` + +- Now try the following command; it should return `{"repositories":[]}`: + ```bash + curl 127.0.0.1:5000/v2/_catalog + ``` + +] diff --git a/slides/swarm/ourapponswarm.md b/slides/swarm/ourapponswarm.md index a78ea5d1..11ffd06f 100644 --- a/slides/swarm/ourapponswarm.md +++ b/slides/swarm/ourapponswarm.md @@ -1,10 +1,4 @@ -class: title - -Our app on Swarm - ---- - -## What's on the menu? +# Our app on Swarm In this part, we will: @@ -95,12 +89,6 @@ class: extra-details *If we wanted to use the Docker Hub...* - - - We would log into the Docker Hub: ```bash docker login @@ -109,12 +97,6 @@ class: extra-details - And in the following slides, we would use our Docker Hub login (e.g. `jpetazzo`) instead of the registry address (i.e. `127.0.0.1:5000`) - - --- class: extra-details @@ -133,847 +115,3 @@ class: extra-details - Use `dtraddress:port/user` instead of the registry address *This is out of the scope of this workshop!* - ---- - -## Using the open source registry - -- We need to run a `registry:2` container -
(make sure you specify tag `:2` to run the new version!) - -- It will store images and layers to the local filesystem -
(but you can add a config file to use S3, Swift, etc.) - -- Docker *requires* TLS when communicating with the registry - - - unless for registries on `127.0.0.0/8` (i.e. `localhost`) - - - or with the Engine flag `--insecure-registry` - - - -- Our strategy: publish the registry container on port 5000, -
so that it's available through `127.0.0.1:5000` on each node - ---- - -class: manual-btp - -# Deploying a local registry - -- We will create a single-instance service, publishing its port - on the whole cluster - -.exercise[ - -- Create the registry service: - ```bash - docker service create --name registry --publish 5000:5000 registry:2 - ``` - -- Now try the following command; it should return `{"repositories":[]}`: - ```bash - curl 127.0.0.1:5000/v2/_catalog - ``` - -] - -(If that doesn't work, wait a few seconds and try again.) - ---- - -class: manual-btp - -## Testing our local registry - -- We can retag a small image, and push it to the registry - -.exercise[ - -- Make sure we have the busybox image, and retag it: - ```bash - docker pull busybox - docker tag busybox 127.0.0.1:5000/busybox - ``` - -- Push it: - ```bash - docker push 127.0.0.1:5000/busybox - ``` - -] - ---- - -class: manual-btp - -## Checking what's on our local registry - -- The registry API has endpoints to query what's there - -.exercise[ - -- Ensure that our busybox image is now in the local registry: - ```bash - curl http://127.0.0.1:5000/v2/_catalog - ``` - -] - -The curl command should now output: -```json -{"repositories":["busybox"]} -``` - ---- - -class: manual-btp - -## Build, tag, and push our application container images - -- Compose has named our images `dockercoins_XXX` for each service - -- We need to retag them (to `127.0.0.1:5000/XXX:v1`) and push them - -.exercise[ - -- Set `REGISTRY` and `TAG` environment variables to use our local registry -- And run this little for loop: - ```bash - cd ~/container.training/dockercoins - REGISTRY=127.0.0.1:5000 TAG=v1 - for SERVICE in hasher rng webui worker; do - docker tag dockercoins_$SERVICE $REGISTRY/$SERVICE:$TAG - docker push $REGISTRY/$SERVICE - done - ``` - -] - ---- - -class: manual-btp - -# Overlay networks - -- SwarmKit integrates with overlay networks - -- Networks are created with `docker network create` - -- Make sure to specify that you want an *overlay* network -
(otherwise you will get a local *bridge* network by default) - -.exercise[ - -- Create an overlay network for our application: - ```bash - docker network create --driver overlay dockercoins - ``` - -] - ---- - -class: manual-btp - -## Viewing existing networks - -- Let's confirm that our network was created - -.exercise[ - -- List existing networks: - ```bash - docker network ls - ``` - -] - ---- - -class: manual-btp - -## Can you spot the differences? - -The networks `dockercoins` and `ingress` are different from the other ones. - -Can you see how? - --- - -class: manual-btp - -- They are using a different kind of ID, reflecting the fact that they - are SwarmKit objects instead of "classic" Docker Engine objects. - -- Their *scope* is `swarm` instead of `local`. - -- They are using the overlay driver. - ---- - -class: manual-btp, extra-details - -## Caveats - -.warning[In Docker 1.12, you cannot join an overlay network with `docker run --net ...`.] - -Starting with version 1.13, you can, if the network was created with the `--attachable` flag. - -*Why is that?* - -Placing a container on a network requires allocating an IP address for this container. - -The allocation must be done by a manager node (worker nodes cannot update Raft data). - -As a result, `docker run --net ...` requires collaboration with manager nodes. - -It alters the code path for `docker run`, so it is allowed only under strict circumstances. - ---- - -class: manual-btp - -## Run the application - -- First, create the `redis` service; that one is using a Docker Hub image - -.exercise[ - -- Create the `redis` service: - ```bash - docker service create --network dockercoins --name redis redis - ``` - -] - ---- - -class: manual-btp - -## Run the other services - -- Then, start the other services one by one - -- We will use the images pushed previously - -.exercise[ - -- Start the other services: - ```bash - REGISTRY=127.0.0.1:5000 - TAG=v1 - for SERVICE in hasher rng webui worker; do - docker service create --network dockercoins --detach=true \ - --name $SERVICE $REGISTRY/$SERVICE:$TAG - done - ``` - -] - -??? - -## Wait for our application to be up - -- We will see later a way to watch progress for all the tasks of the cluster - -- But for now, a scrappy Shell loop will do the trick - -.exercise[ - -- Repeatedly display the status of all our services: - ```bash - watch "docker service ls -q | xargs -n1 docker service ps" - ``` - -- Stop it once everything is running - -] - ---- - -class: manual-btp - -## Expose our application web UI - -- We need to connect to the `webui` service, but it is not publishing any port - -- Let's reconfigure it to publish a port - -.exercise[ - -- Update `webui` so that we can connect to it from outside: - ```bash - docker service update webui --publish-add 8000:80 --detach=false - ``` - -] - -Note: to "de-publish" a port, you would have to specify the container port. -
(i.e. in that case, `--publish-rm 80`) - ---- - -class: manual-btp - -## What happens when we modify a service? - -- Let's find out what happened to our `webui` service - -.exercise[ - -- Look at the tasks and containers associated to `webui`: - ```bash - docker service ps webui - ``` -] - --- - -class: manual-btp - -The first version of the service (the one that was not exposed) has been shutdown. - -It has been replaced by the new version, with port 80 accessible from outside. - -(This will be discussed with more details in the section about stateful services.) - ---- - -class: manual-btp - -## Connect to the web UI - -- The web UI is now available on port 8000, *on all the nodes of the cluster* - -.exercise[ - -- If you're using Play-With-Docker, just click on the `(8000)` badge - -- Otherwise, point your browser to any node, on port 8000 - -] - ---- - -## Scaling the application - -- We can change scaling parameters with `docker update` as well - -- We will do the equivalent of `docker-compose scale` - -.exercise[ - -- Bring up more workers: - ```bash - docker service update worker --replicas 10 --detach=false - ``` - -- Check the result in the web UI - -] - -You should see the performance peaking at 10 hashes/s (like before). - ---- - -class: manual-btp - -# Global scheduling - -- We want to utilize as best as we can the entropy generators - on our nodes - -- We want to run exactly one `rng` instance per node - -- SwarmKit has a special scheduling mode for that, let's use it - -- We cannot enable/disable global scheduling on an existing service - -- We have to destroy and re-create the `rng` service - ---- - -class: manual-btp - -## Scaling the `rng` service - -.exercise[ - -- Remove the existing `rng` service: - ```bash - docker service rm rng - ``` - -- Re-create the `rng` service with *global scheduling*: - ```bash - docker service create --name rng --network dockercoins --mode global \ - --detach=false $REGISTRY/rng:$TAG - ``` - -- Look at the result in the web UI - -] - ---- - -class: extra-details, manual-btp - -## Why do we have to re-create the service to enable global scheduling? - -- Enabling it dynamically would make rolling updates semantics very complex - -- This might change in the future (after all, it was possible in 1.12 RC!) - -- As of Docker Engine 17.05, other parameters requiring to `rm`/`create` the service are: - - - service name - - - hostname - - - network - ---- - -class: swarm-ready - -## How did we make our app "Swarm-ready"? - -This app was written in June 2015. (One year before Swarm mode was released.) - -What did we change to make it compatible with Swarm mode? - --- - -.exercise[ - -- Go to the app directory: - ```bash - cd ~/container.training/dockercoins - ``` - -- See modifications in the code: - ```bash - git log -p --since "4-JUL-2015" -- . ':!*.yml*' ':!*.html' - ``` - - - - -] - ---- - -class: swarm-ready - -## What did we change in our app since its inception? - -- Compose files - -- HTML file (it contains an embedded contextual tweet) - -- Dockerfiles (to switch to smaller images) - -- That's it! - --- - -class: swarm-ready - -*We didn't change a single line of code in this app since it was written.* - --- - -class: swarm-ready - -*The images that were [built in June 2015]( -https://hub.docker.com/r/jpetazzo/dockercoins_worker/tags/) -(when the app was written) can still run today ... -
... in Swarm mode (distributed across a cluster, with load balancing) ... -
... without any modification.* - ---- - -class: swarm-ready - -## How did we design our app in the first place? - -- [Twelve-Factor App](https://12factor.net/) principles - -- Service discovery using DNS names - - - Initially implemented as "links" - - - Then "ambassadors" - - - And now "services" - -- Existing apps might require more changes! - ---- - -class: manual-btp - -# Integration with Compose - -- 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) - ---- - -## Compose file version 3 - -(New in Docker Engine 1.13) - -- Almost identical to version 2 - -- Can be directly used by a Swarm cluster through `docker stack ...` commands - -- Introduces a `deploy` section to pass Swarm-specific parameters - -- Resource limits are moved to this `deploy` section - -- See [here](https://github.com/aanand/docker.github.io/blob/8524552f99e5b58452fcb1403e1c273385988b71/compose/compose-file.md#upgrading) for the complete list of changes - -- Supersedes *Distributed Application Bundles* - - (JSON payload describing an application; could be generated from a Compose file) - ---- - -class: manual-btp - -## Removing everything - -- Before deploying using "stacks," let's get a clean slate - -.exercise[ - -- Remove *all* the services: - ```bash - docker service ls -q | xargs docker service rm - ``` - -] - ---- - -## Our first stack - -We need a registry to move images around. - -Without a stack file, it would be deployed with the following command: - -```bash -docker service create --publish 5000:5000 registry:2 -``` - -Now, we are going to deploy it with the following stack file: - -```yaml -version: "3" - -services: - registry: - image: registry:2 - ports: - - "5000:5000" -``` - ---- - -## Checking our stack files - -- All the stack files that we will use are in the `stacks` directory - -.exercise[ - -- Go to the `stacks` directory: - ```bash - cd ~/container.training/stacks - ``` - -- Check `registry.yml`: - ```bash - cat registry.yml - ``` - -] - ---- - -## Deploying our first stack - -- All stack manipulation commands start with `docker stack` - -- Under the hood, they map to `docker service` commands - -- Stacks have a *name* (which also serves as a namespace) - -- Stacks are specified with the aforementioned Compose file format version 3 - -.exercise[ - -- Deploy our local registry: - ```bash - docker stack deploy registry --compose-file registry.yml - ``` - -] - ---- - -## Inspecting stacks - -- `docker stack ps` shows the detailed state of all services of a stack - -.exercise[ - -- Check that our registry is running correctly: - ```bash - docker stack ps registry - ``` - -- Confirm that we get the same output with the following command: - ```bash - docker service ps registry_registry - ``` - -] - ---- - -class: manual-btp - -## Specifics of stack deployment - -Our registry is not *exactly* identical to the one deployed with `docker service create`! - -- Each stack gets its own overlay network - -- Services of the task are connected to this network -
(unless specified differently in the Compose file) - -- Services get network aliases matching their name in the Compose file -
(just like when Compose brings up an app specified in a v2 file) - -- Services are explicitly named `_` - -- Services and tasks also get an internal label indicating which stack they belong to - ---- - -class: auto-btp - -## Testing our local registry - -- Connecting to port 5000 *on any node of the cluster* routes us to the registry - -- Therefore, we can use `localhost:5000` or `127.0.0.1:5000` as our registry - -.exercise[ - -- Issue the following API request to the registry: - ```bash - curl 127.0.0.1:5000/v2/_catalog - ``` - -] - -It should return: - -```json -{"repositories":[]} -``` - -If that doesn't work, retry a few times; perhaps the container is still starting. - ---- - -class: auto-btp - -## Pushing an image to our local registry - -- We can retag a small image, and push it to the registry - -.exercise[ - -- Make sure we have the busybox image, and retag it: - ```bash - docker pull busybox - docker tag busybox 127.0.0.1:5000/busybox - ``` - -- Push it: - ```bash - docker push 127.0.0.1:5000/busybox - ``` - -] - ---- - -class: auto-btp - -## Checking what's on our local registry - -- The registry API has endpoints to query what's there - -.exercise[ - -- Ensure that our busybox image is now in the local registry: - ```bash - curl http://127.0.0.1:5000/v2/_catalog - ``` - -] - -The curl command should now output: -```json -"repositories":["busybox"]} -``` - ---- - -## Building and pushing stack services - -- When using Compose file version 2 and above, you can specify *both* `build` and `image` - -- When both keys are present: - - - Compose does "business as usual" (uses `build`) - - - but the resulting image is named as indicated by the `image` key -
- (instead of `_:latest`) - - - it can be pushed to a registry with `docker-compose push` - -- Example: - - ```yaml - webfront: - build: www - image: myregistry.company.net:5000/webfront - ``` - ---- - -## Using Compose to build and push images - -.exercise[ - -- Try it: - ```bash - docker-compose -f dockercoins.yml build - docker-compose -f dockercoins.yml push - ``` - -] - -Let's have a look at the `dockercoins.yml` file while this is building and pushing. - ---- - -```yaml -version: "3" - -services: - rng: - build: dockercoins/rng - image: ${REGISTRY-127.0.0.1:5000}/rng:${TAG-latest} - deploy: - mode: global - ... - redis: - image: redis - ... - worker: - build: dockercoins/worker - image: ${REGISTRY-127.0.0.1:5000}/worker:${TAG-latest} - ... - deploy: - replicas: 10 -``` - ---- - -## Deploying the application - -- Now that the images are on the registry, we can deploy our application stack - -.exercise[ - -- Create the application stack: - ```bash - docker stack deploy dockercoins --compose-file dockercoins.yml - ``` - -] - -We can now connect to any of our nodes on port 8000, and we will see the familiar hashing speed graph. - ---- - -## Maintaining multiple environments - -There are many ways to handle variations between environments. - -- Compose loads `docker-compose.yml` and (if it exists) `docker-compose.override.yml` - -- Compose can load alternate file(s) by setting the `-f` flag or the `COMPOSE_FILE` environment variable - -- Compose files can *extend* other Compose files, selectively including services: - - ```yaml - web: - extends: - file: common-services.yml - service: webapp - ``` - -See [this documentation page](https://docs.docker.com/compose/extends/) for more details about these techniques. - - ---- - -class: extra-details - -## Good to know ... - -- Compose file version 3 adds the `deploy` section - -- Further versions (3.1, ...) add more features (secrets, configs ...) - -- You can re-run `docker stack deploy` to update a stack - -- You can make manual changes with `docker service update` ... - -- ... But they will be wiped out each time you `docker stack deploy` - - (That's the intended behavior, when one thinks about it!) - -- `extends` doesn't work with `docker stack deploy` - - (But you can use `docker-compose config` to "flatten" your configuration) - ---- - -## Summary - -- We've seen how to set up a Swarm - -- We've used it to host our own registry - -- We've built our app container images - -- We've used the registry to host those images - -- We've deployed and scaled our application - -- We've seen how to use Compose to streamline deployments - -- Awesome job, team! diff --git a/slides/swarm/pickregistry.md b/slides/swarm/pickregistry.md new file mode 100644 index 00000000..e69de29b diff --git a/slides/swarm/swarmready.md b/slides/swarm/swarmready.md new file mode 100644 index 00000000..a0fff9dd --- /dev/null +++ b/slides/swarm/swarmready.md @@ -0,0 +1,64 @@ +## How did we make our app "Swarm-ready"? + +This app was written in June 2015. (One year before Swarm mode was released.) + +What did we change to make it compatible with Swarm mode? + +-- + +.exercise[ + +- Go to the app directory: + ```bash + cd ~/container.training/dockercoins + ``` + +- See modifications in the code: + ```bash + git log -p --since "4-JUL-2015" -- . ':!*.yml*' ':!*.html' + ``` + + + + +] + +--- + +## What did we change in our app since its inception? + +- Compose files + +- HTML file (it contains an embedded contextual tweet) + +- Dockerfiles (to switch to smaller images) + +- That's it! + +-- + +*We didn't change a single line of code in this app since it was written.* + +-- + +*The images that were [built in June 2015]( +https://hub.docker.com/r/jpetazzo/dockercoins_worker/tags/) +(when the app was written) can still run today ... +
... in Swarm mode (distributed across a cluster, with load balancing) ... +
... without any modification.* + +--- + +## How did we design our app in the first place? + +- [Twelve-Factor App](https://12factor.net/) principles + +- Service discovery using DNS names + + - Initially implemented as "links" + + - Then "ambassadors" + + - And now "services" + +- Existing apps might require more changes! diff --git a/slides/swarm/testingregistry.md b/slides/swarm/testingregistry.md new file mode 100644 index 00000000..393d6965 --- /dev/null +++ b/slides/swarm/testingregistry.md @@ -0,0 +1,38 @@ +## Testing our local registry + +- We can retag a small image, and push it to the registry + +.exercise[ + +- Make sure we have the busybox image, and retag it: + ```bash + docker pull busybox + docker tag busybox 127.0.0.1:5000/busybox + ``` + +- Push it: + ```bash + docker push 127.0.0.1:5000/busybox + ``` + +] + +--- + +## Checking what's on our local registry + +- The registry API has endpoints to query what's there + +.exercise[ + +- Ensure that our busybox image is now in the local registry: + ```bash + curl http://127.0.0.1:5000/v2/_catalog + ``` + +] + +The curl command should now output: +```json +{"repositories":["busybox"]} +```