From 10d019c15ecef107b8d8ee5e64a06ea6ec56d1b7 Mon Sep 17 00:00:00 2001 From: Allythy Date: Tue, 10 Aug 2021 14:36:24 -0300 Subject: [PATCH] Migration from jekyll to Honkit - Initializing the Honkit base structure - Add files that will be ignored by gitignore --- .gitignore | 349 ++- 404.html | 29 - CNAME | 1 - Gemfile | 30 - Gemfile.lock | 81 - README.md | 180 -- SUMMARY.md | 25 + _config.yml | 20 - _includes/navbar.html | 23 - _includes/sidebar.html | 19 - _layouts/default.html | 22 - assets/css/bootswatch-superhero.min.css | 12 - assets/css/highlight.css | 70 - assets/css/main.scss | 59 - capitulos/CHAPTER_00.md | 40 - capitulos/CHAPTER_01.md | 97 - capitulos/CHAPTER_02.md | 406 --- capitulos/CHAPTER_03.md | 151 -- capitulos/CHAPTER_04.md | 473 ---- capitulos/CHAPTER_05.md | 184 -- capitulos/CHAPTER_06.md | 73 - capitulos/CHAPTER_07.md | 377 --- capitulos/CHAPTER_08.md | 578 ----- capitulos/CHAPTER_09.md | 406 --- capitulos/CHAPTER_10.md | 213 -- capitulos/CHAPTER_11.md | 185 -- capitulos/CHAPTER_12.md | 344 --- capitulos/CHAPTER_13.md | 607 ----- capitulos/CHAPTER_14.md | 244 -- capitulos/CHAPTER_15.md | 859 ------- .../CHAPTER_00.md => chapters/chapter_00.md | 0 .../CHAPTER_01.md => chapters/chapter_01.md | 0 .../CHAPTER_02.md => chapters/chapter_02.md | 0 .../CHAPTER_03.md => chapters/chapter_03.md | 0 .../CHAPTER_04.md => chapters/chapter_04.md | 0 .../CHAPTER_05.md => chapters/chapter_05.md | 0 .../CHAPTER_06.md => chapters/chapter_06.md | 0 .../CHAPTER_07.md => chapters/chapter_07.md | 0 .../CHAPTER_08.md => chapters/chapter_08.md | 0 .../CHAPTER_09.md => chapters/chapter_09.md | 0 .../CHAPTER_10.md => chapters/chapter_10.md | 0 .../CHAPTER_11.md => chapters/chapter_11.md | 0 .../CHAPTER_12.md => chapters/chapter_12.md | 0 .../CHAPTER_13.md => chapters/chapter_13.md | 0 .../CHAPTER_14.md => chapters/chapter_14.md | 0 .../CHAPTER_15.md => chapters/chapter_15.md | 0 index.markdown | 70 - package.json | 5 + yarn.lock | 2235 +++++++++++++++++ 49 files changed, 2609 insertions(+), 5858 deletions(-) delete mode 100644 404.html delete mode 100644 CNAME delete mode 100644 Gemfile delete mode 100644 Gemfile.lock create mode 100644 SUMMARY.md delete mode 100644 _config.yml delete mode 100644 _includes/navbar.html delete mode 100644 _includes/sidebar.html delete mode 100644 _layouts/default.html delete mode 100644 assets/css/bootswatch-superhero.min.css delete mode 100644 assets/css/highlight.css delete mode 100644 assets/css/main.scss delete mode 100644 capitulos/CHAPTER_00.md delete mode 100644 capitulos/CHAPTER_01.md delete mode 100644 capitulos/CHAPTER_02.md delete mode 100644 capitulos/CHAPTER_03.md delete mode 100644 capitulos/CHAPTER_04.md delete mode 100644 capitulos/CHAPTER_05.md delete mode 100644 capitulos/CHAPTER_06.md delete mode 100644 capitulos/CHAPTER_07.md delete mode 100644 capitulos/CHAPTER_08.md delete mode 100644 capitulos/CHAPTER_09.md delete mode 100644 capitulos/CHAPTER_10.md delete mode 100644 capitulos/CHAPTER_11.md delete mode 100644 capitulos/CHAPTER_12.md delete mode 100644 capitulos/CHAPTER_13.md delete mode 100644 capitulos/CHAPTER_14.md delete mode 100644 capitulos/CHAPTER_15.md rename _chapters/CHAPTER_00.md => chapters/chapter_00.md (100%) rename _chapters/CHAPTER_01.md => chapters/chapter_01.md (100%) rename _chapters/CHAPTER_02.md => chapters/chapter_02.md (100%) rename _chapters/CHAPTER_03.md => chapters/chapter_03.md (100%) rename _chapters/CHAPTER_04.md => chapters/chapter_04.md (100%) rename _chapters/CHAPTER_05.md => chapters/chapter_05.md (100%) rename _chapters/CHAPTER_06.md => chapters/chapter_06.md (100%) rename _chapters/CHAPTER_07.md => chapters/chapter_07.md (100%) rename _chapters/CHAPTER_08.md => chapters/chapter_08.md (100%) rename _chapters/CHAPTER_09.md => chapters/chapter_09.md (100%) rename _chapters/CHAPTER_10.md => chapters/chapter_10.md (100%) rename _chapters/CHAPTER_11.md => chapters/chapter_11.md (100%) rename _chapters/CHAPTER_12.md => chapters/chapter_12.md (100%) rename _chapters/CHAPTER_13.md => chapters/chapter_13.md (100%) rename _chapters/CHAPTER_14.md => chapters/chapter_14.md (100%) rename _chapters/CHAPTER_15.md => chapters/chapter_15.md (100%) delete mode 100644 index.markdown create mode 100644 package.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore index f40fbd8..8832952 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,344 @@ -_site -.sass-cache -.jekyll-cache -.jekyll-metadata -vendor + +# Created by https://www.toptal.com/developers/gitignore/api/linux,windows,macos,pycharm+all,visualstudiocode,node,sublimetext +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,windows,macos,pycharm+all,visualstudiocode,node,sublimetext + +# Book build output +_book + +# eBook build output +*.epub +*.mobi +*.pdf + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env.production + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### PyCharm+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### SublimeText ### +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json +sftp-config-alt*.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/linux,windows,macos,pycharm+all,visualstudiocode,node,sublimetext diff --git a/404.html b/404.html deleted file mode 100644 index 9d12f61..0000000 --- a/404.html +++ /dev/null @@ -1,29 +0,0 @@ ---- -permalink: /404.html ---- - - - - - - {{ site.title }} - - - - -
-
-

404

- -

- -

Página não encontrada :(

- -

- -
- Ir para a Página inicial -
-
- - diff --git a/CNAME b/CNAME deleted file mode 100644 index aebf7fd..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -livro.descomplicandodocker.com.br \ No newline at end of file diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 6d5ab76..0000000 --- a/Gemfile +++ /dev/null @@ -1,30 +0,0 @@ -source "https://rubygems.org" -# Hello! This is where you manage which Jekyll version is used to run. -# When you want to use a different version, change it below, save the -# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: -# -# bundle exec jekyll serve -# -# This will help ensure the proper Jekyll version is running. -# Happy Jekylling! -gem "jekyll", "~> 4.2.0" -# This is the default theme for new Jekyll sites. You may change this to anything you like. -gem "minima", "~> 2.5" -# If you want to use GitHub Pages, remove the "gem "jekyll"" above and -# uncomment the line below. To upgrade, run `bundle update github-pages`. -# gem "github-pages", group: :jekyll_plugins -# If you have any plugins, put them here! -group :jekyll_plugins do - gem "jekyll-feed", "~> 0.12" -end - -# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem -# and associated library. -platforms :mingw, :x64_mingw, :mswin, :jruby do - gem "tzinfo", "~> 1.2" - gem "tzinfo-data" -end - -# Performance-booster for watching directories on Windows -gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] - diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 369d778..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,81 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - colorator (1.1.0) - concurrent-ruby (1.1.9) - em-websocket (0.5.2) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0.6.0) - eventmachine (1.2.7) - ffi (1.15.3) - forwardable-extended (2.6.0) - http_parser.rb (0.6.0) - i18n (1.8.10) - concurrent-ruby (~> 1.0) - jekyll (4.2.0) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (~> 1.0) - jekyll-sass-converter (~> 2.0) - jekyll-watch (~> 2.0) - kramdown (~> 2.3) - kramdown-parser-gfm (~> 1.0) - liquid (~> 4.0) - mercenary (~> 0.4.0) - pathutil (~> 0.9) - rouge (~> 3.0) - safe_yaml (~> 1.0) - terminal-table (~> 2.0) - jekyll-feed (0.15.1) - jekyll (>= 3.7, < 5.0) - jekyll-sass-converter (2.1.0) - sassc (> 2.0.1, < 3.0) - jekyll-seo-tag (2.7.1) - jekyll (>= 3.8, < 5.0) - jekyll-watch (2.2.1) - listen (~> 3.0) - kramdown (2.3.1) - rexml - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) - liquid (4.0.3) - listen (3.6.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.4.0) - minima (2.5.1) - jekyll (>= 3.5, < 5.0) - jekyll-feed (~> 0.9) - jekyll-seo-tag (~> 2.1) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (4.0.6) - rb-fsevent (0.11.0) - rb-inotify (0.10.1) - ffi (~> 1.0) - rexml (3.2.5) - rouge (3.26.0) - safe_yaml (1.0.5) - sassc (2.4.0) - ffi (~> 1.9) - terminal-table (2.0.0) - unicode-display_width (~> 1.1, >= 1.1.1) - unicode-display_width (1.7.0) - -PLATFORMS - ruby - x86_64-linux - -DEPENDENCIES - jekyll (~> 4.2.0) - jekyll-feed (~> 0.12) - minima (~> 2.5) - tzinfo (~> 1.2) - tzinfo-data - wdm (~> 0.1.1) - -BUNDLED WITH - 2.2.21 diff --git a/README.md b/README.md index 1c325aa..cded141 100644 --- a/README.md +++ b/README.md @@ -66,183 +66,3 @@ secret' e o 'docker stack', e atualizamos praticamente todo o restante do livro, visando torna-lo super atual e didático. Adicionamos mais exemplos práticos, para que sua experiência possa ser ainda mais agradável e proveitosa. - -# Sumário - -- [**Introdução**](./capitulos/CHAPTER_00.md#introdução) - -- [**1. O que é *container*?**](./capitulos/CHAPTER_01.md#1-o-que-é-container) - - - [1.1. Então vamos lá, o que é um *container*?](./capitulos/CHAPTER_01.md#11-então-vamos-lá-o-que-é-um-container) - - - [1.2. E quando começou que eu não vi?](./capitulos/CHAPTER_01.md#12-e-quando-começou-que-eu-não-vi) - -- [**2. O que é o Docker?**](./capitulos/CHAPTER_02.md#2-o-que-é-o-docker) - - - [2.1. Onde entra o Docker nessa história?](./capitulos/CHAPTER_02.md#21-onde-entra-o-docker-nessa-história) - - - [2.2. E esse negócio de camadas?](./capitulos/CHAPTER_02.md#22-e-esse-negócio-de-camadas) - - - [2.2.1. *Copy-On-Write* (COW) e Docker](./capitulos/CHAPTER_02.md#221-copy-on-write-cow-e-docker) - - - [2.3. Storage drivers](./capitulos/CHAPTER_02.md#23-storage-drivers) - - - [2.3.1. AUFS (*Another Union File System*)](./capitulos/CHAPTER_02.md#231-aufs-another-union-file-system) - - - [2.3.2. *Device Mapper*](./capitulos/CHAPTER_02.md#232-device-mapper) - - - [2.3.3. *Overlay* e *Overlay2*](./capitulos/CHAPTER_02.md#233-overlayfs-e-overlayfs2) - - - [2.3.4. BTRFS](./capitulos/CHAPTER_02.md#234-btrfs) - - - [2.4. Docker Internals](./capitulos/CHAPTER_02.md#24-docker-internals) - - - [2.5. *Namespaces*](./capitulos/CHAPTER_02.md#25-namespaces) - - - [2.5.1. PID *namespace*](./capitulos/CHAPTER_02.md#251-pid-namespace) - - - [2.5.2. Net *namespace*](./capitulos/CHAPTER_02.md#252-net-namespace) - - - [2.5.3. Mnt *namespace*](./capitulos/CHAPTER_02.md#253-mnt-namespace) - - - [2.5.4. IPC *namespace*](./capitulos/CHAPTER_02.md#254-ipc-namespace) - - - [2.5.5. UTS *namespace*](./capitulos/CHAPTER_02.md#255-uts-namespace) - - - [2.5.6. User *namespace*](./capitulos/CHAPTER_02.md#256-user-namespace) - - - [2.6. *Cgroups*](./capitulos/CHAPTER_02.md#26-cgroups) - - - [2.7. *Netfilter*](./capitulos/CHAPTER_02.md#27-netfilter) - - - [2.8. Para quem ele é bom?](./capitulos/CHAPTER_02.md#28-para-quem-ele-é-bom) - -- [**3. Instalando o Docker**](./capitulos/CHAPTER_03.md#3-instalando-o-docker) - - - [3.1. Quero instalar, vamos lá?](./capitulos/CHAPTER_03.md#31-quero-instalar-vamos-lá) - - - [3.2. Instalando no Debian/Centos/Ubuntu/Suse/Fedora](./capitulos/CHAPTER_03.md#32-instalando-no-debiancentosubuntususefedora) - - - [3.3. Instalando 'manualmente' no Debian](./capitulos/CHAPTER_03.md#33-instalando-manualmente-no-debian) - - - [3.3.1. Dica importante](./capitulos/CHAPTER_03.md#331-dica-importante) - -- [**4. Executando e administrando *containers* Docker**](./capitulos/CHAPTER_04.md#4-executando-e-administrando-containers-docker) - - - [4.1. Então vamos brincar com esse tal de *container*!](./capitulos/CHAPTER_04.md#41-então-vamos-brincar-com-esse-tal-de-container) - - - [4.2. Legal, quero mais!](./capitulos/CHAPTER_04.md#42-legal-quero-mais) - - - [4.2.1. Modo interativo](./capitulos/CHAPTER_04.md#421-modo-interativo) - - - [4.2.2. *Daemonizando* o *container*](./capitulos/CHAPTER_04.md#422-daemonizando-o-container) - - - [4.3. Entendi, agora vamos praticar um pouco?](./capitulos/CHAPTER_04.md#43-entendi-agora-vamos-praticar-um-pouco) - - - [4.4. Tá, agora quero sair\...](./capitulos/CHAPTER_04.md#44-tá-agora-quero-sair) - - - [4.5. Posso voltar ao *container*?](./capitulos/CHAPTER_04.md#45-posso-voltar-ao-container) - - - [4.6. Continuando com a brincadeira\...](./capitulos/CHAPTER_04.md#46-continuando-com-a-brincadeira) - - - [4.7. Subindo e matando *containers*...](./capitulos/CHAPTER_04.md#47-subindo-e-matando-containers) - - - [4.8. Visualizando o consumo de recursos pelo *container*\...](./capitulos/CHAPTER_04.md#48-visualizando-o-consumo-de-recursos-pelo-container) - - - [4.9. Cansei de brincar de container, quero removê-lo!](./capitulos/CHAPTER_04.md#49-cansei-de-brincar-de-container-quero-removê-lo) - -- [**5. Configurando CPU e memória para os meus *containers***](./capitulos/CHAPTER_05.md#5-configurando-cpu-e-memória-para-os-meus-containers) - - - [5.1. Especificando a quantidade de memória](./capitulos/CHAPTER_05.md#51-especificando-a-quantidade-de-memória) - - - [5.2. Especificando a quantidade de CPU](./capitulos/CHAPTER_05.md#52-especificando-a-quantidade-de-cpu) - - - [5.3. Eu consigo alterar CPU e memória dos meus *containers* em execução?](./capitulos/CHAPTER_05.md#53-eu-consigo-alterar-cpu-e-memória-dos-meus-containers-em-execução) - -- [**6. Meu primeiro e tosco *dockerfile*\...**](./capitulos/CHAPTER_06.md#6-meu-primeiro-e-tosco-dockerfile) - -- [**7. Entendendo volumes**](./capitulos/CHAPTER_07.md#7-entendendo-volumes) - - - [7.1. Introdução a volumes no Docker](./capitulos/CHAPTER_07.md#71-introdução-a-volumes-no-docker) - - - [7.2. Criando volumes](./capitulos/CHAPTER_07.md#72-criando-volumes) - - - [7.3. Localizando volumes](./capitulos/CHAPTER_07.md#73-localizando-volumes) - - - [7.4. Criando e montando um *data-only container*](./capitulos/CHAPTER_07.md#74-criando-e-montando-um-data-only-container) - - - [7.5. Sempre é bom um *backup*\...](./capitulos/CHAPTER_07.md#75-sempre-é-bom-um-backup) - -- [**8. Criando e gerenciando imagens**](./capitulos/CHAPTER_08.md#8-criando-e-gerenciando-imagens) - - - [8.1. Agora eu quero criar minha imagem, posso?](./capitulos/CHAPTER_08.md#81-agora-eu-quero-criar-minha-imagem-posso) - - - [8.2. Vamos começar do começo então, *dockerfile*!](./capitulos/CHAPTER_08.md#82-vamos-começar-do-começo-então-dockerfile) - - - [8.3. Bora aprender um pouco mais sobre *dockerfile*?](./capitulos/CHAPTER_08.md#83-bora-aprender-um-pouco-mais-sobre-dockerfile) - - - [8.4. *Multi-stage*](./capitulos/CHAPTER_08.md#84-multi-stage) - - - [8.5. Vamos customizar uma imagem base agora?](./capitulos/CHAPTER_08.md#85-vamos-customizar-uma-imagem-base-agora) - -- [**9. Compartilhando as imagens**](./capitulos/CHAPTER_09.md#9-compartilhando-as-imagens) - - - [9.1. O que é o *Docker Hub*?](./capitulos/CHAPTER_09.md#91-o-que-é-o-docker-hub) - - - [9.2. Vamos criar uma conta?](./capitulos/CHAPTER_09.md#92-vamos-criar-uma-conta) - - - [9.3. Agora vamos compartilhar essas imagens na *interwebs*!](./capitulos/CHAPTER_09.md#93-agora-vamos-compartilhar-essas-imagens-na-interwebs) - - - [9.4. Não confio na internet; posso criar o meu *registry* local?](./capitulos/CHAPTER_09.md#94-não-confio-na-internet-posso-criar-o-meu-registry-local) - -- [**10. Gerenciando a rede dos *containers***](./capitulos/CHAPTER_10.md#10-gerenciando-a-rede-dos-containers) - - - [10.1. Consigo fazer com que a porta do *container* responda na porta do *host*?](./capitulos/CHAPTER_10.md#101-consigo-fazer-com-que-a-porta-do-container-responda-na-porta-do-host) - - - [10.2. E como ele faz isso? Mágica?](./capitulos/CHAPTER_10.md#102-e-como-ele-faz-isso-mágica) - -- [**11. Controlando o *daemon* do Docker**](./capitulos/CHAPTER_11.md#11-controlando-o-daemon-do-docker) - - - [11.1. O Docker sempre utiliza 172.16.X.X ou posso configurar outro intervalo de IP?](./capitulos/CHAPTER_11.md#111-o-docker-sempre-utiliza-17216xx-ou-posso-configurar-outro-intervalo-de-ip) - - - [11.2. Opções de *sockets*](./capitulos/CHAPTER_11.md#112-opções-de-sockets) - - - [11.2.1. *Unix Domain Socket*](./capitulos/CHAPTER_11.md#1121-unix-domain-socket) - - - [11.2.2. TCP](./capitulos/CHAPTER_11.md#1122-tcp) - - - [11.3. Opções de *storage*](./capitulos/CHAPTER_11.md#113-opções-de-storage) - - - [11.4. Opções de rede](./capitulos/CHAPTER_11.md#114-opções-de-rede) - - - [11.5. Opções diversas](./capitulos/CHAPTER_11.md#115-opções-diversas) - -- [**12. Docker Machine**](./capitulos/CHAPTER_12.md#12-docker-machine) - - - [12.1. Ouvi dizer que minha vida ficaria melhor com o Docker Machine!](./capitulos/CHAPTER_12.md#121-ouvi-dizer-que-minha-vida-ficaria-melhor-com-o-docker-machine) - - - [12.1.1. Vamos instalar?](./capitulos/CHAPTER_12.md#1211-vamos-instalar) - - - [12.1.2. Vamos iniciar nosso primeiro projeto?](./capitulos/CHAPTER_12.md#1212-vamos-iniciar-nosso-primeiro-projeto) - -- [**13. Docker Swarm**](./capitulos/CHAPTER_13.md#13-docker-swarm) - - - [13.1. Criando o nosso *cluster*!](./capitulos/CHAPTER_13.md#131-criando-o-nosso-cluster) - - - [13.2. O sensacional services!](./capitulos/CHAPTER_13.md#132-o-sensacional-services) - -- [**14. Docker Secrets**](./capitulos/CHAPTER_14.md#14-docker-secrets) - - - [14.1. O comando *docker secret*](./capitulos/CHAPTER_14.md#141-o-comando-docker-secret) - - - [14.2. Tudo bem, mas como uso isso?](./capitulos/CHAPTER_14.md#142-tudo-bem-mas-como-uso-isso) - - - [14.3. Acessando a *secret*](./capitulos/CHAPTER_14.md#143-acessando-a-secret) - - - [14.4. Atualizando a *secret* de um serviço](./capitulos/CHAPTER_14.md#144-atualizando-a-secret-de-um-serviço) - -- [**15. Docker Compose**](./capitulos/CHAPTER_15.md#15-docker-compose) - - - [15.1. O comando docker stack](./capitulos/CHAPTER_15.md#151-o-comando-docker-stack) - - - [15.2. E já acabou? :(](./capitulos/CHAPTER_15.md#152-e-já-acabou-) diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..045b9a8 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,25 @@ +# Summary + +### Sobre + +* [Proposta do livro](README.md) + +### Capítulos + +* [Introdução](chapters/chapter_00.md) +* [ O que é container](chapters/chapter_01.md) +* [O que é o Docker](chapters/chapter_02.md) +* [Instalando o Docker](chapters/chapter_03.md) +* [Executando e administrando containers Docker](chapters/chapter_04.md) +* [Configurando CPU e memória para os meus containers](chapters/chapter_05.md) +* [Meu primeiro e tosco dockerfile...](chapters/chapter_06.md) +* [Entendendo volumes](chapters/chapter_07.md) +* [Criando e gerenciando imagens](chapters/chapter_08.md) +* [Compartilhando as imagens](chapters/chapter_09.md) +* [Gerenciando a rede dos containers](chapters/chapter_10.md) +* [Controlando o daemon do Docker](chapters/chapter_11.md) +* [Docker Machine](chapters/chapter_12.md) +* [Docker Swarm](chapters/chapter_13.md) +* [Docker Secrets](chapters/chapter_14.md) +* [Docker Compose](chapters/chapter_15.md) + diff --git a/_config.yml b/_config.yml deleted file mode 100644 index 1505c25..0000000 --- a/_config.yml +++ /dev/null @@ -1,20 +0,0 @@ -title: Livro Descomplicando o Docker -baseurl: "/" - -sass: - sass_dir: _sass - style: compressed - -collections: - chapters: - output: true - -defaults: - - - scope: - path: "" - type: "chapters" - values: - layout: "default" - -theme: jekyll-theme-dinky \ No newline at end of file diff --git a/_includes/navbar.html b/_includes/navbar.html deleted file mode 100644 index fcbceb0..0000000 --- a/_includes/navbar.html +++ /dev/null @@ -1,23 +0,0 @@ - diff --git a/_includes/sidebar.html b/_includes/sidebar.html deleted file mode 100644 index c3eb6a7..0000000 --- a/_includes/sidebar.html +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/_layouts/default.html b/_layouts/default.html deleted file mode 100644 index ec668a9..0000000 --- a/_layouts/default.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {{ site.title }} - - - - - {% include navbar.html %} - -
- {% include sidebar.html %} - -
-
- {{ content }} -
-
-
- - diff --git a/assets/css/bootswatch-superhero.min.css b/assets/css/bootswatch-superhero.min.css deleted file mode 100644 index 75723c4..0000000 --- a/assets/css/bootswatch-superhero.min.css +++ /dev/null @@ -1,12 +0,0 @@ -/*! - * Bootswatch v5.1.0 - * Homepage: https://bootswatch.com - * Copyright 2012-2021 Thomas Park - * Licensed under MIT - * Based on Bootstrap -*//*! - * Bootstrap v5.1.0 (https://getbootstrap.com/) - * Copyright 2011-2021 The Bootstrap Authors - * Copyright 2011-2021 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */@import url(https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap);:root{--bs-blue:#4c9be8;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#e83e8c;--bs-red:#d9534f;--bs-orange:#f0ad4e;--bs-yellow:#ffc107;--bs-green:#5cb85c;--bs-teal:#20c997;--bs-cyan:#5bc0de;--bs-white:#fff;--bs-gray:#868e96;--bs-gray-dark:#343a40;--bs-gray-100:#ebebeb;--bs-gray-200:#4e5d6c;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#868e96;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#4c9be8;--bs-secondary:#4e5d6c;--bs-success:#5cb85c;--bs-info:#5bc0de;--bs-warning:#ffc107;--bs-danger:#d9534f;--bs-light:#abb6c2;--bs-dark:#20374c;--bs-primary-rgb:76,155,232;--bs-secondary-rgb:78,93,108;--bs-success-rgb:92,184,92;--bs-info-rgb:91,192,222;--bs-warning-rgb:255,193,7;--bs-danger-rgb:217,83,79;--bs-light-rgb:170.516129,182.25,193.983871;--bs-dark-rgb:32,55,76;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-rgb:235,235,235;--bs-font-sans-serif:Lato,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#ebebeb;--bs-body-bg:#0f2537}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#4c9be8;text-decoration:underline}a:hover{color:#3d7cba}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em;color:inherit}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:0}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:rgba(255,255,255,.4);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#868e96}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#0f2537;border:1px solid #dee2e6;border-radius:0;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#868e96}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{width:100%;padding-right:var(--bs-gutter-x,.75rem);padding-left:var(--bs-gutter-x,.75rem);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y) * -1);margin-right:calc(var(--bs-gutter-x) * -.5);margin-left:calc(var(--bs-gutter-x) * -.5)}.row>*{-ms-flex-negative:0;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{-ms-flex:1 0 0%;flex:1 0 0%}.row-cols-auto>*{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.row-cols-1>*{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.row-cols-2>*{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.row-cols-3>*{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.row-cols-4>*{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.row-cols-5>*{-ms-flex:0 0 auto;flex:0 0 auto;width:20%}.row-cols-6>*{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.333333%}.col-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.col-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.col-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.666667%}.col-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.col-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.333333%}.col-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.666667%}.col-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.col-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.333333%}.col-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.666667%}.col-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{-ms-flex:1 0 0%;flex:1 0 0%}.row-cols-sm-auto>*{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.row-cols-sm-1>*{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.row-cols-sm-2>*{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.row-cols-sm-3>*{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.row-cols-sm-5>*{-ms-flex:0 0 auto;flex:0 0 auto;width:20%}.row-cols-sm-6>*{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.333333%}.col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.666667%}.col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.333333%}.col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.666667%}.col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.333333%}.col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.666667%}.col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{-ms-flex:1 0 0%;flex:1 0 0%}.row-cols-md-auto>*{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.row-cols-md-1>*{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.row-cols-md-2>*{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.row-cols-md-3>*{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.row-cols-md-5>*{-ms-flex:0 0 auto;flex:0 0 auto;width:20%}.row-cols-md-6>*{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.333333%}.col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.666667%}.col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.333333%}.col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.666667%}.col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.333333%}.col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.666667%}.col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{-ms-flex:1 0 0%;flex:1 0 0%}.row-cols-lg-auto>*{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.row-cols-lg-1>*{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.row-cols-lg-2>*{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.row-cols-lg-3>*{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.row-cols-lg-5>*{-ms-flex:0 0 auto;flex:0 0 auto;width:20%}.row-cols-lg-6>*{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.333333%}.col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.666667%}.col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.333333%}.col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.666667%}.col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.333333%}.col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.666667%}.col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{-ms-flex:1 0 0%;flex:1 0 0%}.row-cols-xl-auto>*{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.row-cols-xl-1>*{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.row-cols-xl-2>*{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.row-cols-xl-3>*{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.row-cols-xl-5>*{-ms-flex:0 0 auto;flex:0 0 auto;width:20%}.row-cols-xl-6>*{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.333333%}.col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.666667%}.col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.333333%}.col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.666667%}.col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.333333%}.col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.666667%}.col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{-ms-flex:1 0 0%;flex:1 0 0%}.row-cols-xxl-auto>*{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.row-cols-xxl-1>*{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.row-cols-xxl-2>*{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.row-cols-xxl-3>*{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.row-cols-xxl-4>*{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.row-cols-xxl-5>*{-ms-flex:0 0 auto;flex:0 0 auto;width:20%}.row-cols-xxl-6>*{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-xxl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-xxl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.333333%}.col-xxl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.666667%}.col-xxl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.col-xxl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.333333%}.col-xxl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.666667%}.col-xxl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.col-xxl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.333333%}.col-xxl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.666667%}.col-xxl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.col-xxl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.333333%}.col-xxl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.666667%}.col-xxl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.333333%}.offset-xxl-2{margin-left:16.666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.333333%}.offset-xxl-5{margin-left:41.666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.333333%}.offset-xxl-8{margin-left:66.666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.333333%}.offset-xxl-11{margin-left:91.666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-bg:transparent;--bs-table-accent-bg:rgba(255, 255, 255, 0.05);--bs-table-striped-color:#ebebeb;--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:#ebebeb;--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:#ebebeb;--bs-table-hover-bg:rgba(255, 255, 255, 0.075);width:100%;margin-bottom:1rem;color:#ebebeb;vertical-align:top;border-color:rgba(0,0,0,.15)}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:last-child)>:last-child>*{border-bottom-color:currentColor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-striped>tbody>tr:nth-of-type(odd){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg:#4c9be8;--bs-table-striped-bg:#55a0e9;--bs-table-striped-color:#fff;--bs-table-active-bg:#5ea5ea;--bs-table-active-color:#fff;--bs-table-hover-bg:#59a3ea;--bs-table-hover-color:#fff;color:#fff;border-color:#5ea5ea}.table-secondary{--bs-table-bg:#4e5d6c;--bs-table-striped-bg:#576573;--bs-table-striped-color:#fff;--bs-table-active-bg:#606d7b;--bs-table-active-color:#fff;--bs-table-hover-bg:#5b6977;--bs-table-hover-color:#fff;color:#fff;border-color:#606d7b}.table-success{--bs-table-bg:#5cb85c;--bs-table-striped-bg:#64bc64;--bs-table-striped-color:#fff;--bs-table-active-bg:#6cbf6c;--bs-table-active-color:#fff;--bs-table-hover-bg:#68bd68;--bs-table-hover-color:#fff;color:#fff;border-color:#6cbf6c}.table-info{--bs-table-bg:#5bc0de;--bs-table-striped-bg:#63c3e0;--bs-table-striped-color:#fff;--bs-table-active-bg:#6bc6e1;--bs-table-active-color:#fff;--bs-table-hover-bg:#67c5e0;--bs-table-hover-color:#fff;color:#fff;border-color:#6bc6e1}.table-warning{--bs-table-bg:#ffc107;--bs-table-striped-bg:#ffc413;--bs-table-striped-color:#000;--bs-table-active-bg:#ffc720;--bs-table-active-color:#000;--bs-table-hover-bg:#ffc61a;--bs-table-hover-color:#000;color:#fff;border-color:#ffc720}.table-danger{--bs-table-bg:#d9534f;--bs-table-striped-bg:#db5c58;--bs-table-striped-color:#fff;--bs-table-active-bg:#dd6461;--bs-table-active-color:#fff;--bs-table-hover-bg:#dc605c;--bs-table-hover-color:#fff;color:#fff;border-color:#dd6461}.table-light{--bs-table-bg:#abb6c2;--bs-table-striped-bg:#afbac5;--bs-table-striped-color:#fff;--bs-table-active-bg:#b3bec8;--bs-table-active-color:#fff;--bs-table-hover-bg:#b1bcc7;--bs-table-hover-color:#fff;color:#fff;border-color:#b3bec8}.table-dark{--bs-table-bg:#20374c;--bs-table-striped-bg:#2b4155;--bs-table-striped-color:#fff;--bs-table-active-bg:#364b5e;--bs-table-active-color:#fff;--bs-table-hover-bg:#314659;--bs-table-hover-color:#fff;color:#fff;border-color:#364b5e}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:.5rem;padding-bottom:.5rem;font-size:1.25rem}.col-form-label-sm{padding-top:.25rem;padding-bottom:.25rem;font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:rgba(255,255,255,.4)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:0 solid transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#a6cdf4;outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-webkit-input-placeholder{color:#868e96;opacity:1}.form-control::-moz-placeholder{color:#868e96;opacity:1}.form-control:-ms-input-placeholder{color:#868e96;opacity:1}.form-control::-ms-input-placeholder{color:#868e96;opacity:1}.form-control::placeholder{color:#868e96;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#ebebeb;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;-moz-margin-end:.75rem;margin-inline-end:.75rem;color:#ebebeb;background-color:#4e5d6c;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:0;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#4a5867}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#ebebeb;background-color:#4e5d6c;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:0;border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#4a5867}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#ebebeb;background-color:transparent;border:solid transparent;border-width:0 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem);padding:.25rem .5rem;font-size:.875rem;border-radius:0}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;-moz-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem);padding:.5rem 1rem;font-size:1.25rem;border-radius:0}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;-moz-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem)}textarea.form-control-sm{min-height:calc(1.5em + .5rem)}textarea.form-control-lg{min-height:calc(1.5em + 1rem)}.form-control-color{width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em;border-radius:0}.form-control-color::-webkit-color-swatch{height:1.5em;border-radius:0}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:0 solid transparent;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#a6cdf4;outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#4e5d6c}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{-webkit-filter:brightness(90%);filter:brightness(90%)}.form-check-input:focus{border-color:#a6cdf4;outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25)}.form-check-input:checked{background-color:#4c9be8;border-color:#4c9be8}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#4c9be8;border-color:#4c9be8;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;-webkit-filter:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23a6cdf4'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;-webkit-filter:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #0f2537,0 0 0 .25rem rgba(76,155,232,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #0f2537,0 0 0 .25rem rgba(76,155,232,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#4c9be8;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#c9e1f8}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#4c9be8;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#c9e1f8}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:3.5rem;line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:0 solid transparent;-webkit-transform-origin:0 0;transform-origin:0 0;transition:opacity .1s ease-in-out,-webkit-transform .1s ease-in-out;transition:opacity .1s ease-in-out,transform .1s ease-in-out;transition:opacity .1s ease-in-out,transform .1s ease-in-out,-webkit-transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control{padding:1rem .75rem}.form-floating>.form-control::-webkit-input-placeholder{color:transparent}.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control:-ms-input-placeholder{color:transparent}.form-floating>.form-control::-ms-input-placeholder{color:transparent}.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-ms-input-placeholder){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:1;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:not(:-ms-input-placeholder)~label{opacity:1;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:1;-webkit-transform:scale(.85) translateY(-.5rem) translateX(.15rem);transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:1;-webkit-transform:scale(.85) translateY(-.5rem) translateX(.15rem);transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#ebebeb;text-align:center;white-space:nowrap;background-color:#4e5d6c;border:0 solid transparent;border-radius:0}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:0}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:0}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#5cb85c}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(92,184,92,.9);border-radius:0}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#5cb85c;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#5cb85c;box-shadow:0 0 0 .25rem rgba(92,184,92,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#5cb85c}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#5cb85c;box-shadow:0 0 0 .25rem rgba(92,184,92,.25)}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#5cb85c}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#5cb85c}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(92,184,92,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#5cb85c}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group .form-control.is-valid,.input-group .form-select.is-valid,.was-validated .input-group .form-control:valid,.was-validated .input-group .form-select:valid{z-index:1}.input-group .form-control.is-valid:focus,.input-group .form-select.is-valid:focus,.was-validated .input-group .form-control:valid:focus,.was-validated .input-group .form-select:valid:focus{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#d9534f}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(217,83,79,.9);border-radius:0}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#d9534f;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23d9534f'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23d9534f' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#d9534f;box-shadow:0 0 0 .25rem rgba(217,83,79,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#d9534f}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23d9534f'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23d9534f' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#d9534f;box-shadow:0 0 0 .25rem rgba(217,83,79,.25)}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#d9534f}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#d9534f}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(217,83,79,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#d9534f}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group .form-control.is-invalid,.input-group .form-select.is-invalid,.was-validated .input-group .form-control:invalid,.was-validated .input-group .form-select:invalid{z-index:2}.input-group .form-control.is-invalid:focus,.input-group .form-select.is-invalid:focus,.was-validated .input-group .form-control:invalid:focus,.was-validated .input-group .form-select:invalid:focus{z-index:3}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#ebebeb;text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#ebebeb}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-primary{color:#fff;background-color:#4c9be8;border-color:#4c9be8}.btn-primary:hover{color:#fff;background-color:#4184c5;border-color:#3d7cba}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#4184c5;border-color:#3d7cba;box-shadow:0 0 0 .25rem rgba(103,170,235,.5)}.btn-check:active+.btn-primary,.btn-check:checked+.btn-primary,.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#3d7cba;border-color:#3974ae}.btn-check:active+.btn-primary:focus,.btn-check:checked+.btn-primary:focus,.btn-primary.active:focus,.btn-primary:active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(103,170,235,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#4c9be8;border-color:#4c9be8}.btn-secondary{color:#fff;background-color:#4e5d6c;border-color:#4e5d6c}.btn-secondary:hover{color:#fff;background-color:#424f5c;border-color:#3e4a56}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#424f5c;border-color:#3e4a56;box-shadow:0 0 0 .25rem rgba(105,117,130,.5)}.btn-check:active+.btn-secondary,.btn-check:checked+.btn-secondary,.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#3e4a56;border-color:#3b4651}.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary:focus,.btn-secondary.active:focus,.btn-secondary:active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(105,117,130,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#4e5d6c;border-color:#4e5d6c}.btn-success{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-success:hover{color:#fff;background-color:#4e9c4e;border-color:#4a934a}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#4e9c4e;border-color:#4a934a;box-shadow:0 0 0 .25rem rgba(116,195,116,.5)}.btn-check:active+.btn-success,.btn-check:checked+.btn-success,.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#4a934a;border-color:#458a45}.btn-check:active+.btn-success:focus,.btn-check:checked+.btn-success:focus,.btn-success.active:focus,.btn-success:active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(116,195,116,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-info:hover{color:#fff;background-color:#4da3bd;border-color:#499ab2}.btn-check:focus+.btn-info,.btn-info:focus{color:#fff;background-color:#4da3bd;border-color:#499ab2;box-shadow:0 0 0 .25rem rgba(116,201,227,.5)}.btn-check:active+.btn-info,.btn-check:checked+.btn-info,.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#499ab2;border-color:#4490a7}.btn-check:active+.btn-info:focus,.btn-check:checked+.btn-info:focus,.btn-info.active:focus,.btn-info:active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(116,201,227,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-warning{color:#fff;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#fff;background-color:#d9a406;border-color:#cc9a06}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#fff;background-color:#d9a406;border-color:#cc9a06;box-shadow:0 0 0 .25rem rgba(255,202,44,.5)}.btn-check:active+.btn-warning,.btn-check:checked+.btn-warning,.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#cc9a06;border-color:#bf9105}.btn-check:active+.btn-warning:focus,.btn-check:checked+.btn-warning:focus,.btn-warning.active:focus,.btn-warning:active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(255,202,44,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#ffc107;border-color:#ffc107}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-danger:hover{color:#fff;background-color:#b84743;border-color:#ae423f}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#b84743;border-color:#ae423f;box-shadow:0 0 0 .25rem rgba(223,109,105,.5)}.btn-check:active+.btn-danger,.btn-check:checked+.btn-danger,.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#ae423f;border-color:#a33e3b}.btn-check:active+.btn-danger:focus,.btn-check:checked+.btn-danger:focus,.btn-danger.active:focus,.btn-danger:active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(223,109,105,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-light{color:#fff;background-color:#abb6c2;border-color:#abb6c2}.btn-light:hover{color:#fff;background-color:#919ba5;border-color:#88929b}.btn-check:focus+.btn-light,.btn-light:focus{color:#fff;background-color:#919ba5;border-color:#88929b;box-shadow:0 0 0 .25rem rgba(183,193,203,.5)}.btn-check:active+.btn-light,.btn-check:checked+.btn-light,.btn-light.active,.btn-light:active,.show>.btn-light.dropdown-toggle{color:#fff;background-color:#88929b;border-color:#808991}.btn-check:active+.btn-light:focus,.btn-check:checked+.btn-light:focus,.btn-light.active:focus,.btn-light:active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(183,193,203,.5)}.btn-light.disabled,.btn-light:disabled{color:#fff;background-color:#abb6c2;border-color:#abb6c2}.btn-dark{color:#fff;background-color:#20374c;border-color:#20374c}.btn-dark:hover{color:#fff;background-color:#1b2f41;border-color:#1a2c3d}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#1b2f41;border-color:#1a2c3d;box-shadow:0 0 0 .25rem rgba(65,85,103,.5)}.btn-check:active+.btn-dark,.btn-check:checked+.btn-dark,.btn-dark.active,.btn-dark:active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1a2c3d;border-color:#182939}.btn-check:active+.btn-dark:focus,.btn-check:checked+.btn-dark:focus,.btn-dark.active:focus,.btn-dark:active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(65,85,103,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#20374c;border-color:#20374c}.btn-outline-primary{color:#4c9be8;border-color:#4c9be8}.btn-outline-primary:hover{color:#fff;background-color:#4c9be8;border-color:#4c9be8}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(76,155,232,.5)}.btn-check:active+.btn-outline-primary,.btn-check:checked+.btn-outline-primary,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show,.btn-outline-primary:active{color:#fff;background-color:#4c9be8;border-color:#4c9be8}.btn-check:active+.btn-outline-primary:focus,.btn-check:checked+.btn-outline-primary:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus,.btn-outline-primary:active:focus{box-shadow:0 0 0 .25rem rgba(76,155,232,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#4c9be8;background-color:transparent}.btn-outline-secondary{color:#4e5d6c;border-color:#4e5d6c}.btn-outline-secondary:hover{color:#fff;background-color:#4e5d6c;border-color:#4e5d6c}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(78,93,108,.5)}.btn-check:active+.btn-outline-secondary,.btn-check:checked+.btn-outline-secondary,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show,.btn-outline-secondary:active{color:#fff;background-color:#4e5d6c;border-color:#4e5d6c}.btn-check:active+.btn-outline-secondary:focus,.btn-check:checked+.btn-outline-secondary:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus,.btn-outline-secondary:active:focus{box-shadow:0 0 0 .25rem rgba(78,93,108,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#4e5d6c;background-color:transparent}.btn-outline-success{color:#5cb85c;border-color:#5cb85c}.btn-outline-success:hover{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(92,184,92,.5)}.btn-check:active+.btn-outline-success,.btn-check:checked+.btn-outline-success,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show,.btn-outline-success:active{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-check:active+.btn-outline-success:focus,.btn-check:checked+.btn-outline-success:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus,.btn-outline-success:active:focus{box-shadow:0 0 0 .25rem rgba(92,184,92,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#5cb85c;background-color:transparent}.btn-outline-info{color:#5bc0de;border-color:#5bc0de}.btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(91,192,222,.5)}.btn-check:active+.btn-outline-info,.btn-check:checked+.btn-outline-info,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show,.btn-outline-info:active{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-check:active+.btn-outline-info:focus,.btn-check:checked+.btn-outline-info:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus,.btn-outline-info:active:focus{box-shadow:0 0 0 .25rem rgba(91,192,222,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#5bc0de;background-color:transparent}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#fff;background-color:#ffc107;border-color:#ffc107}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-check:active+.btn-outline-warning,.btn-check:checked+.btn-outline-warning,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show,.btn-outline-warning:active{color:#fff;background-color:#ffc107;border-color:#ffc107}.btn-check:active+.btn-outline-warning:focus,.btn-check:checked+.btn-outline-warning:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus,.btn-outline-warning:active:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-danger{color:#d9534f;border-color:#d9534f}.btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(217,83,79,.5)}.btn-check:active+.btn-outline-danger,.btn-check:checked+.btn-outline-danger,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show,.btn-outline-danger:active{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-check:active+.btn-outline-danger:focus,.btn-check:checked+.btn-outline-danger:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus,.btn-outline-danger:active:focus{box-shadow:0 0 0 .25rem rgba(217,83,79,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#d9534f;background-color:transparent}.btn-outline-light{color:#abb6c2;border-color:#abb6c2}.btn-outline-light:hover{color:#fff;background-color:#abb6c2;border-color:#abb6c2}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(171,182,194,.5)}.btn-check:active+.btn-outline-light,.btn-check:checked+.btn-outline-light,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show,.btn-outline-light:active{color:#fff;background-color:#abb6c2;border-color:#abb6c2}.btn-check:active+.btn-outline-light:focus,.btn-check:checked+.btn-outline-light:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus,.btn-outline-light:active:focus{box-shadow:0 0 0 .25rem rgba(171,182,194,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#abb6c2;background-color:transparent}.btn-outline-dark{color:#20374c;border-color:#20374c}.btn-outline-dark:hover{color:#fff;background-color:#20374c;border-color:#20374c}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(32,55,76,.5)}.btn-check:active+.btn-outline-dark,.btn-check:checked+.btn-outline-dark,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show,.btn-outline-dark:active{color:#fff;background-color:#20374c;border-color:#20374c}.btn-check:active+.btn-outline-dark:focus,.btn-check:checked+.btn-outline-dark:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus,.btn-outline-dark:active:focus{box-shadow:0 0 0 .25rem rgba(32,55,76,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#20374c;background-color:transparent}.btn-link{font-weight:400;color:#4c9be8;text-decoration:underline}.btn-link:hover{color:#3d7cba}.btn-link.disabled,.btn-link:disabled{color:#868e96}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;border-radius:0}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:0}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropend,.dropstart,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#ebebeb;text-align:left;list-style:none;background-color:#4e5d6c;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:0}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#ebebeb;text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#ebebeb;background-color:rgba(255,255,255,.075)}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#4c9be8}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#868e96;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#ebebeb}.dropdown-menu-dark{color:#dee2e6;background-color:#343a40;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:focus,.dropdown-menu-dark .dropdown-item:hover{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#4c9be8}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;color:#4c9be8;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:#3d7cba}.nav-link.disabled{color:rgba(255,255,255,.4);pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #4e5d6c}.nav-tabs .nav-link{margin-bottom:-1px;background:0 0;border:1px solid transparent;border-top-left-radius:0;border-top-right-radius:0}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#4e5d6c #4e5d6c #4e5d6c;isolation:isolate}.nav-tabs .nav-link.disabled{color:rgba(255,255,255,.4);background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#ebebeb;background-color:#0f2537;border-color:#4e5d6c}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:0}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#4c9be8}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:-ms-flexbox;display:flex;-ms-flex-wrap:inherit;flex-wrap:inherit;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:0;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas-header{display:none}.navbar-expand-sm .offcanvas{position:inherit;bottom:0;z-index:1000;-ms-flex-positive:1;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;-webkit-transform:none;transform:none}.navbar-expand-sm .offcanvas-bottom,.navbar-expand-sm .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-sm .offcanvas-body{display:-ms-flexbox;display:flex;-ms-flex-positive:0;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas-header{display:none}.navbar-expand-md .offcanvas{position:inherit;bottom:0;z-index:1000;-ms-flex-positive:1;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;-webkit-transform:none;transform:none}.navbar-expand-md .offcanvas-bottom,.navbar-expand-md .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-md .offcanvas-body{display:-ms-flexbox;display:flex;-ms-flex-positive:0;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas-header{display:none}.navbar-expand-lg .offcanvas{position:inherit;bottom:0;z-index:1000;-ms-flex-positive:1;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;-webkit-transform:none;transform:none}.navbar-expand-lg .offcanvas-bottom,.navbar-expand-lg .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-lg .offcanvas-body{display:-ms-flexbox;display:flex;-ms-flex-positive:0;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas-header{display:none}.navbar-expand-xl .offcanvas{position:inherit;bottom:0;z-index:1000;-ms-flex-positive:1;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;-webkit-transform:none;transform:none}.navbar-expand-xl .offcanvas-bottom,.navbar-expand-xl .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-xl .offcanvas-body{display:-ms-flexbox;display:flex;-ms-flex-positive:0;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas{position:inherit;bottom:0;z-index:1000;-ms-flex-positive:1;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;-webkit-transform:none;transform:none}.navbar-expand-xxl .offcanvas-bottom,.navbar-expand-xxl .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-xxl .offcanvas-body{display:-ms-flexbox;display:flex;-ms-flex-positive:0;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas-header{display:none}.navbar-expand .offcanvas{position:inherit;bottom:0;z-index:1000;-ms-flex-positive:1;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;-webkit-transform:none;transform:none}.navbar-expand .offcanvas-bottom,.navbar-expand .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand .offcanvas-body{display:-ms-flexbox;display:flex;-ms-flex-positive:0;flex-grow:0;padding:0;overflow-y:visible}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.55)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.55);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.55)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:#fff}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.75);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.75)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#4e5d6c;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:0}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:0;border-top-right-radius:0}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:rgba(255,255,255,.075);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:0}.card-footer{padding:.5rem 1rem;background-color:rgba(255,255,255,.075);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0}.card-header-tabs{margin-right:-.5rem;margin-bottom:-.5rem;margin-left:-.5rem;border-bottom:0}.card-header-tabs .nav-link.active{background-color:#4e5d6c;border-bottom-color:#4e5d6c}.card-header-pills{margin-right:-.5rem;margin-left:-.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:0}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:0;border-top-right-radius:0}.card-img,.card-img-bottom{border-bottom-right-radius:0;border-bottom-left-radius:0}.card-group>.card{margin-bottom:.75rem}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion-button{position:relative;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#ebebeb;text-align:left;background-color:#0f2537;border:0;border-radius:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#448cd1;background-color:#edf5fd;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23448cd1'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}.accordion-button::after{-ms-flex-negative:0;flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ebebeb'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#a6cdf4;outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25)}.accordion-header{margin-bottom:0}.accordion-item{background-color:#0f2537;border:1px solid rgba(0,0,0,.125)}.accordion-item:first-of-type{border-top-left-radius:0;border-top-right-radius:0}.accordion-item:first-of-type .accordion-button{border-top-left-radius:0;border-top-right-radius:0}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button{border-radius:0}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.375rem .75rem;margin-bottom:1rem;list-style:none;background-color:#4e5d6c}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#ebebeb;content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:#ebebeb}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#fff;text-decoration:none;background-color:#4e5d6c;border:1px solid transparent;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#fff;background-color:rgba(255,255,255,.4);border-color:transparent}.page-link:focus{z-index:3;color:#3d7cba;background-color:#4e5d6c;outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#4c9be8;border-color:#4c9be8}.page-item.disabled .page-link{color:rgba(255,255,255,.4);pointer-events:none;background-color:#4e5d6c;border-color:transparent}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-top-left-radius:0;border-bottom-left-radius:0}.page-item:last-child .page-link{border-top-right-radius:0;border-bottom-right-radius:0}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:0;border-bottom-left-radius:0}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:0;border-bottom-right-radius:0}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:0;border-bottom-left-radius:0}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:0;border-bottom-right-radius:0}.badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:0}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:1px solid transparent;border-radius:0}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{color:#2e5d8b;background-color:#dbebfa;border-color:#c9e1f8}.alert-primary .alert-link{color:#254a6f}.alert-secondary{color:#2f3841;background-color:#dcdfe2;border-color:#caced3}.alert-secondary .alert-link{color:#262d34}.alert-success{color:#376e37;background-color:#def1de;border-color:#ceeace}.alert-success .alert-link{color:#2c582c}.alert-info{color:#377385;background-color:#def2f8;border-color:#ceecf5}.alert-info .alert-link{color:#2c5c6a}.alert-warning{color:#997404;background-color:#fff3cd;border-color:#ffecb5}.alert-warning .alert-link{color:#7a5d03}.alert-danger{color:#82322f;background-color:#f7dddc;border-color:#f4cbca}.alert-danger .alert-link{color:#682826}.alert-light{color:#666d74;background-color:#eef0f3;border-color:#e6e9ed}.alert-light .alert-link{color:#52575d}.alert-dark{color:#13212e;background-color:#d2d7db;border-color:#bcc3c9}.alert-dark .alert-link{color:#0f1a25}@-webkit-keyframes progress-bar-stripes{0%{background-position-x:1rem}}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#4e5d6c;border-radius:0}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#4c9be8;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:0}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#fff;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#fff;text-decoration:none;background-color:rgba(255,255,255,.4)}.list-group-item-action:active{color:#ebebeb;background-color:#4e5d6c}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#fff;text-decoration:none;background-color:#4e5d6c;border:1px solid transparent}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:rgba(255,255,255,.4);pointer-events:none;background-color:#4e5d6c}.list-group-item.active{z-index:2;color:#fff;background-color:#4c9be8;border-color:#4c9be8}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:0;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:0;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:0;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:0;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:0;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:0;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:0;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:0;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:0;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:0;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1400px){.list-group-horizontal-xxl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:0;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-top-right-radius:0;border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#2e5d8b;background-color:#dbebfa}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#2e5d8b;background-color:#c5d4e1}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#2e5d8b;border-color:#2e5d8b}.list-group-item-secondary{color:#2f3841;background-color:#dcdfe2}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#2f3841;background-color:#c6c9cb}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#2f3841;border-color:#2f3841}.list-group-item-success{color:#376e37;background-color:#def1de}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#376e37;background-color:#c8d9c8}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#376e37;border-color:#376e37}.list-group-item-info{color:#377385;background-color:#def2f8}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#377385;background-color:#c8dadf}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#377385;border-color:#377385}.list-group-item-warning{color:#997404;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#997404;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#997404;border-color:#997404}.list-group-item-danger{color:#82322f;background-color:#f7dddc}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#82322f;background-color:#dec7c6}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#82322f;border-color:#82322f}.list-group-item-light{color:#666d74;background-color:#eef0f3}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#666d74;background-color:#d6d8db}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#666d74;border-color:#666d74}.list-group-item-dark{color:#13212e;background-color:#d2d7db}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#13212e;background-color:#bdc2c5}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#13212e;border-color:#13212e}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#fff;background:transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:0;opacity:.5}.btn-close:hover{color:#fff;text-decoration:none;opacity:1}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(76,155,232,.25);opacity:1}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;opacity:.25}.btn-close-white{-webkit-filter:invert(1) grayscale(100%) brightness(200%);filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:.875rem;pointer-events:auto;background-color:#4e5d6c;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);box-shadow:0 .5rem 1rem rgba(0,0,0,.15);border-radius:0}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.5rem .75rem;color:#ebebeb;background-color:#4e5d6c;background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.2);border-top-left-radius:0;border-top-right-radius:0}.toast-header .btn-close{margin-right:-.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal{position:fixed;top:0;left:0;z-index:1055;display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#4e5d6c;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:0;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1050;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid rgba(0,0,0,.2);border-top-left-radius:0;border-top-right-radius:0}.modal-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-negative:0;flex-shrink:0;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid rgba(0,0,0,.2);border-bottom-right-radius:0;border-bottom-left-radius:0}.modal-footer>*{margin:.25rem}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[data-popper-placement^=right],.bs-tooltip-end{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[data-popper-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[data-popper-placement^=left],.bs-tooltip-start{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:0}.popover{position:absolute;top:0;left:0;z-index:1070;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#4e5d6c;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:0}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#4e5d6c}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#4e5d6c}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#4e5d6c}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid rgba(255,255,255,.075)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#4e5d6c}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:rgba(255,255,255,.075);border-bottom:1px solid rgba(0,0,0,.2);border-top-left-radius:0;border-top-right-radius:0}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#ebebeb}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{-webkit-filter:invert(1) grayscale(100);filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1045;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;max-width:100%;visibility:hidden;background-color:#4e5d6c;background-clip:padding-box;outline:0;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;transition:transform .3s ease-in-out,-webkit-transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin-top:-.5rem;margin-right:-.5rem;margin-bottom:-.5rem}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{-ms-flex-positive:1;flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(0,0,0,.2);-webkit-transform:translateX(-100%);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(0,0,0,.2);-webkit-transform:translateX(100%);transform:translateX(100%)}.offcanvas-top{top:0;right:0;left:0;height:30vh;max-height:100%;border-bottom:1px solid rgba(0,0,0,.2);-webkit-transform:translateY(-100%);transform:translateY(-100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(0,0,0,.2);-webkit-transform:translateY(100%);transform:translateY(100%)}.offcanvas.show{-webkit-transform:none;transform:none}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentColor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{-webkit-animation:placeholder-glow 2s ease-in-out infinite;animation:placeholder-glow 2s ease-in-out infinite}@-webkit-keyframes placeholder-glow{50%{opacity:.2}}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;-webkit-animation:placeholder-wave 2s linear infinite;animation:placeholder-wave 2s linear infinite}@-webkit-keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0;mask-position:-200% 0}}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0;mask-position:-200% 0}}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#4c9be8}.link-primary:focus,.link-primary:hover{color:#3d7cba}.link-secondary{color:#4e5d6c}.link-secondary:focus,.link-secondary:hover{color:#3e4a56}.link-success{color:#5cb85c}.link-success:focus,.link-success:hover{color:#4a934a}.link-info{color:#5bc0de}.link-info:focus,.link-info:hover{color:#499ab2}.link-warning{color:#ffc107}.link-warning:focus,.link-warning:hover{color:#cc9a06}.link-danger{color:#d9534f}.link-danger:focus,.link-danger:hover{color:#ae423f}.link-light{color:#abb6c2}.link-light:focus,.link-light:hover{color:#88929b}.link-dark{color:#20374c}.link-dark:focus,.link-dark:hover{color:#1a2c3d}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:calc(3 / 4 * 100%)}.ratio-16x9{--bs-aspect-ratio:calc(9 / 16 * 100%)}.ratio-21x9{--bs-aspect-ratio:calc(9 / 21 * 100%)}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.hstack{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-ms-flex-align:center;align-items:center;-ms-flex-item-align:stretch;align-self:stretch}.vstack{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;-ms-flex-direction:column;flex-direction:column;-ms-flex-item-align:stretch;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;-ms-flex-item-align:stretch;align-self:stretch;width:1px;min-height:1em;background-color:currentColor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{-webkit-transform:translate(-50%,-50%)!important;transform:translate(-50%,-50%)!important}.translate-middle-x{-webkit-transform:translateX(-50%)!important;transform:translateX(-50%)!important}.translate-middle-y{-webkit-transform:translateY(-50%)!important;transform:translateY(-50%)!important}.border{border:1px solid #dee2e6!important}.border-0{border:0!important}.border-top{border-top:1px solid #dee2e6!important}.border-top-0{border-top:0!important}.border-end{border-right:1px solid #dee2e6!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:1px solid #dee2e6!important}.border-start-0{border-left:0!important}.border-primary{border-color:#4c9be8!important}.border-secondary{border-color:#4e5d6c!important}.border-success{border-color:#5cb85c!important}.border-info{border-color:#5bc0de!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#d9534f!important}.border-light{border-color:#abb6c2!important}.border-dark{border-color:#20374c!important}.border-white{border-color:#fff!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.justify-content-evenly{-ms-flex-pack:space-evenly!important;justify-content:space-evenly!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.order-first{-ms-flex-order:-1!important;order:-1!important}.order-0{-ms-flex-order:0!important;order:0!important}.order-1{-ms-flex-order:1!important;order:1!important}.order-2{-ms-flex-order:2!important;order:2!important}.order-3{-ms-flex-order:3!important;order:3!important}.order-4{-ms-flex-order:4!important;order:4!important}.order-5{-ms-flex-order:5!important;order:5!important}.order-last{-ms-flex-order:6!important;order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:rgba(255,255,255,.4)!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:0!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:0!important}.rounded-2{border-radius:0!important}.rounded-3{border-radius:0!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-top{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-end{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-bottom{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-start{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.justify-content-sm-evenly{-ms-flex-pack:space-evenly!important;justify-content:space-evenly!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.order-sm-first{-ms-flex-order:-1!important;order:-1!important}.order-sm-0{-ms-flex-order:0!important;order:0!important}.order-sm-1{-ms-flex-order:1!important;order:1!important}.order-sm-2{-ms-flex-order:2!important;order:2!important}.order-sm-3{-ms-flex-order:3!important;order:3!important}.order-sm-4{-ms-flex-order:4!important;order:4!important}.order-sm-5{-ms-flex-order:5!important;order:5!important}.order-sm-last{-ms-flex-order:6!important;order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.justify-content-md-evenly{-ms-flex-pack:space-evenly!important;justify-content:space-evenly!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.order-md-first{-ms-flex-order:-1!important;order:-1!important}.order-md-0{-ms-flex-order:0!important;order:0!important}.order-md-1{-ms-flex-order:1!important;order:1!important}.order-md-2{-ms-flex-order:2!important;order:2!important}.order-md-3{-ms-flex-order:3!important;order:3!important}.order-md-4{-ms-flex-order:4!important;order:4!important}.order-md-5{-ms-flex-order:5!important;order:5!important}.order-md-last{-ms-flex-order:6!important;order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.justify-content-lg-evenly{-ms-flex-pack:space-evenly!important;justify-content:space-evenly!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.order-lg-first{-ms-flex-order:-1!important;order:-1!important}.order-lg-0{-ms-flex-order:0!important;order:0!important}.order-lg-1{-ms-flex-order:1!important;order:1!important}.order-lg-2{-ms-flex-order:2!important;order:2!important}.order-lg-3{-ms-flex-order:3!important;order:3!important}.order-lg-4{-ms-flex-order:4!important;order:4!important}.order-lg-5{-ms-flex-order:5!important;order:5!important}.order-lg-last{-ms-flex-order:6!important;order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.justify-content-xl-evenly{-ms-flex-pack:space-evenly!important;justify-content:space-evenly!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.order-xl-first{-ms-flex-order:-1!important;order:-1!important}.order-xl-0{-ms-flex-order:0!important;order:0!important}.order-xl-1{-ms-flex-order:1!important;order:1!important}.order-xl-2{-ms-flex-order:2!important;order:2!important}.order-xl-3{-ms-flex-order:3!important;order:3!important}.order-xl-4{-ms-flex-order:4!important;order:4!important}.order-xl-5{-ms-flex-order:5!important;order:5!important}.order-xl-last{-ms-flex-order:6!important;order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:-ms-flexbox!important;display:flex!important}.d-xxl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xxl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xxl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xxl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xxl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xxl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xxl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xxl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xxl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.flex-xxl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xxl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.justify-content-xxl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xxl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xxl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xxl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xxl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.justify-content-xxl-evenly{-ms-flex-pack:space-evenly!important;justify-content:space-evenly!important}.align-items-xxl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xxl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xxl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xxl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xxl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xxl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xxl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xxl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xxl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xxl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xxl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xxl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xxl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xxl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xxl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xxl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xxl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.order-xxl-first{-ms-flex-order:-1!important;order:-1!important}.order-xxl-0{-ms-flex-order:0!important;order:0!important}.order-xxl-1{-ms-flex-order:1!important;order:1!important}.order-xxl-2{-ms-flex-order:2!important;order:2!important}.order-xxl-3{-ms-flex-order:3!important;order:3!important}.order-xxl-4{-ms-flex-order:4!important;order:4!important}.order-xxl-5{-ms-flex-order:5!important;order:5!important}.order-xxl-last{-ms-flex-order:6!important;order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}.d-print-none{display:none!important}}.btn-primary{background-color:#4c9be8}.btn-secondary{background-color:#4e5d6c}.btn-success{background-color:#5cb85c}.btn-info{background-color:#5bc0de}.btn-warning{background-color:#ffc107}.btn-danger{background-color:#d9534f}.btn-light{background-color:#abb6c2}.btn-dark{background-color:#20374c}.dropdown-menu{font-size:.875rem}.dropdown-header{font-size:.875rem}.blockquote-footer{color:#ebebeb}.table{font-size:.875rem}.table .thead-dark th{color:#fff}.table a:not(.btn){color:#fff;text-decoration:underline}.table .dropdown-menu a{text-decoration:none}.table .text-muted{color:rgba(255,255,255,.4)}.checkbox label,.help-block,.radio label,label{font-size:.875rem}.form-floating label{color:#868e96}.nav-pills .nav-link,.nav-pills .nav-link:hover,.nav-tabs .nav-link,.nav-tabs .nav-link:hover{color:#ebebeb}.nav-pills .nav-link.disabled,.nav-tabs .nav-link.disabled{color:rgba(255,255,255,.4)}.page-link:focus,.page-link:hover{color:#fff;text-decoration:none}.alert{border:none;color:#fff}.alert .alert-link,.alert a{color:#fff;text-decoration:underline}.alert-primary{background-color:#4c9be8}.alert-secondary{background-color:#4e5d6c}.alert-success{background-color:#5cb85c}.alert-info{background-color:#5bc0de}.alert-warning{background-color:#ffc107}.alert-danger{background-color:#d9534f}.alert-light{background-color:#abb6c2}.alert-dark{background-color:#20374c}.badge-info,.badge-warning{color:#fff}.popover-header{border-top-left-radius:0;border-top-right-radius:0}.modal-footer,.modal-header{background-color:rgba(255,255,255,.075)} diff --git a/assets/css/highlight.css b/assets/css/highlight.css deleted file mode 100644 index eac4a78..0000000 --- a/assets/css/highlight.css +++ /dev/null @@ -1,70 +0,0 @@ -.highlight pre { background-color: #404040 } -.highlight .hll { background-color: #404040 } -.highlight .c { color: #999999; font-style: italic } /* Comment */ -.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ -.highlight .g { color: #d0d0d0 } /* Generic */ -.highlight .k { color: #6ab825; font-weight: bold } /* Keyword */ -.highlight .l { color: #d0d0d0 } /* Literal */ -.highlight .n { color: #d0d0d0 } /* Name */ -.highlight .o { color: #d0d0d0 } /* Operator */ -.highlight .x { color: #d0d0d0 } /* Other */ -.highlight .p { color: #d0d0d0 } /* Punctuation */ -.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */ -.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ -.highlight .gd { color: #d22323 } /* Generic.Deleted */ -.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #d22323 } /* Generic.Error */ -.highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #589819 } /* Generic.Inserted */ -.highlight .go { color: #cccccc } /* Generic.Output */ -.highlight .gp { color: #aaaaaa } /* Generic.Prompt */ -.highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ -.highlight .gt { color: #d22323 } /* Generic.Traceback */ -.highlight .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */ -.highlight .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */ -.highlight .ld { color: #d0d0d0 } /* Literal.Date */ -.highlight .m { color: #3677a9 } /* Literal.Number */ -.highlight .s { color: #ed9d13 } /* Literal.String */ -.highlight .na { color: #bbbbbb } /* Name.Attribute */ -.highlight .nb { color: #24909d } /* Name.Builtin */ -.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */ -.highlight .no { color: #40ffff } /* Name.Constant */ -.highlight .nd { color: #ffa500 } /* Name.Decorator */ -.highlight .ni { color: #d0d0d0 } /* Name.Entity */ -.highlight .ne { color: #bbbbbb } /* Name.Exception */ -.highlight .nf { color: #447fcf } /* Name.Function */ -.highlight .nl { color: #d0d0d0 } /* Name.Label */ -.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */ -.highlight .nx { color: #d0d0d0 } /* Name.Other */ -.highlight .py { color: #d0d0d0 } /* Name.Property */ -.highlight .nt { color: #6ab825; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #40ffff } /* Name.Variable */ -.highlight .ow { color: #6ab825; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #666666 } /* Text.Whitespace */ -.highlight .mf { color: #3677a9 } /* Literal.Number.Float */ -.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */ -.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */ -.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */ -.highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */ -.highlight .sc { color: #ed9d13 } /* Literal.String.Char */ -.highlight .sd { color: #ed9d13 } /* Literal.String.Doc */ -.highlight .s2 { color: #ed9d13 } /* Literal.String.Double */ -.highlight .se { color: #ed9d13 } /* Literal.String.Escape */ -.highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */ -.highlight .si { color: #ed9d13 } /* Literal.String.Interpol */ -.highlight .sx { color: #ffa500 } /* Literal.String.Other */ -.highlight .sr { color: #ed9d13 } /* Literal.String.Regex */ -.highlight .s1 { color: #ed9d13 } /* Literal.String.Single */ -.highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */ -.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #40ffff } /* Name.Variable.Class */ -.highlight .vg { color: #40ffff } /* Name.Variable.Global */ -.highlight .vi { color: #40ffff } /* Name.Variable.Instance */ -.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */ diff --git a/assets/css/main.scss b/assets/css/main.scss deleted file mode 100644 index 0bc51b1..0000000 --- a/assets/css/main.scss +++ /dev/null @@ -1,59 +0,0 @@ ---- ---- -@import "bootswatch-superhero.min.css"; -@import "highlight.css"; - -#wrapper { - display: flex; - min-height: calc(100vh - 57px); - flex-direction: row; -} - -#sidebar { - width: 20%; - color:#bbb; - padding: 20px 20px 0 20px; - - .introduction { - margin-bottom: 10px; - - a { - color: white; - } - } - - ul.menu { - width: 100%; - padding: 0; - - li { - width: 100%; - padding: 10px; - border: 1px solid white; - list-style: none; - margin-bottom: 5px; - font-size: 10pt; - - a { - color: inherit; - } - } - } - - p.copyright { - font-size: 10pt; - } -} - -#content { - width: 80%; - padding: 40px 40px 0 40px; - - div.highlight pre { - padding: 5px; - } - - img { - width: 100%; - } -} diff --git a/capitulos/CHAPTER_00.md b/capitulos/CHAPTER_00.md deleted file mode 100644 index 5e846d1..0000000 --- a/capitulos/CHAPTER_00.md +++ /dev/null @@ -1,40 +0,0 @@ -
- -# Introdução - -Se você é um desenvolvedor que sempre sonhou em poder reproduzir o -ambiente de produção em sua máquina ou a aplicação que você desenhou e -desenvolveu poder rodar em produção facilmente, com o mesmo "binário" -que foi utilizado nos momentos de testes\... - -\...Imagine conseguir instalar e testar diversas aplicações rapidamente -e ainda simular um ambiente completo, bem mais leve e inteligente do que -as máquinas virtuais em questão de minutos. - -Se você é um administrador de sistemas que sempre sonhou em não precisar -mais preparar os servidores para suportar milhares de aplicações -diferentes, feitas em linguagens diferentes, com bibliotecas diferentes, -com versões diferentes (ufa!)... - -\...Imagine economizar milhões de horas em instalações de novos -servidores, atualizações de aplicações, *deploys*, acionamentos na -madrugada por conta de serviços que "falharam" e não poderiam ser -executados em outros servidores por incompatibilidades diversas. - -Se você precisa escalar seu ambiente em questão de minutos para suportar -uma demanda que o pegou de surpresa após uma campanha do departamento de -marketing de sua empresa\... - -Se você é um gestor e está preocupado com a fatura do *datacenter* no -final do mês por conta da quantidade de recursos necessários para seu -ambiente funcionar\.... - -E mesmo quando você possui todos os recursos computacionais para -suportar a demanda, se você percebe que na maioria das vezes os seus -recursos estão ociosos e sua equipe está com dificuldades para -equalizá-los\... - -\...Então este livro e o Docker foram feitos para você! Boa leitura e -divirta-se! - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_01.md b/capitulos/CHAPTER_01.md deleted file mode 100644 index ab24ec5..0000000 --- a/capitulos/CHAPTER_01.md +++ /dev/null @@ -1,97 +0,0 @@ -
- -# 1. O que é *container*? - -## 1.1. Então vamos lá, o que é um *container*? - -*Container* é, em português claro, o agrupamento de uma aplicação junto -com suas dependências, que compartilham o *kernel* do sistema -operacional do *host*, ou seja, da máquina (virtual ou física) onde está -rodando. Deu para entender? - -*Containers* são bem similares às máquinas virtuais, porém mais leves e -mais integrados ao sistema operacional da máquina *host*, uma vez que, -como já dissemos, compartilha o seu *kernel*, o que proporciona melhor -desempenho por conta do gerenciamento único dos recursos. - -Na maioria dos casos, a imagem de um *container* é bastante enxuta, -havendo somente o necessário para o funcionamento da aplicação, que, -quando em execução, possui um pequeno *overhead* se comparada à mesma -aplicação rodando nativamente no sistema operacional, grande parte disso -por conta do compartilhamento dos recursos com a máquina *host*. - -Quando estamos utilizando máquinas virtuais, nós emulamos um novo -sistema operacional e virtualizamos todo o seu hardware utilizando mais -recursos da máquina *host*, o que não ocorre quando utilizamos -*containers*, pois os recursos são compartilhados. O ganho óbvio disso é -a capacidade de rodar mais *containers* em um único *host*, se comparado -com a quantidade que se conseguiria com máquinas virtuais. - -A seguir, na figura, podemos notar as diferenças de quando temos -aplicações sendo executadas nativamente, máquinas virtuais e por fim em -*containers*. Repare que não é necessário emular um novo sistema -operacional quando estamos utilizando *containers*, diferentemente das -máquinas virtuais. - -![DIFERENCAS ENTRE MÁQUINA VIRTUAL E CONTAINERS](../media/image3.png) - -Outro ponto interessante na utilização de *containers* é a -portabilidade. Não importa em qual ambiente você criou o seu -*container*, ele irá rodar em qualquer outro que possua, no nosso caso, -o Docker instalado, seja ele no Linux, MacOS ou Windows. Você não -precisa se preocupar com suas dependências, está tudo dentro do -*container*. :D - -O desenvolvedor consegue, na sua própria máquina, criar uma aplicação em -*container* e depois executá-la em um servidor de produção sem nenhum -problema de dependência ou algo do tipo -- nem mesmo o bom e velho -"engraçado, na minha máquina funciona" escapa, hein? - -Lembre-se: na máquina virtual você emula um novo sistema operacional -dentro do sistema operacional do *host*. Já no *container* você emular -somente as aplicações e suas dependências e as torna portáteis. - -## 1.2. E quando começou que eu não vi? - -Apesar de o termo ter se tornado *hype* nos últimos anos, durante -décadas já utilizávamos *containers* em sistemas Unix através do comando -*chroot.* Sim, bem mais simplório, é verdade, pois era apenas uma forma -de isolar o *filesystem*, mas já era o começo! - -Em seguida vieram os *jails* do FreeBSD, que, além do isolamento do -*filesystem*, permitiam também o isolamento de processos, seguidos de -perto pela Sun, que desenvolveu o *Solaris Zones*, mais uma solução -baseada em *containers*, porém somente para sistemas Solaris. - -O grande passo rumo ao cenário que temos hoje foi a criação, pela -Parallels do Virtuozzo, de um painel que permitia o fácil gerenciamento -de *containers* e a disponibilização do *core* do Virtuozzo como *open -source* com o nome de OpenVZ. - -O OpenVZ foi uma ferramenta que ganhou bastante destaque no -gerenciamento de *containers* e ajudou e muito na popularização do VPS -(*Virtual Private Server*) e, consequentemente, na criação de centenas -de empresas de *hosting* espalhadas pelo mundo. O principal ponto -negativo do OpenVZ era a necessidade de aplicar um *patch* no *kernel* -Linux. - -Logo após surgir o OpenVZ, o Google iniciou o desenvolvimento do CGroups -para o *kernel* do Linux e iniciou a utilização de *containers* em seus -*datacenters*. - -Em 2008, desenvolvedores de empresas como Virtuozzo, IBM e o próprio -Google iniciaram o projeto LXC, que trazia consigo o CGroups, -*namespaces* e *chroot* para prover uma completa e estável solução para -a criação e o gerenciamento de *containers*. - -Porém, foi no ano de 2013 que os *containers* conquistaram o -*mainstream*, saíram do *underground* através da utilização massiva -pelas empresas de internet e gigantes de tecnologia e invadiram os -principais eventos de tecnologia ao redor do mundo, com palestras sobre -o sucesso na utilização de *containers* e com o melhor aproveitamento -dos recursos físicos como CPU e memória, maior agilidade no *deployment* -de novas aplicações em fração de segundos e tudo isso com uma facilidade -que impressiona. Amigo, estamos falando do simplesmente sensacional -**Docker**. - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_02.md b/capitulos/CHAPTER_02.md deleted file mode 100644 index 0a5df4c..0000000 --- a/capitulos/CHAPTER_02.md +++ /dev/null @@ -1,406 +0,0 @@ -
- -# 2. O que é o Docker? - -## 2.1. Onde entra o Docker nessa história? - -Tudo começou em 2008, quando Solomon Hykes fundou a dotCloud, empresa -especializada em PaaS com um grande diferencial: o seu -*Platform-as-a-Service* não era atrelado a nenhuma linguagem de -programação específica, como era o caso, por exemplo, da Heroku, que -suportava somente aplicações desenvolvidas em Ruby. - -A grande virada na história da dotCloud ocorreu em março de 2013, quando -decidiram tornar *open source* o *core* de sua plataforma -- assim -nascia o Docker! - -As primeiras versões do Docker nada mais eram do que um *wrapper* do LXC -integrado ao *Union Filesystem*, mas o seu crescimento foi fantástico e -muito rápido, tanto que em seis meses seu GitHub já possuía mais de seis -mil *stars* e mais de 170 pessoas contribuindo para o projeto ao redor -do mundo. - -Com isso, a dotCloud passou a se chamar Docker e a versão 1.0 foi -lançada apenas 15 meses após sua versão 0.1. A versão 1.0 do Docker -trouxe muito mais estabilidade e foi considerada "production ready", -além de trazer o Docker Hub, um repositório público para *containers*. - -Por ser um projeto *open source*, qualquer pessoa pode visualizar o -código e contribuir com melhorias para o Docker. Isso traz maior -transparência e faz com que correções de *bugs* e melhorias aconteçam -bem mais rápido do que seria em um software proprietário com uma equipe -bem menor e poucos cenários de testes. - -Quando o Docker 1.0 foi lançado e anunciado que estava pronto para -produção, empresas como Spotify já o utilizavam em grande escala; logo -AWS e Google começaram a oferecer suporte a Docker em suas nuvens. Outra -gigante a se movimentar foi a Red Hat, que se tornou uma das principais -parceiras do Docker, inclusive o incorporando-o ao *OpenShift*. - -Atualmente, o Docker é oficialmente suportado apenas em máquinas Linux -64 *bits*. Isso significa que seus *containers* também terão que ser um -Linux 64 *bits*, pois lembre que o *container* utiliza o mesmo *kernel* -da máquina *host*. ;) - -Hoje o Docker pode ser executado tranquilamente em outras plataformas -como Windows e MacOS, porém ainda não com a mesma performance e -estabilidade do Docker sendo executado no Linux. Ahhh, o Linux! \<3 \<3 -\<3 - -## 2.2. E esse negócio de camadas? - -### 2.2.1. *Copy-On-Write* (COW) e Docker - -Antes de entender as camadas propriamente ditas, precisamos entender -como um dos principais requisitos para essa coisa acontecer, o -*Copy-On-Write* (ou COW para os íntimos), funciona. Nas palavras do -próprio Jérome Petazzoni: - -*It's a little bit like having a book. You can make notes in that book -if you want, but each time you approach the pen to the page, suddenly -someone shows up and takes the page and makes a xerox copy and hand it -back to you, that's exactly how copy on write works.* - -Em tradução livre, seria como se você tivesse um livro e que fosse -permitido fazer anotações nele caso quisesse, porém, cada vez que você -estivesse prestes a tocar a página com a caneta, de repente alguém -aparecesse, tirasse uma xerox dessa página e entregasse a cópia para -você. É exatamente assim que o *Copy-On-Write* funciona. - -Basicamente, significa que um novo recurso, seja ele um bloco no disco -ou uma área em memória, só é alocado quando for modificado. - -Tá, mas o que isso tudo tem a ver com o Docker? Bom, como você sabe, o -Docker usa um esquema de camadas, ou *layers*, e para montar essas -camadas são usadas técnicas de *Copy-On-Write*. Um *container* é -basicamente uma pilha de camadas compostas por N camadas *read-only* e -uma, a superior, *read-write*. - -## 2.3. *Storage drivers* - -Apesar de um *container* possuir uma camada de escrita, na maior parte -do tempo você não quer escrever dados diretamente nele, por vários -motivos, dentre eles a sua natureza volátil. Em situações onde sua -aplicação gera dados, você vai preferir usar volumes "atachados" ao -*container* e escrever neles (veremos mais à frente como fazer isso). -Porém, em algumas situações é, sim, necessária a escrita local no -*container*, e é aí que o *storage driver* entra na história. *Storage -driver* é o mecanismo utilizado pela *engine* do Docker para ditar a -forma como esses dados serão manipulados no *filesystem* do *container*. -A seguir, os principais *storage drivers* e suas peculiaridades. - -### 2.3.1. AUFS (*Another Union File System*) - -O primeiro *filesystem* disponível para o Docker foi o AUFS, um dos mais -antigos *Copy-On-Write filesystems*, e inicialmente teve que passar por -algumas modificações a fim de melhorar a estabilidade. - -O AUFS funciona no nível de arquivos (não em bloco), e a ideia é ter -múltiplos diretórios (camadas) que ele apresenta para o SO como um ponto -único de montagem. - -Quando você tenta ler um arquivo, a busca é iniciada pela camada -superior, até achar o arquivo ou concluir que ele não existe. Para -escrever em um arquivo, este precisa primeiro ser copiado para a camada -superior (*writable*) -- e, sim, você adivinhou: escrever em arquivos -grandes pode causar certa degradação da performance, já que o arquivo -precisaria ser copiado completamente para a primeira camada, mesmo -quando uma parte bem pequena vai sofrer alteração. - -Já que estamos falando de coisa chata, outra coisa que pode degradar a -sua performance usando AUFS é o fato de que ele procura cada diretório -de um *path* em cada camada do *filesystem* toda vez que você tentar -executar um comando. Por exemplo, se você tem um *path* com cinco -camadas, serão realizadas 25 buscas (*stat()*, uma *system call*). Isso -pode ser bem complicado em aplicações que fazem *load* dinâmico, como os -*apps* Python que importam os .py da vida. - -Outra particularidade é quando algum arquivo é deletado. Quando isso -acontece é criado um *whiteout* para esse arquivo. Em outras palavras, -ele é renomeado para ".wh.arquivo" e fica indisponível para o -*container*, já que, né, não dá para apagar de verdade, pois as outras -camadas são *read-only*. - -### 2.3.2. *Device Mapper* - -*Device Mapper* é um *kernel-based framework* da Red Hat usado para -algumas abstrações, como, por exemplo, o mapeamento de "blocos físicos" -em "blocos lógicos", permitindo técnicas como LVM e RAID. No contexto do -Docker, porém, ele se resume ao "thin provisioning target" ou ao -*storage driver* "devicemapper". Assim que essa coisa de Docker começou -a andar, o pessoal da Red Hat (e toda a galera que usava alguma *distro* -relacionada com Red Hat) se interessou bastante, só que havia um -problema: eles não queriam usar AUFS. Para resolver isso, eles reuniram -uma equipe de engenheiros muito habilidosos que adicionaram suporte ao -*Device Mapper* no Docker. - -Em se tratando de Docker, o *Device Mapper* e o AUFS são bem similares: -a grande diferença entre eles é que, no *Device Mapper*, quando você -precisa escrever no arquivo, a cópia é feita em nível de blocos, que era -um problema lá no AUFS, e com isso você ganha uma granularidade bem -maior. Em teoria, o problema que você tinha quando escrevia um arquivo -grande desaparece. Por padrão, *Device Mapper* escreve em arquivos de -*loopback*, o que deixa as coisas mais lentas, mas agora na versão 1.17+ -você já pode configurá-lo em modo *direct-lvm*, que escreve em blocos e, -em teoria, resolveria esse problema. É um pouco mais chatinho de -configurar, mas é uma solução mais elegante para ambientes em produção. - -Além de AUFS e *Device Mapper*, você também pode usar BRTFS e OverlayFS -como *storage driver*. Por serem tecnologias relativamente jovens, -aprecie com moderação. - -### 2.3.3. OverlayFS e OverlayFS2 - -A bola da vez. Uma versão melhorada do AUFS, o OverlayFS e sua versão -seguinte e oficialmente recomendada pelo Docker, o Overlay2, são ambos -*other union filesystems*, mas dessa vez muito mais eficientes, rápidos -e com uma implementação muito mais simples. - -Por serem *union file systems*, também compartilham da ideia de juntar -vários diretórios em um único ponto de montagem como nosso amigo AUFS, -porém, no caso do OverlayFS, apenas dois diretórios são suportados, o -que não acontece no Overlay2, que tem suporte *multi-layer*. Ambos -suportam *page caching sharing*, ou seja, múltiplos *containers* -acessando o mesmo arquivo dividem a mesma entrada no arquivo de -paginação, o que é um uso mais eficiente de memória. - -Aquele problema antigo do AUFS de ter de copiar todo o arquivo para a -camada de cima para escrever nele ainda persiste, porém no OverlayFS ele -só é copiado uma vez e fica lá para que as outras escritas no mesmo -arquivo possam acontecer mais rápido, então tem uma pequena vantagem. - -Nota-se um consumo excessivo de *inodes* quando se usa OverlayFS. Esse é -um problema resolvido no Overlay2, então sempre que possível busque -usá-lo -- até porque, no geral, tem uma performance superior. Lembrando -que *kernel* 4.0+ é pré-requisito para usar OverlayFS2. - -### 2.3.4. BTRFS - -BTRFS é a geração seguinte de *union filesystem*. Ele é muito mais -*space-efficient*, suporta muitas tecnologias avançadas de *storage* e -já está incluso no *mainline* do *kernel*. O BTRFS, diferentemente do -AUFS, realiza operações a nível de bloco e usa um esquema de *thin -provision* parecido com o do *Device Mapper* e suporta *copy-on-write -snapshots*. Você pode inclusive combinar vários *devices* físicos em um -único BTRFS *filesystem*, algo como um LVM. - -O BTRFS é suportado atualmente na versão CE apenas em distribuições -*debian-like* e na versão EE apenas em SLES (*Suse Linux Enterprise -Server*). - -**IMPORTANTE: alterar o *storage drive* fará com que qualquer -*container* já criado se torne inacessível ao sistema local. Cuidado!** - -## 2.4. Docker Internals - -O Docker utiliza algumas *features* básicas do *kernel* Linux para seu -funcionamento. A seguir temos um diagrama no qual é possível visualizar -os módulos e *features* do *kernel* de que o Docker faz uso: - -![MODULOS E FEATURES DO KERNEL](../media/image5.png) - -## 2.5. *Namespaces* - -*Namespaces* foram adicionados no *kernel* Linux na versão 2.6.24 e são -eles que permitem o isolamento de processos quando estamos utilizando o -Docker. São os responsáveis por fazer com que cada *container* possua -seu próprio *environment*, ou seja, cada *container* terá a sua árvore -de processos, pontos de montagens, etc., fazendo com que um *container* -não interfira na execução de outro. Vamos saber um pouco mais sobre -alguns *namespaces* utilizados pelo Docker. - -### 2.5.1. PID *namespace* - -O PID *namespace* permite que cada *container* tenha seus próprios -identificadores de processos. Isso faz com que o *container* possua um -PID para um processo em execução -- e quando você procurar por esse -processo na máquina *host* o encontrará; porém, com outra identificação, -ou seja, com outro PID. - -A seguir temos o processo "testando.sh" sendo executado no *container*. - -Perceba o PID desse processo na árvore de processos dele: - -```bash -root@c774fa1d6083:/# bash testando.sh & -[1] 7 - -root@c774fa1d6083:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 0 18:06 ? 00:00:00 /bin/bash -root 7 1 0 18:07 ? 00:00:00 bash testando.sh -root 8 7 0 18:07 ? 00:00:00 sleep 60 -root 9 1 0 18:07 ? 00:00:00 ps -ef - -root@c774fa1d6083:/# -``` - -Agora, perceba o PID do mesmo processo exibido através do *host*: - -```bash -root@linuxtips:~# ps -ef | grep testando.sh - -root 2958 2593 0 18:12 pts/2 00:00:00 bash testando.sh -root 2969 2533 0 18:12 pts/0 00:00:00 grep --color=auto testando.sh - -root@linuxtips:~# -``` - -Diferentes, né? Porém, são o mesmo processo. :) - -### 2.5.2. Net *namespace* - -O *Net Namespace* permite que cada *container* possua sua interface de -rede e portas. Para que seja possível a comunicação entre os -*containers*, é necessário criar dois *Net Namespaces* diferentes, um -responsável pela interface do *container* (normalmente utilizamos o -mesmo nome das interfaces convencionais do Linux, por exemplo, a eth0) e -outro responsável por uma interface do *host*, normalmente chamada de -veth\* (veth + um identificador aleatório). Essas duas interfaces estão -*linkadas* através da *bridge* Docker0 no *host*, que permite a -comunicação entre os *containers* através de roteamento de pacotes. - -Conforme falamos, veja as interfaces. Interfaces do *host*: - -```bash -root@linuxtips:~# ip addr - -1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default - link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 - inet 127.0.0.1/8 scope host lo - valid_lft forever preferred_lft forever - inet6 ::1/128 scope host - valid_lft forever preferred_lft forever -2: eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - link/ether 00:1c:42:c7:bd:d8 brd ff:ff:ff:ff:ff:ff - inet 10.211.55.35/24 brd 10.211.55.255 scope global eth1 - valid_lft forever preferred_lft forever - inet6 fdb2:2c26:f4e4:0:21c:42ff:fec7:bdd8/64 scope global dynamic - valid_lft 2591419sec preferred_lft 604219sec - inet6 fe80::21c:42ff:fec7:bdd8/64 scope link - valid_lft forever preferred_lft forever -3: docker0: mtu 1500 qdisc noqueue state UP group default - link/ether 02:42:c7:c1:37:14 brd ff:ff:ff:ff:ff:ff - inet 172.17.0.1/16 scope global docker0 - valid_lft forever preferred_lft forever - inet6 fe80::42:c7ff:fec1:3714/64 scope link - valid_lft forever preferred_lft forever -5: vetha2e1681: mtu 1500 qdisc noqueue master docker0 state UP group default - link/ether 52:99:bc:ab:62:5e brd ff:ff:ff:ff:ff:ff - inet6 fe80::5099:bcff:feab:625e/64 scope link - valid_lft forever preferred_lft forever -root@linuxtips:~# -``` - -Interfaces do *container*: - -```bash -root@6ec75484a5df:/# ip addr - -1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default - link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 - inet 127.0.0.1/8 scope host lo - valid_lft forever preferred_lft forever - inet6 ::1/128 scope host - valid_lft forever preferred_lft forever -6: eth0: mtu 1500 qdisc noqueue state UP group default - link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff - inet 172.17.0.3/16 scope global eth0 - valid_lft forever preferred_lft forever - inet6 fe80::42:acff:fe11:3/64 scope link - valid_lft forever preferred_lft forever - -root@6ec75484a5df:/# -``` - -Conseguiu visualizar as interfaces Docker0 e veth\* do *host*? E a eth0 -do *container*? Sim? *Otémooo*! :D - -### 2.5.3. Mnt *namespace* - -É evolução do *chroot*. Com o *Mnt Namespace* cada *container* pode ser -dono de seu ponto de montagem, bem como de seu sistema de arquivos raiz. -Ele garante que um processo rodando em um sistema de arquivos não -consiga acessar outro sistema de arquivos montado por outro *Mnt -Namespace*. - -### 2.5.4. IPC *namespace* - -Ele provê um SystemV IPC isolado, além de uma fila de mensagens POSIX -própria. - -### 2.5.5. UTS *namespace* - -Responsável por prover o isolamento de *hostname*, nome de domínio, -versão do SO, etc. - -### 2.5.6. User *namespace* - -O mais recente *namespace* adicionado no *kernel* Linux, disponível -desde a versão 3.8. É o responsável por manter o mapa de identificação -de usuários em cada *container*. - -## 2.6. *Cgroups* - -É o *cgroups* o responsável por permitir a limitação da utilização de -recursos do *host* pelos *containers*. Com o *cgroups* você consegue -gerenciar a utilização de CPU, memória, dispositivos, I/O, etc. - -## 2.7. *Netfilter* - -A já conhecida ferramenta *iptables* faz parte de um módulo chamado -*netfilter*. Para que os *containers* consigam se comunicar, o Docker -constrói diversas regras de roteamento através do *iptables*; inclusive -utiliza o NAT, que veremos mais adiante no livro. - -```bash -root@linuxtips:~# iptables -t nat -L -Chain PREROUTING (policy ACCEPT) -target prot opt source destination -DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL - -Chain INPUT (policy ACCEPT) -target prot opt source destination - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -DOCKER all -- anywhere !127.0.0.0/8 ADDRTYPE match dst-type LOCAL - -Chain POSTROUTING (policy ACCEPT) -target prot opt source destination -MASQUERADE all -- 172.17.0.0/16 anywhere - -Chain DOCKER (2 references) -target prot opt source destination -RETURN all -- anywhere anywhere - -root@linuxtips:~# -``` - -## 2.8. Para quem ele é bom? - -O Docker é muito bom para os desenvolvedores, pois com ele você tem -liberdade para escolher a sua linguagem de programação, seu banco de -dados e sua distribuição predileta. Já para os *sysadmins* é melhor -ainda, pois, além da liberdade de escolher a distribuição, não -precisamos preparar o servidor com todas as dependências da aplicação. -Também não precisamos nos preocupar se a máquina é física ou virtual, -pois o Docker suporta ambas. - -A empresa como um todo ganha, com a utilização do Docker, maior -agilidade no processo de desenvolvimento de aplicações, encurtando o -processo de transição entre os ambientes de QA STAGING e PROD, pois é -utilizada a mesma imagem. Traz menos custos com hardware por conta do -melhor gerenciamento e aproveitamento dos recursos, além do *overhead*, -que é bem menor se comparado com outras soluções, como a virtualização. - -Com Docker fica muito mais viável a criação de *microservices* -(microsserviços, a ideia de uma grande aplicação ser quebrada em várias -pequenas partes e estas executarem tarefas específicas), um assunto que -tem ganhado cada vez mais espaço no mundo da tecnologia e que vamos -abordar com mais detalhes no final deste livro. - -Ainda temos diversos outros motivos para utilizar *containers* e que -vamos descobrindo conforme evoluímos com a utilização do Docker. :D - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_03.md b/capitulos/CHAPTER_03.md deleted file mode 100644 index b05f9a4..0000000 --- a/capitulos/CHAPTER_03.md +++ /dev/null @@ -1,151 +0,0 @@ -
- -# 3. Instalando o Docker - -## 3.1. Quero instalar, vamos lá? - -Bom, dado que você já sabe o que é um *container* e o que é o tal do -Docker, chegou a hora de pôr a mão na massa. Vamos instalar o Docker -pela primeira vez! - -O *daemon* do Docker roda nativo em distribuições Linux, e por isso a -instalação em sistemas operacionais que não sejam Linux consiste -basicamente em subir uma VM e rodar o *daemon* de lá. O cliente, no -entanto, pode ser instalado nos principais sistemas operacionais -disponíveis atualmente. - -Para realizar a instalação do Docker em máquinas Linux é bastante -simples. Precisamos somente observar alguns pontos: - -- O Docker não suporta processadores 32 *bits*. - -- O Docker é suportado (*stable*) somente na versão do *kernel* 3.8 ou superior. - -- O *kernel* deve ter suporte aos sistemas de arquivos utilizados pelo Docker, como o AUFS, *Device Mapper*, OverlayFS, etc. - -- O *kernel* deverá ter suporte a *cgroups* e *namespaces*, o que normalmente já vem por *default* habilitado na maioria das *distros*. - -Você também pode acessar a URL: -[https://docs.docker.com/install/](https://docs.docker.com/install/). -Lá é possível aprender a instalar o Docker em diversas distribuições -Linux, nos principais *clouds* e também no MacOS e no Windows. - -Neste livro vamos utilizar a distribuição Ubuntu Linux, porém não muda -nada para outras distribuições. Chega de conversa, vamos lá! - -Primeiro, vamos verificar a versão do *kernel* para saber se ele é -compatível com o Docker: - -```bash -# uname -r -``` - -## 3.2. Instalando no Debian/Centos/Ubuntu/Suse/Fedora - -A instalação do Docker é bastante simples. Você pode optar por -instalá-lo utilizando os pacotes disponíveis para sua *distro* -- por -exemplo, o *apt-get* ou *yum.* - -Nós preferimos fazer a instalação através da execução do *curl* a -seguir, que irá executar um *script* e detectará qual a distribuição que -estamos utilizando, para então adicionar o repositório oficial do Docker -em nosso gerenciador de pacotes, o *rpm* ou *apt*, por exemplo. - -```bash -# curl -fsSL https://get.docker.com/ | sh -``` - -Assim ele sempre buscará a versão mais recente do Docker. :) - -## 3.3. Instalando 'manualmente' no Debian - -Caso você esteja utilizando o Debian e queira realizar a instalação -através dos pacotes disponíveis no repositório, faça: - -```bash -# apt-key adv --keyserver \ - hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D -``` - -Agora vamos criar/editar o arquivo "/etc/apt/sources.list.d/docker.list" -e adicionar o endereço do repositório correspondente à versão do seu -Debian. No nosso caso estamos utilizando a versão Debian 8, também -conhecida como Jessie. - -```bash -# vim /etc/apt/sources.list.d/docker.list # Debian Jessie - -deb https://apt.dockerproject.org/repo debian-jessie main -``` - -Após adicionar a linha anterior, é necessário atualizar a lista de -repositórios executando: - -```bash -# apt-get update -``` - -Após finalizar a atualização da lista de repositórios disponíveis, já -podemos fazer a instalação do Docker. O nome do pacote é "docker-ce". :) - -```bash -# apt-get install docker-ce -``` - -Vamos verificar se o Docker está em execução. Digite na linha de comando -o seguinte: - -```bash -# /etc/init.d/docker status -``` - -Ou: - -```bash -# service docker status - -docker container stop/waiting -``` - -Com isso, podemos verificar se o processo está em execução. Como podemos -notar, o *daemon* do Docker não está em execução, portanto vamos -iniciá-lo. - -```bash -# service docker start -docker container start/running, process 4303 - -# service docker status -docker container start/running, process 4303 -``` - -Perfeito! Agora já temos o Docker instalado e pronto para começar a -brincar com os *containers*. \\o/ - -### 3.3.1. Dica importante - -Por padrão, o *daemon* do Docker faz *bind* em um *socket* Unix, e não -em uma porta TCP. *Sockets* Unix, por sua vez, são de propriedade e de -uso exclusivo do usuário *root* (por isso o Docker sempre é iniciado -como *root*), mas também podem ser acessados através do *sudo* por -outros usuários. - -Para evitar que você tenha que ficar usando *sudo* ao rodar comandos do -Docker, crie um grupo chamado *docker* e adicione o seu usuário a ele. -Pare o serviço e inicie-o novamente. - -Infelizmente, nem tudo são flores. Esse procedimento faz com que o -usuário tenha **os mesmos privilégios do usuário *root*** em operações -relacionadas ao Docker. Mais informações no link: -[https://docs.docker.com/engine/security/](https://docs.docker.com/engine/security/). - -Para criar um grupo no Linux e adicionar um usuário não tem segredo, -basta rodar: - -```bash -$ sudo usermod -aG docker user -``` - -Dica de um milhão de dólares: **user** = **seu usuário**. :D - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_04.md b/capitulos/CHAPTER_04.md deleted file mode 100644 index d82859b..0000000 --- a/capitulos/CHAPTER_04.md +++ /dev/null @@ -1,473 +0,0 @@ -
- -# 4. Executando e administrando *containers* Docker - -## 4.1. Então vamos brincar com esse tal de *container*! - -Como todos sabemos, o Docker utiliza a linha de comando para que você -possa interagir com ele -- basicamente você utiliza o comando "docker". - -Bom, agora que já iniciamos o Docker, vamos rodar nosso primeiro -*container*. - -Como é de costume quando alguém está aprendendo uma nova linguagem de -programação, é bem comum fazer como o primeiro código um ***hello -world*!** - -Apesar de o Docker não ser uma linguagem de programação, vamos utilizar -esse costume com o nosso primeiro exemplo de um *container* em execução. - -O Docker possui uma imagem personalizada de *hello-world* e serve para -que você possa testar a sua instalação e validar se tudo funciona -conforme o esperado. :D - -Para que possamos executar um *container*, utilizamos o parâmetro "run" -do subcomando "container" do comando "docker". Simples, não? :D - -```bash -root@linuxtips:~# docker container run hello-world -Unable to find image 'hello-world:latest' locally -latest: Pulling from library/hello-world -03f4658f8b78: Pull complete a3ed95caeb02: Pull complete -Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7 -Status: Downloaded newer image for hello-world:latest - -Hello from Docker. -This message shows that your installation appears to be working correctly. - 1. The Docker client contacted the Docker daemon. - 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. - (amd64) - 3. The Docker daemon created a new container from that image which runs the - executable that produces the output you are currently reading. - 4. The Docker daemon streamed that output to the Docker client, which sent it - to your terminal. - - -To try something more ambitious, you can run an Ubuntu container with: - $ docker run -it ubuntu bash - -Share images, automate workflows, and more with a free Docker Hub account: - https://hub.docker.com - -For more examples and ideas, visit: - https://docs.docker.com/userguide/ - -root@linuxtips:~# -``` - -No exemplo anterior, estamos executando um *container* utilizando a -imagem personalizada do *hello-world*. - -Apesar de ser uma tarefa simples, quando você executou o comando "docker -container run hello-world" foram necessárias quatro etapas para sua -conclusão, vamos ver quais: - -1. O comando "docker" se comunica com o *daemon* do Docker informando a ação desejada. - -2. O *daemon* do Docker verifica se a imagem "hello-world" existe em seu *host*; caso ainda não, o Docker faz o *download* da imagem diretamente do Docker Hub. - -3. O *daemon* do Docker cria um novo *container* utilizando a imagem que você acabou de baixar. - -4. O *daemon* do Docker envia a saída para o comando "docker", que imprime a mensagem em seu terminal. - -Viu? É simples como voar! :) - -Muito bem, agora que nós já temos uma imagem em nosso *host*, como eu -faço para visualizá-la? - -Muito simples, basta digitar o seguinte comando: - -```bash -root@linuxtips:~# docker image ls -REPOSITORY TAG IMAGE ID CREATED SIZE -hello-world latest 690ed74de00f 5 months 960 B - -root@linuxtips:~# -``` - -Como você pode notar no código, a saída traz cinco colunas: - -- **REPOSITORY** -- O nome da imagem. - -- **TAG** -- A versão da imagem. - -- **IMAGE ID** -- Identificação da imagem. - -- **CREATED** -- Quando ela foi criada. - -- **SIZE** -- Tamanho da imagem. - -Quando executamos o comando "docker container run hello-world", ele -criou o *container*, imprimiu a mensagem na tela e depois o *container* -foi finalizado automaticamente, ou seja, ele executou sua tarefa, que -era exibir a mensagem, e depois foi finalizado. - -Para ter certeza de que ele realmente foi finalizado, digite: - -```bash -root@linuxtips:~# docker container ls - -CONTAINER ID IMAGE COMMAND CREATED STATUS PORT NAMES - -root@linuxtips:~# -``` - -Com o "docker container ls", você consegue visualizar todos os -*containers* em execução e ainda obter os detalhes sobre eles. A saída -do "docker container ls" é dividida em sete colunas; vamos conhecer o -que elas nos dizem: - -- **CONTAINER ID** -- Identificação única do *container.* - -- **IMAGE** -- A imagem que foi utilizada para a execução do *container.* - -- **COMMAND** -- O comando em execução. - -- **CREATED** -- Quando ele foi criado. - -- **STATUS** -- O seu status atual. - -- **PORTS** -- A porta do *container* e do *host* que esse *container* utiliza. - -- **NAMES** -- O nome do *container.* - -Uma opção interessante do "docker container ls" é o parâmetro "-a". - -```bash -root@linuxtips:~# docker container ls -a - -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -6e45cf509282 hello-world "/hello" 4 seconds Exited(0) tracted_ardinghelli - -root@linuxtips:~# -``` - -Com a opção "-a" você consegue visualizar não somente os *containers* em -execução, como também *containers* que estão parados ou que foram -finalizados. - -## 4.2. Legal, quero mais! - -Agora que vimos como criar um simples *container*, bem como visualizar -as imagens e *containers* que estão em nosso *host*, vamos criar um -novo, porém conhecendo três parâmetros que irão trazer maior -flexibilidade no uso e na administração de nossos *containers*. Estou -falando dos parâmetros "-t", "-i" e "-d". - -- **-t** -- Disponibiliza um TTY (console) para o nosso *container*. - -- **-i** -- Mantém o STDIN aberto mesmo que você não esteja conectado no *container.* - -- **-d** -- Faz com que o *container* rode como um *daemon*, ou seja, sem a interatividade que os outros dois parâmetros nos fornecem. - -Com isso temos dois modos de execução de nossos *containers*: modo -interativo ou *daemonizando* o *container*. - -### 4.2.1. Modo interativo - -Na maior parte das vezes você vai subir um *container* a partir de uma -imagem que já está pronta, toda ajustadinha. Porém, há alguns casos em -que você precisa interagir com o seu *container* -- isso pode acontecer, -por exemplo, na hora de montar a sua imagem personalizada. - -Nesse caso, usar o modo interativo é a melhor opção. Para isso, basta -passar os parâmetros "-ti" ao comando "docker container run". - -### 4.2.2. *Daemonizando* o *container* - -Utilizando o parâmetro "-d" do comando "docker container run", é -possível *daemonizar* o *container*, fazendo com que o *container* seja -executado como um processo *daemon*. - -Isso é ideal quando nós já possuímos um *container* que não iremos -acessar (via *shell*) para realizar ajustes. Imagine uma imagem já com a -sua aplicação e tudo que precisa configurado; você irá subir o -*container* e somente irá consumir o serviço entregue por sua aplicação. -Se for uma aplicação *web*, basta acessar no *browser* passando o IP e a -porta onde o serviço é disponibilizado no *container*. Sensacional, não? - -Ou seja, se você quer subir um *container* para ser utilizado como uma -máquina Linux convencional com *shell* e que necessita de alguma -configuração ou ajuste, utilize o modo interativo, ou seja, os -parâmetros "-ti". - -Agora, se você já tem o *container* configurado, com sua aplicação e -todas as dependências sanadas, não tem a necessidade de usar o modo -interativo -- nesse caso utilizamos o parâmetro "-d", ou seja, o -*container daemonizado*. Vamos acessar somente os serviços que ele -provê, simples assim. :D - -## 4.3. Entendi, agora vamos praticar um pouco? - -Perfeito. Vamos iniciar um novo *container* utilizando dois desses novos -parâmetros que aprendemos. - -Para o nosso exemplo, vamos subir um *container* do Centos 7: - -```bash -root@linuxtips:~# docker container run -ti centos:7 -Unable to find image 'centos:7' locally -7: Pulling from library/centos -a3ed95caeb02: Pull complete 196355c4b639: Pull complete -Digest: sha256:3cdc0670fe9130ab3741b126cfac6d7720492dd2c1c8ae033dcd77d32855bab2 -Status: Downloaded newer image for centos:7 - -[root@3c975fb7fbb5 /]# -``` - -Como a imagem não existia em nosso *host*, ele começou a baixar do -Docker Hub, porém, caso a imagem já estivesse em nosso *host*, ele a -utilizaria, não sendo necessário o *download*. - -Perceba que mudou o seu *prompt* (variável \$PS1), pois agora você já -está dentro do *container*. Para provar que estamos dentro do nosso -*container* Centos, execute o seguinte comando: - -```bash -[root@3c975fb7fbb5 /]# cat /etc/redhat-release -CentOS Linux release 7.2.1511 (Core) - -[root@3c975fb7fbb5 /]# -``` - -O arquivo "/etc/redhat-release" indica qual a versão do Centos que -estamos utilizando, ou seja, estamos realmente em nosso *container* -Centos 7. :D - -## 4.4. Tá, agora quero sair\... - -Idealmente, no *container* vai haver apenas um processo rodando. No -nosso caso, como estamos interagindo (opção "-ti"), é o processo do -*bash*; logo, você não pode utilizar o comando "exit" para sair do -console, pois dessa forma esse único processo para de rodar e seu -*container* morre. Caso queira sair do *container* e mantê-lo em -execução, é necessário sair com o seguinte atalho do teclado: - -**mantenha o botão Ctrl pressionado + p + q** - -Assim, você sairá do *container* e ele continuará em execução. Para -confirmar se o *container* continua em execução, faça: - -```bash -root@linuxtips:~# docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -3c975fb7fbb5 centos:7 "/bin/bash" 2 minutes Up 2 minutes angry_wescoff - -root@linuxtips:~# -``` - -## 4.5. Posso voltar ao *container*? - -Deixamos o nosso *container* em execução e agora queremos acessá-lo -novamente. Como podemos fazer? - -Simples! Basta digitar o seguinte comando: - -```bash -root@linuxtips:~# docker container attach -``` - -O parâmetro "attach" do comando "docker container" possibilita nos -conectarmos a um *container* em execução. Para isso, basta passar como -parâmetro o "CONTAINER ID", que você consegue através da saída do -"docker ps", conforme mostramos no exemplo anterior. - -## 4.6. Continuando com a brincadeira\... - -Existe a possibilidade de criar um *container,* porém não o executar -imediatamente. Quando fazemos o uso do parâmetro "create" do comando -"docker container", ele apenas cria o *container*, não o inicializando, -conforme notamos no exemplo a seguir: - -```bash -root@linuxtips:~# docker container create -ti ubuntu -Unable to find image 'ubuntu:latest' locally -latest: Pulling from library/ubuntu -5a132a7e7af1: Pull complete -fd2731e4c50c: Pull complete -28a2f68d1120: Pull complete -a3ed95caeb02: Pull complete -Digest:sha256:4e85ebe01d056b43955250bbac22bdb8734271122e3c78d21e55ee235fc6802d -Status: Downloaded newer image for ubuntu:latest3e63e65db85a6e36950959dc6bdc00279e2208a335580c478e01723819de9467 - -root@linuxtips:~# -``` - -Perceba que quando você digita "docker container ls" ele não traz o -*container* recém-criado, afinal a saída do "docker container ls" -somente traz os *containers* em execução. Para visualizar o *container* -recém-criado foi necessário utilizar o parâmetro "-a". - -```bash -root@linuxtips:~# docker container ls -a -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -3e63e65db85a ubuntu "/bin/bash" 18 seconds ago Created elo_visves - -root@linuxtips:~# -``` - -Para que o nosso *container* recém-criado seja executado, basta utilizar -o "docker container start \[CONTAINER ID\]", conforme segue: - -```bash -root@linuxtips:~# docker container start [CONTAINER ID] -root@linuxtips:~# docker container attach [CONTAINER ID] - -root@b422f04df14c:/# -``` - -Verificando se estamos realmente utilizando o *container* do Ubuntu: - -```bash -root@b422f04df14c:/# cat /etc/issue -Ubuntu 18.04 LTS \n \l - -root@b422f04df14c:/# -``` - -Lembrando que para sair do *container* e mantê-lo em execução é -necessário utilizar o atalho: **Ctrl + p + q**. - -## 4.7. Subindo e matando *containers*... - -Caso eu queira parar um *container* em execução, basta utilizar o -parâmetro "stop" seguido do "CONTAINER ID": - -```bash -# docker container stop [CONTAINER ID] -``` - -Verificando se o *container* continua em execução: - -```bash -# docker container ls -``` - -Lembrando que para visualizar os *containers* que não estão em execução -é necessário utilizar o parâmetro "-a". - -Para colocar novamente em execução um *container* que está parado, é -necessário utilizar o parâmetro "start" do comando "docker container" -seguido do "CONTAINER ID": - -```bash -# docker container start [CONTAINER ID] -``` - -Da mesma forma como podemos utilizar o *stop/start* para -desligar/iniciar um *container*, podemos também fazer o uso do -"restart", como notamos a seguir: - -```bash -# docker container restart [CONTAINER ID] -``` - -Para pausar um *container*, execute: - -```bash -# docker container pause [CONTAINER ID] -``` - -E verifique o status do *container*: - -```bash -root@linuxtips:~# docker container ls -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -b34f4987bdce ubuntu "/bin/bash" 12 seconds ago Up 11 seconds (Paused) drunk_turi - -root@linuxtips:~# -``` - -Para "despausar" o *container*: -```bash -# docker container unpause [CONTAINER ID] -``` -## 4.8. Visualizando o consumo de recursos pelo *container*\... - -Caso você queira visualizar informações referentes ao consumo de -recursos pelo *container*, também é bastante simples: basta utilizar o -parâmetro "stats" para verificar o consumo de CPU, memória e rede pelo -*container* em tempo real. - -```bash -# docker container stats [CONTAINER ID] - -CONTAINER CPU% MEM USAGE/LIMIT MEM % NET I/O BLOCK I/O PIDS -b34f4987bdce 0.00% 503.8kB/2.094GB 0.02% 648B/648B 0B/0B 2 -``` - -Para sair, pressione **Ctrl + C.** - -Para visualizar todos os *containers* de uma só vez, basta não -especificar o \[CONTAINER ID\],conforme segue: - -```bash -# docker container stats -``` - -Agora, se você quer visualizar quais processos estão em execução em -determinado *container*, utilize o parâmetro "top". Com ele você -consegue informações sobre os processos em execução, como, por exemplo, -UID e o PID do processo. - -```bash -# docker container top [CONTAINER ID] -UID PID PPID C STIME TTY TIME COMMAND -root 10656 4303 0 20:24 pts/3 00:00:00 /bin/bash -``` - -Para verificar os *logs* de um determinado *container*, utilize o -parâmetro "logs", simples assim. :D - -```bash -# docker container logs [CONTAINER ID] -``` - -Lembre-se: ele exibe o STDOUT, a saída padrão. Ou seja, normalmente você -irá visualizar o histórico de mensagens que aparecerem em primeiro plano -durante a execução do *container*. - -Para exibir os *logs* de forma dinâmica, ou seja, conforme aparecem -novas mensagens ele atualiza a saída no terminal utilizamos a opção "-f" - -```bash -# docker container logs -f [CONTAINER ID] -``` - -. Com isso seu terminal ficará travado, apenas escutando o *log*, e -qualquer nova entrada ele exibirá na tela. Saída parecida com o "tail --f" no Linux. Lembre-se, utilize o ctrl+c para cancelar a exibição dos -logs. - -## 4.9. Cansei de brincar de *container*, quero removê-lo! - -Bem, remover um *container* é mais simples ainda do que sua criação. -Quando removemos um *container*, a imagem que foi utilizada para a sua -criação permanece no *host*; somente o *container* é apagado. - -```bash -root@linuxtips:~# docker container rm b34f4987bdce - -Failed to remove container (b34f4987bdce): Error response from daemon: -Conflict, You cannot remove a running container. Stop the container -before attempting removal or use -f - -root@linuxtips:~# -``` - -Perceba que, quando você tentou remover o *container*, ele retornou um -erro dizendo que falhou em remover, pois o *container* estava em -execução. Ele inclusive recomenda que você pare o *container* antes de -removê-lo ou então utilize a opção "-f", forçando assim sua remoção. - -```bash -root@linuxtips:~# docker container rm -f b34f4987bdce -b34f4987bdce - -root@linuxtips:~# -``` - -Para confirmar a remoção do *container*, utilize o comando "docker -container ls -a". - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_05.md b/capitulos/CHAPTER_05.md deleted file mode 100644 index c15c4bd..0000000 --- a/capitulos/CHAPTER_05.md +++ /dev/null @@ -1,184 +0,0 @@ -
- -# 5. Configurando CPU e memória para os meus *containers* - -Vamos imaginar que você precise subir quatro *containers* para um -projeto novo. Esses *containers* possuem as seguintes características: - -- Dois *web* *servers*. - -- Dois DB MySQL. - -Evidentemente, por se tratar de serviços diferentes, na maioria dos -casos possuem características de consumo de recursos, como CPU e -memória, diferentes um do outro. - -- *Web server* -- 0,5 CPU \| 128 MB de memória - -- DB MySQL -- 1 CPU \| 256 MB de memória - -E agora, como fazemos? :( - -Por padrão, quando você executa um *container* sem especificar a -quantidade de recursos que ele irá utilizar, ele sobe sem um controle, -podendo inclusive impactar o *host* onde está sendo executado. - -Portanto, é muito importante limitar a utilização de recursos de seus -*containers*, visando um melhor aproveitamento de seus recursos -computacionais, como veremos agora. :) - -## 5.1. Especificando a quantidade de memória - -Primeiro, vamos executar um *container* para realizarmos o nosso -exemplo. - -```bash -root@linuxtips:~# docker container run -ti --name teste debian -``` - -Agora vamos visualizar a quantidade de memória que está configurada para -esse *container*. Uma forma fácil é utilizar a saída do comando "docker -container inspect": - -```bash -root@linuxtips:~# docker container inspect teste | grep -i mem - "CpusetMems": "", - "KernelMemory": 0, - "Memory": 0, - "MemoryReservation": 0, - "MemorySwap": 0, - "MemorySwappiness": -1, -``` - -Como percebemos, os valores correspondentes à memória estão zerados, ou -seja, sem nenhum limite estabelecido. - -Vamos agora subir um novo *container*, porém passando os valores para -que utilize 512 MB de memória: - -```bash -root@linuxtips:~# docker container run -ti -m 512M --name novo_container debian -``` - -Utilizamos o parâmetro "-m" para especificar a quantidade de memória que -desejamos disponibilizar ao *container*. Vamos utilizar o "docker -container inspect" novamente para verificar se a nossa configuração -funcionou: - -```bash -root@linuxtips:~# docker container inspect novo_container | grep -i mem - "CpusetMems": "", - "KernelMemory": 0, - "Memory": 536870912, - "MemoryReservation": 0, - "MemorySwap": -1, - "MemorySwappiness": -1, -``` - -Muito bom, parece que deu certo! - -Podemos ver no campo "Memory" o valor utilizado na criação do -*container*. Vale ressaltar que o valor exibido é em *bytes*. - -Quando você utiliza o parâmetro "-m" ou "\--memory", você está passando -o máximo de memória que o *container* utilizará do *host*. - -## 5.2. Especificando a quantidade de CPU - -Para que você consiga limitar a quantidade de CPUs que os *containers* -irão consumir, basta utilizar o parâmetro "\--cpu". Com ele é possível -dizer a quantidade de CPUs que você deseja disponibilizar para -determinado *container*. Por exemplo, se utilizarmos "\--cpus=0.5" -estamos dizendo ao Docker para limitar o consumo pelo *container* em -meio CPU. Fácil, não? - -```bash -# docker container run --cpus=0.5 --name teste1 nginx -``` - -Com o comando anterior, estamos subindo um *container* utilizando a -imagem do Nginx -- até aqui nenhuma novidade, certo? Porém, agora -passamos o parâmetro "\--cpus=0.5" falando para o Docker que esse -*container* poderá utilizar no máximo 0,5 CPU, ou seja, metade de 1 -*core*. :D Simples como voar. - -Para verificar, vamos utilizar o comando "docker container inspect": - -```bash -root@linuxtips:~# docker container inspect teste1 | grep -i cpu - "CpuShares": 0, - "NanoCpus": 500000000, - "CpuPeriod": 0, - "CpuQuota": 0, - "CpusetCpus": "", - "CpusetMems": "", -``` - -O campo "NanoCpus" traz a informação que configuramos. :) - -Simples, fácil e rápido! - -## 5.3. Eu consigo alterar CPU e memória dos meus *containers* em execução? - -Sim! \\o/ - -Com o lançamento da versão 1.10 do Docker, temos o comando "docker -update", que permite alterar as configurações referentes a CPU, memória -e I/O com o *container* em execução de forma muito simples! Isso é -fantástico! - -Como exemplo, iremos subir um *container* e também alterar as -informações referentes a memória e CPU: - -```bash -root@linuxtips:~# docker container run -ti --cpus=4 -m 512m --name teste1 nginx - -root@linuxtips:~# docker container inspect teste1 | grep -i cpu - "CpuShares": 0, - "NanoCpus": 4000000000, - "CpuPeriod": 0, - "CpuQuota": 0, - "CpusetCpus": "", - "CpusetMems": "", - -root@linuxtips:~# docker container inspect teste1 | grep -i mem - "CpusetMems": "", - "KernelMemory": 0, - "Memory": 536870912, - "MemoryReservation": 0, - "MemorySwap": -1, - "MemorySwappiness": -1, -``` - -Agora, vamos alterar os valores de limite de CPU e memória: - -```bash -root@linuxtips:~# docker container update -m 256m --cpus=1 teste1 -teste1 - -root@linuxtips:~# docker container inspect teste1 | grep -i cpu - "CpuShares": 0, - "NanoCpus": 1000000000, - "CpuPeriod": 0, - "CpuQuota": 0, - "CpusetCpus": "", - "CpusetMems": "", - -root@linuxtips:~# docker container inspect teste1 | grep -i mem - "CpusetMems": "", - "KernelMemory": 0, - "Memory": 268435456, - "MemoryReservation": 0, - "MemorySwap": -1, - "MemorySwappiness": -1, -``` - -Funcionou? SIMMM! - -Assim, com os *containers* em execução, mudamos as informações -referentes à memória e ao CPU! - -Existem outros parâmetros do "docker container update". Para verificar a -lista completa, digite "docker update \--help". - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_06.md b/capitulos/CHAPTER_06.md deleted file mode 100644 index e5e3d21..0000000 --- a/capitulos/CHAPTER_06.md +++ /dev/null @@ -1,73 +0,0 @@ -
- -# 6. Meu primeiro e tosco *dockerfile*\... - -Tudo que nós fizemos até agora foi escrever na linha de comando, o que é -OK para aprender. Porém, principalmente nos dias de hoje, não dá para -viver mais sem automatizar as coisas -- se você, assim como nós, adora -automatizar tudo que for possível, vai gostar bastante desse assunto. - -O *dockerfile* nada mais é do que um arquivo onde você determina todos -os detalhes do seu *container*, como, por exemplo, a imagem que você vai -utilizar, aplicativos que necessitam ser instalados, comandos a serem -executados, os volumes que serão montados, etc., etc., etc.! - -É um *makefile* para criação de *containers*, e nele você passa todas as -instruções para a criação do seu *container*. - -Vamos ver como isso funciona na prática? - -Primeira coisa: vamos criar um diretório onde deixaremos o nosso arquivo -*dockerfile*, somente para ficar organizado. :D - -Depois basta criar o *dockerfile* conforme exemplo a seguir: - -```bash -# mkdir /root/primeiro_dockerfile -# cd /root/primeiro_dockerfile -# vim Dockerfile -``` - -Vamos adicionar as instruções que queremos para essa imagem de -*container* que iremos criar: - -```Dockerfile -FROM debian - -RUN /bin/echo "HELLO DOCKER" -``` - -Apenas isso por enquanto. Salve e saia do *vim*. - -Agora vamos rodar o comando "docker build" para fazer a criação dessa -imagem de *container* utilizando o *dockerfile* criado. - -```bash -root@linuxtips:~/primeiro_dockerfile# docker build -t tosko:1.0 . -Sending build context to Docker daemon 2.048 kB -Step 1/2 : FROM debian -latest: Pulling from library/debian -fdd5d7827f33: Pull complete -a3ed95caeb02: Pull complete -Digest: sha256:e7d38b3517548a1c71e41bffe9c8ae6d6d29546ce46bf62159837aad072c90aa -Status: Downloaded newer image for debian:latest - ---> f50f9524513f -Step 2/2 : RUN /bin/echo "HELLO DOCKER" - ---> Running in df60a0644bed -HELLO DOCKER - ---> fd3af97a8940 -Removing intermediate container df60a0644bed -Successfully built fd3af97a8940 -Successfully tagged tosko:1.0 - -root@linuxtips:~/primeiro_dockerfile# -``` - -Veja que usamos o diretório corrente, representado pelo caractere ".", -para indicar o *path* do meu arquivo *dockerfile*, mas você não precisa -necessariamente estar no mesmo diretório, basta passar o *path* do -diretório onde o arquivo se encontra. - -**Lembre apenas que é o *path* do diretório e não do arquivo.** - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_07.md b/capitulos/CHAPTER_07.md deleted file mode 100644 index 5cb3a32..0000000 --- a/capitulos/CHAPTER_07.md +++ /dev/null @@ -1,377 +0,0 @@ -
- -# 7. Entendendo volumes - -## 7.1. Introdução a volumes no Docker - -Bom, volumes nada mais são que diretórios externos ao *container*, que -são montados diretamente nele, e dessa forma *bypassam* seu -*filesystem*, ou seja, não seguem aquele padrão de camadas que falamos. -Decepcionei você? Que bom, sinal de que é bem simples e você não vai ter -problemas para entender. :) - -A principal função do volume é persistir os dados. Diferentemente do -*filesystem* do *container,* que é volátil e toda informação escrita -nele é perdida quando o *container* morre, quando você escreve em um -volume aquele dado continua lá, independentemente do estado do -*container*. - -Existem algumas particularidades entre os volumes e *containers* que -valem a pena ser mencionadas: - -- O volume é inicializado quando o *container* é criado. - -- Caso ocorra de já haver dados no diretório em que você está montando como volume, ou seja, se o diretório já existe e está "populado" na imagem base, aqueles dados serão copiados para o volume. - -- Um volume pode ser reusado e compartilhado entre *containers*. - -- Alterações em um volume são feitas diretamente no volume. - -- Alterações em um volume não irão com a imagem quando você fizer uma cópia ou *snapshot* de um *container*. - -- Volumes continuam a existir mesmo se você deletar o *container*. - -Dito isso, chega de papo. Vamos aprender a adicionar um volume em um -*container*. - -Primeiro, vamos ver como funciona da maneira antiga, que ainda é -suportada, porém não é elegante. :) - -Essa maneira é muito utilizada quando se quer montar um diretório -específico do *host* dentro do *container*. Isso é ruim quando estamos -trabalhando em *cluster*, uma vez que teríamos que garantir esse -diretório criado em todos os *hosts* do *cluster*. Não seria legal. - -Porém, podemos aprender como funciona e utilizar em algum momento, caso -se faça necessário. Para evitar erros, primeiro crie o diretório -"/volume" na sua máquina. - -```bash -root@linuxtips:~# mkdir /volume -root@linuxtips:~# docker container run -ti --mount type=bind,src=/volume,dst=/volume ubuntu -root@7db02e999bf2:/# df -h - -Filesystem Size Used Avail Use% Mounted on -none 13G 6.8G 5.3G 57% / -tmpfs 999M 0 999M 0% /dev -tmpfs 999M 0 999M 0% /sys/fs/cgroup -/dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /volume -shm 64M 0 64M 0% /dev/shm - -root@7db02e999bf2:/# ls -bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var volume - -root@7db02e999bf2:/# -``` - -No exemplo anterior, conhecemos um novo parâmetro do comando "docker -container run", o "\--mount". - -O parâmetro "\--mount" é o responsável por indicar o volume, que em -nosso exemplo é o "/volume", e onde ele será montado no *container*. -Perceba que, quando passamos o parâmetro "\--mount -type=bind,src=/volume,dst=/volume", o Docker montou esse diretório no -*container*, porém sem nenhum conteúdo. - -Podemos também montar um volume no *container linkando-o* com um -diretório do *host* já com algum conteúdo. Para exemplificar, vamos -compartilhar o diretório "/root/primeiro\_container", que utilizamos -para guardar o nosso primeiro *dockerfile*, e montá-lo no *container* em -um volume chamado "/volume" da seguinte forma: - -```bash -# docker container run -ti --mount type=bind,src=/root/primeiro_container,dst=/volume ubuntu - -root@3d372a410ea2:/# df -h -Filesystem Size Used Avail Use% Mounted on -none 13G 6.8G 5.3G 57% / -tmpfs 999M 0 999M 0% /dev -tmpfs 999M 0 999M 0% /sys/fs/cgroup -/dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /volume -shm 64M 0 64M 0% /dev/shm - -root@3d372a410ea2:/# -``` - -Com isso, estamos montando o diretório "/root/primeiro\_dockerfile" do -*host* dentro do *container* com o nome de "/volume". - -No *container*: - -```bash -root@3d372a410ea2:/# ls /volume/ -Dockerfile - -root@3d372a410ea2:/# -``` - -No *host*: - -```bash -root@linuxtips:~# ls /root/primeiro_dockerfile/ -Dockerfile - -root@linuxtips:~# -``` - -Caso eu queira deixar o volume no *container* apenas como *read-only,* é -possível. Basta passar o parâmetro "ro" após o destino onde será montado -o volume: - -```bash -# docker container run -ti --mount type=bind,src=/root/primeiro_container,dst=/volume,ro ubuntu -root@8d7863b1d9af:/# df -h - -Filesystem Size Used Avail Use% Mounted on -none 13G 6.8G 5.3G 57% / -tmpfs 999M 0 999M 0% /dev -tmpfs 999M 0 999M 0% /sys/fs/cgroup -/dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /volume -shm 64M 0 64M 0% /dev/shm - -root@8d7863b1d9af:/# cd /volume/ -root@8d7863b1d9af:/volume# ls -Dockerfile - -root@8d7863b1d9af:/volume# mkdir teste -mkdir: cannot create directory 'teste': Read-only file system - -root@8d7863b1d9af:/volume# -``` - -Assim como é possível montar um diretório como volume, também é possível -montar um arquivo: - -```bash -# docker container run -ti --mount type=bind,src=/root/primeiro_container/Dockerfile,dst=/Dockerfile ubuntu - -root@df0e3e58280a:/# df -h - -Filesystem Size Used Avail Use% Mounted on -none 13G 6.8G 5.3G 57% / -tmpfs 999M 0 999M 0% /dev -tmpfs 999M 0 999M 0% /sys/fs/cgroup -/dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /Dockerfile -shm 64M 0 64M 0% /dev/shm - -root@df0e3e58280a:/# cat Dockerfile -FROM debian -RUN /bin/echo "HELLO DOCKER" - -root@df0e3e58280a:/# -``` - -Isso faz com que o arquivo "/root/primeiro\_dockerfile/Dockerfile" seja -montado em "/Dockerfile" no *container*. - -## 7.2. Criando volumes - -Agora vamos criar os volumes da maneira mais elegante e atual. Hoje -temos a possibilidade de realizar o gerenciamento de volumes de maneira -muito simples e inteligente. - -Sempre que criamos um volume, ele cria um diretório com o mesmo nome -dentro de "/var/lib/docker/volumes/". - -No exemplo a seguir, o volume "giropops" seria então criado em -"/var/lib/docker/volumes/giropops"; com isso, todos os arquivos -disponíveis nesse diretório também estariam disponíveis no local -indicado no *container*. Vamos aos exemplos! :D - -É possível fazer a criação de volumes e toda a sua administração através -do comando: - -```bash -# docker volume create giropops -``` - -É possível removê-lo através do comando: - -```bash -# docker volume rm giropops -``` - -Para verificar detalhes sobre esse volume: - -```bash -# docker volume inspect giropops -``` - -Para remover os volumes que não estão sendo utilizados (use com extrema -moderação! :D): - -```bash -# docker volume prune -``` - -Para que você possa montar o volume criado em algum -*container*/*service*, basta executar o seguinte comando: - -```bash -# docker container run -d --mount type=volume,source=giropops,destination=/var/opa nginx -``` - -Onde: - -- **\--mount** -- Comando utilizado para montar volumes. - -- **type=volume** -- Indica que o tipo é "volume". Ainda existe o tipo "bind", onde, em vez de indicar um volume, você indicaria um diretório como *source*. - -- **source=giropops** -- Qual o volume que pretendo montar. - -- **destination=/var/opa** -- Onde no *container* montarei esse volume. - -Simples como voar, não? - -## 7.3. Localizando volumes - -Caso você queira obter a localização do seu volume, é simples. Mas para -isso você precisa conhecer o comando "docker volume inspect". - -Com o "docker volume inspect" você consegue obter detalhes do seu -*container*, como, por exemplo, detalhes do volume. - -A saída do comando "docker volume inspect" retorna mais informação do -que somente o *path* do diretório no *host*. Vamos usar a opção -"\--format" ou "-f" para filtrar a saída do "inspect". - -```bash -docker volume inspect --format '{{ .Mountpoint }}' giropops -/var/lib/docker/volumes/giropopos/_data -``` - -## 7.3. Criando e montando um *data-only container* - -Uma opção bastante interessante em relação aos volumes diz respeito ao -*data-only container*, cuja principal função é prover volumes para -outros *containers*. Lembra do NFS *server* e do Samba? Ambos -centralizavam diretórios com a finalidade de compartilhar entre outros -servidores. Pois bem, o *data-only container* tem a mesma finalidade: -prover volumes a outros *containers*. - -Um dos grandes baratos do Docker é a portabilidade. Um *container* -criado no seu *laptop* deve ser portátil a ponto de rodar em qualquer -outro ambiente que utilize o Docker, em todos os cantos do universo! - -Sendo assim, o que acontece se eu criar um ambiente em Docker que diz -para os *containers* montarem um diretório do *host* local? Depende. -Depende de como está esse tal *host* local. Perguntas como "o diretório -existe?" "as permissões estão ajustadas?", entre outras mais, definirão -o sucesso na execução dos *containers*, o que foge completamente do -escopo do Docker. - -Vamos ver como funciona isso na prática! :) - -Para o nosso exemplo, primeiro vamos criar um *container* chamado -"dbdados", com um volume chamado "/data", que guardará os dados de um -banco PostgreSQL. - -Para que possamos criar um *container* especificando um nome para ele, -utilizamos o parâmetro "\--name", conforme veremos no exemplo a seguir: - -```bash -# docker container create -v /data --name dbdados centos -``` - -Com isso, apenas criamos o *container* e especificamos um volume para -ele, mas ainda não o iniciamos. - -Sabemos que no *container* o volume se encontra montado em "/data". -Porém, qual a localização desse volume no *host*? - -Lembra do "docker inspect"? Vamos utilizá-lo novamente: - -```bash -root@linuxtips:~# docker inspect -f {{.Mounts}} dbdados - -[{46255137fe3f6d5f593e9ba9aaaf570b2f8b5c870f587c2fb34f29b79f97c30c /var/lib/docker/volumes/46255137fe3f6d5f593e9ba9aaaf570b2f8b5c870f587c2fb34f29b79f97c30c/_data /data local true }] -``` - -Perceba que agora utilizamos o nome do *container* em vez do "CONTAINER -ID". Totalmente possível e muito mais intuitivo. - -Quando executamos o "docker inspect", ele nos retornou o caminho do -nosso volume. Vamos ver se existe algum conteúdo dentro dele: - -```bash -root@linuxtips:~# ls \ - /var/lib/docker/volumes/46255137fe3f6d5f593e9ba9aaaf570b2f8b5c870f587c2fb34f29b79f97c30c/_data -``` - -Como vimos, o diretório ainda não possui conteúdo. - -Agora vamos criar os *containers* que rodarão o PostgreSQL utilizando o -volume "/data" do *container* "dbdados" para guardar os dados. - -Para que possamos fazer o exemplo, precisamos conhecer mais dois -parâmetros superimportantes: - -- **\--volumes-from** -- É utilizado quando queremos montar um volume disponibilizado por outro *container*. - -- **-e** -- É utilizado para informar variáveis de ambiente para o *container*. No exemplo, estamos passando as variáveis de ambiente do PostgreSQL. - -Pronto, agora estamos preparados! Vamos criar os *containers* com o -PostgreSQL: - -```bash -# docker run -d -p 5432:5432 --name pgsql1 --volumes-from dbdados \ - -e POSTGRESQL_USER=docker -e POSTGRESQL_PASS=docker \ - -e POSTGRESQL_DB=docker kamui/postgresql - -# docker run -d -p 5433:5432 --name pgsql2 --volumes-from dbdados \ - -e POSTGRESQL_USER=docker -e POSTGRESQL_PASS=docker \ - -e POSTGRESQL_DB=docker kamui/postgresql -``` - -Para verificar os dois *containers* com o PostgreSQL em execução, -utilize o "docker container ls". - -Pronto, agora temos os dois *containers* com PostgreSQL em execução! -Será que já temos algum dado no volume "/data" do *container* "dbdados"? - -Vamos verificar novamente no *host* se o volume agora possui algum dado: - -```bash -root@linuxtips:~# ls /var/lib/docker/volumes/46255137fe3f6d5f593e9ba9aaaf570b2f8b5c870f587c2fb34f29b79f97c30c/_data - -base pg_clog pg_ident.conf pg_notify pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION postgresql.conf postmaster.pid server.key global pg_hba.conf pg_multixact pg_serial pg_stat pg_subtrans pg_twophase pg_xlog postmaster.opts server.crt - -root@linuxtips:~# -``` - -Sensacional! Como percebemos, os dois *containers* do PostgreSQL estão -escrevendo seus dados no volume "/data" do *container* "dbdados". Chega -a ser lacrimejante! :D - -## 7.4. Sempre é bom um *backup*\... - - -Outra coisa bem bacana é a possibilidade de fazer *backups* dos seus -*containers* de dados de forma muito simples e rápida. - -Digamos que você queira fazer o *backup* do diretório "/data" do -*container* "dbdados" que nós criamos há pouco; como faríamos? - -```bash -root@linuxtips:~# cd backup/ -root@linuxtips:~/backup# docker run -ti --volumes-from dbdados -v $(pwd):/backup debian tar -cvf /backup/backup.tar /data -``` - -Quando executamos o comando anterior, é criado um novo *container* -montando o(s) volume(s) do *container* "dbdados" (que no caso é o -"/data", lembra?). Além disso, será montado o diretório corrente do -*host* no volume "/backup" do *container*, e em seguida será executado o -comando do *tar* para empacotar o diretório "/data" dentro do diretório -"/backup". Bem simples, né? - -```bash -root@linuxtips:~/backup# ls -backup.tar -root@linuxtips:~/backup# -``` - -Lembrando que os volumes são sempre criados dentro de -"/var/lib/docker/volumes". Caso queira fazer o *backup* de todos os -volumes, basta tratar esse diretório em suas rotinas de *backup*. ;) - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_08.md b/capitulos/CHAPTER_08.md deleted file mode 100644 index 9fc27cf..0000000 --- a/capitulos/CHAPTER_08.md +++ /dev/null @@ -1,578 +0,0 @@ -
- -# 8. Criando e gerenciando imagens - -## 8.1. Agora eu quero criar minha imagem, posso? - -Claro que pode! - -E mais, vamos aprender de duas formas simples e intuitivas. - -Uma das coisas mais interessantes do Docker é a possibilidade de usar -imagens criadas por outras pessoas ao redor do mundo através de algum -*registry* como o Docker Hub. Isso agiliza muito a sua vida, ainda mais -quando você precisa apenas testar uma determinada tecnologia. O POC -(*Proof of Concept* -- em português, prova de conceito) se torna muito -mais ágil, fazendo com que você consiga testar diversas ferramentas no -mesmo tempo em que levaria para testar somente uma sem o Docker. - -Entretanto, em determinados momentos precisamos criar a nossa própria -imagem do zero, ou então modificar uma imagem criada por terceiros e -salvar essas alterações em uma nova imagem. - -Agora vamos ver os dois casos: como montar uma distribuição praticamente -do zero utilizando somente instruções através do *dockerfile* e outra -realizando modificações em uma imagem já existente e salvando em uma -imagem nova. - -## 8.2. Vamos começar do começo então, *dockerfile*! - -Vamos montar a nossa primeira imagem utilizando como roteiro de criação -um *dockerfile*. Você verá o quanto é simples a criação de um -*dockerfile* bem completo e prático. :) - -Para começar, vamos criar um diretório chamado "/root/Dockerfiles". - -```bash -# mkdir /root/Dockerfiles -``` - -Agora começaremos a criação do nosso *dockerfile*, nosso mapa de criação -da imagem. Para que possamos organizá-lo melhor, vamos criar um -diretório chamado "apache", onde guardaremos esse nosso primeiro -exemplo: - -```bash -# cd /root/Dockerfiles/ -# mkdir apache -``` - -Por enquanto, vamos apenas criar um arquivo chamado "Dockerfile" e -adicionar o conteúdo conforme exemplo a seguir: - -```bash -# cd apache -# vim Dockerfile -``` - -```Dockerfile -FROM debian - -RUN apt-get update && apt-get install -y apache2 && apt-get clean - -ENV APACHE_LOCK_DIR="/var/lock" - -ENV APACHE_PID_FILE="/var/run/apache2.pid" - -ENV APACHE_RUN_USER="www-data" - -ENV APACHE_RUN_GROUP="www-data" - -ENV APACHE_LOG_DIR="/var/log/apache2" - -LABEL description="Webserver" - -VOLUME /var/www/html/ - -EXPOSE 80 -``` - -Muito bom! Agora que você já adicionou as informações conforme o -exemplo, vamos entender cada seção utilizada nesse nosso primeiro -*dockerfile*: - -- **FROM** -- Indica a imagem a servir como base. - -- **RUN** -- Lista de comandos que deseja executar na criação da imagem. - -- **ENV** -- Define variáveis de ambiente. - -- **LABEL** -- Adiciona *metadata* à imagem, como descrição, versão, etc. - -- **VOLUME** -- Define um volume a ser montado no *container.* - -Após a criação do arquivo, vamos *buildar* (construir a nossa imagem) da -seguinte forma: - -```bash -# docker build . -``` - -Lembre-se: você deverá estar no diretório onde está o seu *dockerfile*. - -Todos os passos que definimos em nosso *dockerfile* serão realizados, -como a instalação dos pacotes solicitados e todas as demais tarefas. - -Successfully built 53de2cee9e71 - -Muito bem! Como podemos notar na última linha da saída do "docker -build", a imagem foi criada com sucesso! :D - -Vamos executar o "docker image ls" para ver se está tudo certo com a -nossa primeira imagem! - -```bash -root@linuxtips:~/Dockerfile/apache# docker image ls -REPOSITORY TAG IMAGE ID CREATED SIZE - 53de2cee9e71 2 minutes ago 193.4 MB -``` - -A nossa imagem foi criada! Porém, temos um problema. :/ - -A imagem foi criada e está totalmente funcional, mas, quando a -*buildamos*, não passamos o parâmetro "-t", que é o responsável por -adicionar uma *tag* ("nome:versão") à imagem. - -Vamos executar novamente o *build*, porém passando o parâmetro '-t', -conforme o exemplo a seguir: - -```bash -# docker build -t linuxtips/apache:1.0 . -``` - -Agora vamos ver se realmente a imagem foi criada, adicionando um nome e -uma versão a ela: - -```bash -root@linuxtips:~/Dockerfile/apache# docker image ls -REPOSITORY TAG IMAGE ID CREATED SIZE -linuxtips/apache 1.0 53de2cee9e71 5 minutes ago 193.4 MB -``` - -Maravilha! Funcionou conforme esperávamos! - -Vamos executar um *container* utilizando nossa imagem como base: - -```bash -# docker container run -ti linuxtips/apache:1.0 -``` - -Agora já estamos no *container*. Vamos verificar se o Apache2 está em -execução. Se ainda não estiver, vamos iniciá-lo e verificar se a porta -80 está "LISTEN". - -```bash -root@70dd36fe2d3b:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 1 21:33 ? 00:00:00 /bin/bash -root 6 1 0 21:33 ? 00:00:00 ps -ef - -root@70dd36fe2d3b:/# /etc/init.d/apache2 start -[....] Starting Apache httpd web server: apache2AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message -. ok - -root@70dd36fe2d3b:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 0 21:33 ? 00:00:00 /bin/bash -root 30 1 0 21:33 ? 00:00:00 /usr/sbin/apache2 -k start -www-data 33 30 0 21:33 ? 00:00:00 /usr/sbin/apache2 -k start -www-data 34 30 0 21:33 ? 00:00:00 /usr/sbin/apache2 -k start -root 109 1 0 21:33 ? 00:00:00 ps -ef - -root@70dd36fe2d3b:/# ss -atn -State Recv-Q Send-Q Local Address:Port Peer Address:Port -LISTEN 0 128 :::80 :::* - -root@70dd36fe2d3b:/# ip addr show eth0 -50: eth0: mtu 1500 qdisc noqueue state UP group default - link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff - inet 172.17.0.4/16 scope global eth0 - valid_lft forever preferred_lft forever - inet6 fe80::42:acff:fe11:4/64 scope link - valid_lft forever preferred_lft forever - -root@70dd36fe2d3b:/# -``` - -No código anterior é possível observar o IP do *container* na saída do -"ip addr". Vamos testar a comunicação com o *container* a partir do -*host*. - -No *host*, digite: - -```bash -# curl -``` - -O "curl" retornou a página de boas-vindas do Apache2, ou seja, tudo está -funcionando muito bem e o Apache2, respondendo conforme esperado! - -Maaaaaasssss, não é interessante que eu tenha que entrar no *container* -para subir o meu processo do Apache. Todo *container* deve executar seu -processo em primeiro plano e esse processo deve subir de forma -automática e não com um *serumaninho* acessando o *container* e subindo -o serviço. Vimos antes somente como primeiro exemplo, agora vamos -aperfeiçoá-lo e deixá-lo como deve estar! :D - -A primeira coisa é deixar o nosso *dockerfile* como segue: - -```bash -# vim Dockerfile -``` - -```Dockerfile -FROM debian - -RUN apt-get update && apt-get install -y apache2 && apt-get clean - -ENV APACHE_LOCK_DIR="/var/lock" - -ENV APACHE_PID_FILE="/var/run/apache2/apache2.pid" - -ENV APACHE_RUN_USER="www-data" - -ENV APACHE_RUN_DIR="/var/run/apache2" - -ENV APACHE_RUN_GROUP="www-data" - -ENV APACHE_LOG_DIR="/var/log/apache2" - -LABEL description="Webserver" - -VOLUME /var/www/html/ - -EXPOSE 80 - -ENTRYPOINT ["/usr/sbin/apachectl"] - -CMD ["-D", "FOREGROUND"] -``` - -Perceba que agora nós adicionamos mais duas opções: o ENTRYPOINT e o -CMD! - -Ficou curioso sobre o que eles fazem? Então 'bora aprender muito mais -opções possíveis de serem adicionadas em um *dockerfile*! - -## 8.3. Bora aprender um pouco mais sobre *dockerfile*? - -Vamos agora aprender um pouco mais sobre as opções que podemos utilizar -quando estamos criando um *dockerfile*: - -- **ADD** -- Copia novos arquivos, diretórios, arquivos TAR ou arquivos remotos e os adiciona ao *filesystem* do *container*. - -- **CMD** -- Executa um comando. Diferentemente do RUN, que executa o comando no momento em que está "buildando" a imagem, o CMD irá fazê-lo somente quando o container é iniciado. - -- **LABEL** -- Adiciona metadados à imagem, como versão, descrição e fabricante. - -- **COPY** -- Copia novos arquivos e diretórios e os adiciona ao *filesystem* do *container*. - -- **ENTRYPOINT** -- Permite que você configure um *container* para rodar um executável. Quando esse executável for finalizado, o *container* também será. - -- **ENV** -- Informa variáveis de ambiente ao *container*. - -- **EXPOSE** -- Informa qual porta o *container* estará ouvindo. - -- **FROM** -- Indica qual imagem será utilizada como base. Ela precisa ser a primeira linha do *dockerfile*. - -- **MAINTAINER** -- Autor da imagem. - -- **RUN** -- Executa qualquer comando em uma nova camada no topo da imagem e "commita" as alterações. Essas alterações você poderá utilizar nas próximas instruções de seu *dockerfile*. - -- **USER** -- Determina qual usuário será utilizado na imagem. Por *default* é o *root*. - -- **VOLUME** -- Permite a criação de um ponto de montagem no *container*. - -- **WORKDIR** -- Responsável por mudar do diretório "/" (raiz) para o especificado nele. - -Um detalhe superimportante de mencionar é que quando estamos trabalhando -com o ENTRYPOINT e o CMD dentro do mesmo *dockerfile*, o CMD somente -aceita parâmetros do ENTRYPOINT, conforme nosso exemplo do *dockerfile* -anterior: - -```Dockerfile -ENTRYPOINT ["/usr/sbin/apachectl"] - -CMD ["-D", "FOREGROUND"] -``` - -Onde: - -- **"/usr/sbin/apachectl"** -- Esse é o comando. - -- **"-D", "FOREGROUND"** -- Esse é o argumento, o parâmetro. - -No *shell*, por exemplo, a execução ficaria assim: - -```bash -# /usr/sbin/apachectl -D FOREGROUND -``` - -Ou seja, assim você está iniciando o Apache passando a instrução para -que ele seja iniciado em primeiro plano, como deve ser. :D - -Para maiores detalhes sobre como criar imagens, veja essa apresentação -criada pelo Jeferson: -[https://www.slideshare.net/jfnredes/images-deep-dive](https://www.slideshare.net/jfnredes/images-deep-dive). - -## 8.4. *Multi-stage* - -Um importante e recente recurso adicionado ao *dockerfile* visa -facilitar a vida de quem pretende criar imagens de *containers* de forma -efetiva. Esse cara é o *multi-stage*! - -O *multi-stage* nada mais é do que a possibilidade de você criar uma -espécie de *pipeline* em nosso *dockerfile*, podendo inclusive ter duas -entradas FROM. - -Esse recurso é muito utilizado quando queremos, por exemplo, compilar a -nossa aplicação em um *container* e executá-la, porém não queremos ter -aquela quantidade enorme de pacotes instalados em nossos *containers* -necessários sempre quando se quer compilar códigos de alguma linguagem, -como C, Java ou Golang. - -Vamos a um exemplo para que possamos entender melhor como isso funciona! - -Para isso, preparei uma *app* escrita em Golang superavançada para o -nosso teste: - -```bash -# vim goapp.go -``` - -```golang -package main - -import "fmt" - -func main() { - - fmt.Println("GIROPOPS STRIGUS GIRUS - LINUXTIPS") - -} -``` - -Achou que seria algo avançado? Impossível, fomos nós que fizemos. :D - -Bem, agora vamos criar um *dockerfile* para criar a nossa imagem e assim -executar a nossa *app*. - -```bash -# vim Dockerfile -``` - -```Dockerfile -FROM golang - -WORKDIR /app - -ADD . /app - -RUN go build -o goapp - -ENTRYPOINT ./goapp -``` - -Pronto! Agora vamos realizar o *build*. - -```bash -# docker build -t goapp:1.0 . -``` - -Listando a nossa imagem: - -```bash -# docker image ls | grep goapp -goapp 1.0 50451808b384 11 seconds ago 781MB -``` - -Agora vamos executá-la e ver a nossa fantástica *app* em execução: - -```bash -# docker container run -ti goapp:1.0 -GIROPOPS STRIGUS GIRUS -- LINUXTIPS -``` - -Pronto! Nossa *app* e nossa imagem estão funcionando! Sucesso! - -Porém, podemos melhorar muita coisa se começarmos a utilizar o nosso -poderoso recurso, o *multi-stage*! - -Vamos refazer o nosso *dockerfile* utilizando o *multi-stage*, entender -como ele funciona e a diferença entre as duas imagens. - -Vamos deixar nosso *dockerfile* dessa maneira: - -```bash -# vim Dockerfile -``` - -```Dockerfile -FROM golang AS buildando - -ADD . /src - -WORKDIR /src - -RUN go build -o goapp - -FROM alpine:3.1 - -WORKDIR /app - -COPY --from=buildando /src/goapp /app - -ENTRYPOINT ./goapp -``` - -Perceba que agora nós temos duas entradas FROM, o que não era possível -antes do *multi-stage*. Mas por que isso? - -O que está acontecendo é que agora temos o *dockerfile* dividido em duas -seções. Cada entrada FROM define o início de um bloco, uma etapa. - -Então, em nosso primeiro bloco temos: - -- **FROM golang AS buildando** -- Estamos utilizando a imagem do Golang para criação da imagem de *container*, e aqui estamos apelidando esse bloco como "buildando". - -- **ADD . /src** -- Adicionando o código de nossa *app* dentro do *container* no diretório "/src". - -- **WORKDIR /src** -- Definindo que o diretório de trabalho é o "/src", ou seja, quando o *container* iniciar, estaremos nesse diretório. - -- **RUN go build -o goapp** -- Vamos executar o *build* de nossa *app* Golang. - -Já no segundo bloco temos o seguinte: - -- **FROM alpine:3.1** -- Iniciando o segundo bloco e utilizando a imagem do Alpine para criação da imagem de *container*. - -- **WORKDIR /app** -- Definindo que o diretório de trabalho é o "/app", ou seja, quando o *container* iniciar, estaremos nesse diretório. - -- **COPY \--from=buildando /src/goapp /app** -- Aqui está a mágica: vamos copiar do bloco chamado "buildando" um arquivo dentro de "/src/goapp" para o diretório "/app" do *container* que estamos tratando nesse bloco, ou seja, copiamos o binário que foi compilado no bloco anterior e o trouxemos para esse. - -- **ENTRYPOINT ./goapp** -- Aqui vamos executar a nossa sensacional *app*. :) - -Agora que já entendemos todas as linhas do nosso novo *dockerfile*, -'bora realizar o *build* dele. - -```bash -# docker build -t goapp_multistage:1.0 . -``` - -Vamos executar a nossa imagem para ver se está tudo funcionando: - -```bash -# docker container run -ti goapp_multistage:1.0 -GIROPOPS STRIGUS GIRUS - LINUXTIPS -``` - -Será que existe diferença de tamanho entre elas? Vamos conferir: - -```bash -# docker image ls | grep goapp -goapp_multistage 1.0 dfe57485b7f0 22 seconds ago 7.07MB -goapp 1.0 50451808b384 15 minutes ago 781MB -``` - -A diferença de tamanho é brutal, pois em nossa primeira imagem -precisamos ter um monte de pacotes para que o *build* da *app* Golang -ocorra. Já em nossa segunda imagem também utilizamos a imagem do Golang -e todos os seus pacotes para *buildar* a nossa *app*, porém descartamos -a primeira imagem e somente copiamos o binário para o segundo bloco, -onde estamos utilizando a imagem do Alpine, que é superenxuta. - -Ou seja, utilizamos o primeiro bloco para compilar a nossa *app* e o -segundo bloco somente para executá-la. Simples assim, simples como voar! -:D - -## 8.5. Vamos customizar uma imagem base agora? - -Vamos agora criar uma nova imagem, porém sem utilizar o *dockerfile*. -Vamos executar um *container* com uma imagem base, realizar as -modificações que desejarmos e depois salvar esse *container* como uma -nova imagem! - -Simples, rápido e fácil! - -Bem, primeiro precisamos criar um *container*. Vamos dessa vez utilizar -um *container* Debian, somente para variar. :D - -```bash -root@linuxtips:~# docker container run -ti debian:8 /bin/bash -root@0b7e6f606aae:/# -``` - -Agora vamos fazer as alterações que desejamos. Vamos fazer o mesmo que -fizemos quando montamos nossa primeira imagem com o *dockerfile*, ou -seja, fazer a instalação do Apache2. :D - -```bash -root@0b7e6f606aae:/# apt-get update && apt-get install -y apache2 && apt-get clean -``` - -Agora que já instalamos o Apache2, vamos sair do *container* para que -possamos *commitar* a nossa imagem com base nesse *container* em -execução. - -Lembre-se de que para sair do *container* e deixá-lo ainda em execução é -necessário pressionar **Ctrl + p + q**. ;) - -```bash -# docker container ls -# docker commit -m "meu container" CONTAINERID -# docker image ls -REPOSITORY TAG IMAGE ID CREATED SIZE - fd131aedd43a 4 seconds ago 193.4 MB -``` - -Repare que nossa imagem ficou com o "\" em seu nome e "TAG". Para -que possamos ajustar e dar um nome e uma versão à nossa imagem, vamos -usar o comando "docker tag", conforme mostramos a seguir: - -```bash -# docker tag IMAGEID linuxtips/apache_2:1.0 -REPOSITORY TAG IMAGE ID CREATED SIZE -linuxtips/apache_2 1.0 fd131aedd43a 2 minutes ago 193.4 MB -``` - -Agora sim!!! Temos a nossa imagem criada e nome e versão especificados. - -Vamos iniciar um *container* utilizando a imagem que acabamos de criar: - -```bash -# docker container run -ti linuxtips/apache_2:1.0 /bin/bash -``` - -Vamos subir o Apache2 e testar a comunicação do *container*: - -```bash -root@57094ec894ce:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 0 21:48 ? 00:00:00 /bin/bash -root 6 1 0 21:48 ? 00:00:00 ps -ef - -root@57094ec894ce:/# /etc/init.d/apache2 start -[....] Starting web server: apache2AH00558: apache2: Could notreliably determine the server's fully qualified domain name, using 172.17.0.6. Set the 'ServerName' directive globally to suppress this message -. ok - -root@70dd36fe2d3b:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 0 21:43 ? 00:00:00 /bin/bash -root 30 1 0 21:44 ? 00:00:00 /usr/sbin/apache2 -k start -www-data 33 30 0 21:44 ? 00:00:00 /usr/sbin/apache2 -k start -www-data 34 30 0 21:44 ? 00:00:00 /usr/sbin/apache2 -k start -root 111 1 0 21:44 ? 00:00:00 ps -ef - -root@70dd36fe2d3b:/# ss -atn -State Recv-Q Send-Q Local Address:Port Peer Address:Port -LISTEN 0 128 :::80 :::* - -root@57094ec894ce:/# ip addr show eth0 -54: eth0: mtu 1500 qdisc noqueue state UP group default - link/ether 02:42:ac:11:00:06 brd ff:ff:ff:ff:ff:ff - inet 172.17.0.6/16 scope global eth0 - valid_lft forever preferred_lft forever - inet6 fe80::42:acff:fe11:6/64 scope link - valid_lft forever preferred_lft forever -``` - -Boaaa! Agora já temos o Apache2 em execução. Vamos sair do *container* e -testar a comunicação com o Apache2 a partir do *host*: - -```bash -# curl -``` - -Ele retornará a página de boas-vindas do Apache2! Tudo funcionando -conforme esperado! - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_09.md b/capitulos/CHAPTER_09.md deleted file mode 100644 index a6c482b..0000000 --- a/capitulos/CHAPTER_09.md +++ /dev/null @@ -1,406 +0,0 @@ -
- -# 9. Compartilhando as imagens - -Bem, já aprendemos como criar uma imagem de *container*, seja via -*dockerfile* ou através da modificação de um *container*, e conhecemos -alguns comandos interessantes, como o "docker build" e o "docker -commit". - -Agora vamos aprender a compartilhar essas imagens, seja em um *registry* -local ou então no *registry* do próprio Docker Hub. - -## 9.1. O que é o Docker Hub? - -Docker Hub é um repositório público e privado de imagens que -disponibiliza diversos recursos, como, por exemplo, sistema de -autenticação, *build* automático de imagens, gerenciamento de usuários e -departamentos de sua organização, entre outras funcionalidades. - -Pessoas e empresas se juntam, criam seus *containers* seguindo as -melhores práticas, testam tudo direitinho e depois disponibilizam lá -para você usar sem ter nenhum trabalho. Isso é uma mão na roda -gigantesca, uma vez que você não vai ter que perder tempo instalando -coisas. Você também pode usá-lo para aprender como configurar -determinado serviço. Para isso, basta ir no Docker Hub e procurar; -provavelmente alguém já criou um *container* que você poderá usar pelo -menos de base! - -Apesar dessa facilidade de encontrar coisas prontas, provavelmente você -não vai querer baixar da internet, mesmo que do *registry* do próprio -Docker (sério), e subir no seu ambiente de produção algo que você não -tem certeza de como funciona, o que é, etc. - -Para resolver esse problema o Docker disponibiliza algumas -funcionalidades, como o comando "docker image inspect", que já vimos -antes, quando falávamos de volumes, lembra? Naquele momento usamos a -*flag* "-f" e especificamos um campo de pesquisa, pois o intuito era -mostrar somente a parte que estava sendo discutida naquele capítulo. Mas -o "docker image inspect" vai muito além disso; sem passar o "-f" ele vai -retornar todas as informações contidas naquela imagem, desde a imagem -base que foi utilizada até pontos de montagem, configurações, enfim, -muita coisa. Teste aí: - -```bash -root@linuxtips:~# docker image inspect debian -[ - { - "Id": "sha256:f50f9524513f5356d952965dc97c7e831b02bb6ea0619da9bfc1997e4b9781b7", - "RepoTags": [ - "debian:8", - "debian:latest" - ], - "RepoDigests": [], - "Parent": "", - "Comment": "", - "Created": "2016-03-01T18:51:14.143360029Z", - "Container": "557177343b434b6797c19805d49c37728a4445d2610a6647c27055fbe4ec3451", - "ContainerConfig": { - "Hostname": "e5c68db50333", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": false, - "AttachStderr": false, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": null, - "Cmd": [ - "/bin/sh", - "-c", - "#(nop) CMD ["/bin/bash"]" - ], - "Image": "d8bd0657b25f17eef81a3d52b53da5bda4de0cf5cca3dcafec277634ae4b38fb", - "Volumes": null, - "WorkingDir": "", - "Entrypoint": null, - "OnBuild": null, - "Labels": {} - }, - "DockerVersion": "1.9.1", - "Author": "", - "Config": { - "Hostname": "e5c68db50333", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": false, - "AttachStderr": false, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": null, - "Cmd": [ - "/bin/bash" - ], - "Image": "d8bd0657b25f17eef81a3d52b53da5bda4de0cf5cca3dcafec277634ae4b38fb", - "Volumes": null, - "WorkingDir": "", - "Entrypoint": null, - "OnBuild": null, - "Labels": {} - }, - "Architecture": "amd64", - "Os": "linux", - "Size": 125110803, - "VirtualSize": 125110803, - "GraphDriver": { - "Name": "aufs", - "Data": null - } - } -] - -root@linuxtips:~# -``` - -Às vezes será disponibilizado junto com a imagem o seu respectivo -*dockerfile* e aí fica bem mais fácil: basta ler esse arquivo para saber -exatamente como ela foi criada. :) - -Um comando bastante interessante, que nos faz entender como uma imagem é -dividida em camadas (e, principalmente, o que foi feito em cada camada), -é o "docker history". - -```bash -root@linuxtips:~# docker history linuxtips/apache:1.0 - -IMAGE CREATED CREATED BY SIZE COMMENT -4862def18dfd 36 minutes ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B -06210ac863da 36 minutes ago /bin/sh -c #(nop) VOLUME [/var/www/html/] 0 B -fed9b6bc7ad9 36 minutes ago /bin/sh -c #(nop) LABEL description=Webserver 0 B -68f6e8de3df3 36 minutes ago /bin/sh -c #(nop) ENV APACHE_LOG_DIR=/var/log 0 B -1a129e753d1e 36 minutes ago /bin/sh -c #(nop) ENV APACHE_RUN_GROUP=www-da 0 B -f0f9d7be7c70 36 minutes ago /bin/sh -c #(nop) ENV APACHE_RUN_USER=www-dat 0 B -3dafea4a403a 36 minutes ago /bin/sh -c #(nop) ENV APACHE_PID_FILE=/var/ru 0 B -f31eb176ecc8 36 minutes ago /bin/sh -c #(nop) ENV APACHE_LOCK_DIR=/var/lo 0 B -0bbefd91da05 36 minutes ago /bin/sh -c apt-get update && apt-get install 68.29 MB -f50f9524513f 12 days ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B - 12 days ago /bin/sh -c #(nop) ADD file:b5393172fb513d 125.1MB - -root@linuxtips:~# -``` - -Perceba que as primeiras linhas da saída do comando anterior são -referentes às informações que pedimos para adicionar à imagem no -*dockerfile*. As demais camadas são originais da imagem que pegamos do -Docker Hub através da instrução "FROM". - -Existe também um site chamado "ImageLayers": ele faz exatamente a mesma -coisa que o "docker history", mas você não precisa baixar a imagem -- e, -bom, é *web*. O ImageLayers pode ser acessado em: -[https://imagelayers.io/](https://imagelayers.io/). - -O Docker Hub, como já falamos, tem muitos componentes, dentre eles o -responsável pelo repositório de imagens: o *registry*. - -É possível utilizar um *registry* local em vez de um na nuvem, como o -Docker Hub ou outros *registries* que são facilmente encontrados na -internet. Falaremos disso com detalhes mais à frente. :P - -Para que você possa utilizar o Docker Hub para gerenciar as suas -imagens, é necessário criar uma conta. - -## 9.2. Vamos criar uma conta? - -Para que consiga realizar a criação da sua conta, é necessário acessar a -URL [https://hub.docker.com](https://hub.docker.com). -Antes era possível através do comando "docker login". Hoje, o comando -"docker login" somente é utilizado para autenticar no Docker Hub após a -criação da conta. - -A partir da confirmação do seu e-mail, já é possível se autenticar e -começar a fazer uso do Docker Hub. - -```bash -root@linuxtips:~# docker login -Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. - -Username: linuxtips01 -Password: -Login Succeeded - -root@linuxtips:~# -``` - -Você consegue criar repositórios públicos à vontade, porém na conta -*free* você somente tem direito a um repositório privado. Caso precise -de mais do que um repositório privado, é necessário o *upgrade* da sua -conta e o pagamento de uma mensalidade. :) - -Caso você queira especificar outro *registry* em vez do Docker Hub, -basta passar o endereço como parâmetro, como segue: - -```bash -# docker login registry.seilaqual.com -``` - -## 9.3. Agora vamos compartilhar essas imagens na *interwebs*! - -Uma vez que já criamos a nossa conta no Docker Hub, podemos começar a -utilizá-la! - -Como exemplo, vamos utilizar a imagem que montamos com o *dockerfile* no -capítulo anterior chamada "linuxtips/apache". Quando realizarmos o -*upload* dessa imagem para o Docker Hub, o repositório terá o mesmo nome -da imagem, ou seja, "linuxtips/apache". - -Uma coisa muito importante! A sua imagem deverá ter o seguinte padrão, -para que você consiga fazer o *upload* para o Docker Hub: - -**seuusuario/nomedaimagem:versão** - -Assim, sabemos que "linuxtips/apache:1.0" significa: - -- **linuxtips** -- Usuário do Docker Hub. - -- **apache** -- Nome da imagem. - -- **1.0** -- Versão. - -Agora vamos utilizar o comando "docker push", responsável por fazer o -*upload* da imagem da sua máquina local para o *registry* do Docker Hub, -como mostrado no exemplo a seguir: - -```bash -root@linuxtips:~# docker push linuxtips/apache:1.0 -The push refers to a repository [docker.io/linuxtips/apache] -b3a691489ee1: Pushed -5f70bf18a086: Layer already exists -917c0fc99b35: Pushed -1.0: digest: sha256:c8626093b19a686fd260dbe0c12db79a97ddfb6a6d8e4c4f44634f66991d93d0 size: 6861 - -root@linuxtips:~# -``` - -Acessando a URL -[https://hub.docker.com/](https://hub.docker.com/) -você conseguirá visualizar o repositório que acabou de criar, conforme a -imagem a seguir: - -![REPOSITORIO NO DOCKER HUB](../media/image4.png) - -Por padrão, ele cria o repositório como público. ;) - -Caso você queira visualizar o seu novo repositório pela linha de -comando, basta utilizar o comando "docker search" seguido de seu usuário -do Docker Hub: - -```bash -root@linuxtips:~# docker search - -NAME DESCRIPTION STARS OFFICIAL AUTOMATED -linuxtips/apache 0 -``` - -Já que possuímos a imagem no *registry* do Docker Hub, vamos testá-la -fazendo o *pull* da imagem e em seguida vamos executando-a para saber se -realmente tudo isso funciona de forma simples e fácil assim. :) - -Primeiro vamos parar os *containers* que utilizam a imagem -"linuxtips/apache": - -```bash -# docker container ls | grep seu_usuario/sua_imagem -# docker container stop CONTAINERID -``` - -Não é possível remover uma imagem se algum *container* estiver em -execução utilizando-a como imagem base. Por isso é necessário parar os -*containers* conforme fizemos antes. - -Para que você possa remover uma imagem é necessário utilizar o comando -"docker image rm", responsável por remover imagens do disco local. - -É importante mencionar que, caso possua *containers* parados que -utilizam essa imagem como base, é necessário forçar a remoção da imagem -utilizando o parâmetro "-f": - -```bash -# docker image rm -f linuxtips/apache:1.0 -Untagged: linuxtips/apache:1.0 -``` - -Pronto! Removemos a imagem! - -Agora vamos realizar o *pull* da imagem diretamente do *registry* do -Docker Hub para que tenhamos a imagem novamente em nosso disco local e -assim possamos subir um *container* utilizando-a. - -```bash -root@linuxtips:~# docker pull linuxtips/apache:1.0 -1.0: Pulling from linuxtips/apache -fdd5d7827f33: Already exists -a3ed95caeb02: Already exists -11b590220174: Already exists -Digest: sha256:c8626093b19a686fd260dbe0c12db79a97ddfb6a6d8e4c4f44634f66991d93d0 -Status: Downloaded newer image for linuxtips/apache:1.0 - -root@linuxtips:~# -``` - -Podemos novamente visualizá-la através do comando "docker image ls". - -```bash -root@linuxtips:~# docker image ls -REPOSITORY TAG IMAGE ID CREATED SIZE -linuxtips/apache 1.0 4862def18dfd About an hour ago 193.4 MB - -root@linuxtips:~# -``` - -Para criar o *container* utilizando nossa imagem: - -```bash -root@linuxtips:~# docker container run -d linuxtips/apache:1.0 -``` - -Simples como voar, não? - -## 9.4. Não confio na internet; posso criar o meu *registry* local? - -Como muitas empresas não gostam de manter seus dados na nuvem em -serviços de terceiros, existe a possibilidade de você configurar um -*registry* local. Assim, você não precisa utilizar o *registry* do -Docker Hub, por exemplo. Isso permite a você compartilhar suas imagens -com outras pessoas de sua empresa, funcionando como repositório de -imagens Docker. Sensacional! - -A URL do projeto fica em -[https://github.com/docker/distribution](https://github.com/docker/distribution). -O Docker Distribution é um *registry* que serve para guardar e -compartilhar suas imagens. Ele substitui o Docker Registry, que se -tornou obsoleto. - -Para que possamos ter o Docker Distribution de forma simples e -totalmente funcional, guardando e distribuindo nossas imagens Docker -localmente, basta rodá-lo como um *container*! :D - -```bash -root@linuxtips:~# docker container run -d -p 5000:5000 --restart=always --name registry registry:2 -Unable to find image 'registry:2' locally -2: Pulling from library/registry -fdd5d7827f33: Already exists -a3ed95caeb02: Pull complete -a79b4a92697e: Pull complete -6cbb75c7cc30: Pull complete -4831699594bc: Pull complete -Digest: sha256:20f5d95004b71fe14dbe7468eff33f18ee7fa52502423c5d107d4fb0abb05c1d -Status: Downloaded newer image for registry:2 -4f8efc8a71531656dc74e99dea74da203645c0f342b0706bc74200ae0a50cb20 - -root@linuxtips:~# -``` - -Com o comando anterior, criamos um *container* chamado "registry" que -utiliza a imagem "registry:2" como base e usamos a opção -"\--restart=always". Caso ocorra qualquer problema com o *container* ou -com o Docker, ele será iniciado automaticamente. Passamos também que a -porta de comunicação com o *container* será a 5000, que também utilizará -a porta 5000 do *host* com o mesmo propósito. Vamos ver sobre o -parâmetro "-p" em breve, no capítulo relacionado a redes. ;) - -Você pode verificar o *container* do *registry* em execução, bem como -sua imagem: - -```bash -# docker container ls -# docker image ls -``` - -Muito bom, nosso *registry* já está em execução! Agora vamos testá-lo -tentando realizar um *push* da nossa imagem para ele. - -Primeiramente, teremos que adicionar uma nova *tag* em nossa imagem -mencionando o endereço do novo *registry* em vez do nome do usuário que -utilizávamos quando queríamos fazer o *push* para o Docker Hub. Para -isso, vamos utilizar novamente o comando "docker tag": - -```bash -# docker tag IMAGEMID localhost:5000/apache -# docker image ls -``` - -Agora basta fazer o *push* para o nosso *registry* local da seguinte -forma: - -```bash -root@linuxtips:~# docker push localhost:5000/apache -The push refers to a repository [localhost:5000/apache] -b3a691489ee1: Pushed -5f70bf18a086: Pushed -917c0fc99b35: Pushed -latest: digest: sha256:0e69b8d5cea67fcfedb5d7128a9fd77270461aa5852e6fe9b465565ec8e4e12f size: 925 - -root@linuxtips:~# -``` - -Pronto! Agora nós possuímos um *registry* local! - -Fizemos um *registry* totalmente funcional, porém simples. Caso queira -utilizar recursos como controle de usuários, certificados, outras opções -de *storage*, etc., visite a página do projeto no GitHub: -https://github.com/docker/distribution. - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_10.md b/capitulos/CHAPTER_10.md deleted file mode 100644 index be1bd2a..0000000 --- a/capitulos/CHAPTER_10.md +++ /dev/null @@ -1,213 +0,0 @@ -
- -# 10. Gerenciando a rede dos *containers* - -Quando o Docker é executado, ele cria uma *bridge* virtual chamada -"docker0", para que possa gerenciar a comunicação interna entre o -*container* e o *host* e também entre os *containers*. - -Vamos conhecer alguns parâmetros do comando "Docker container run" que -irão nos ajudar com a rede em que os *containers* irão se comunicar. - -- **\--dns** -- Indica o servidor DNS. - -- **\--hostname** -- Indica um *hostname.* - -- **\--link** -- Cria um *link* entre os *containers*, sem a necessidade de se saber o IP um do outro. - -- **\--net** -- Permite configurar o modo de rede que você usará com o *container*. Temos quatro opções, mas a mais conhecida e utilizada é a "\--net=host", que permite que o *container* utilize a rede do *host* para se comunicar e não crie um *stack* de rede para o *container*. - -- **\--expose** -- Expõe a porta do *container* apenas. - -- **\--publish** -- Expõe a porta do *container* e do *host*. - -- **\--default-gateway** -- Determina a rota padrão. - -- **\--mac-address** -- Determina um MAC *address*. - -Quando o *container* é iniciado, a rede passa por algumas etapas até a -sua inicialização completa: - -1. Cria-se um par de interfaces virtuais. - -2. Cria-se uma interface com nome único, como "veth1234", e em seguida *linka-se* com a *bridge* do Docker, a "docker0". - -3. Com isso, é disponibilizada a interface "eth0" dentro do *container*, em um *network namespace* único. - -4. Configura-se o MAC *address* da interface virtual do *container.* - -5. Aloca-se um IP na "eth0" do *container*. Esse IP tem que pertencer ao *range* da *bridge* "docker0"*.* - -Com isso, o *container* já possui uma interface de rede e já está apto a -se comunicar com outros *containers* ou com o *host*. :D - -## 10.1. Consigo fazer com que a porta do *container* responda na porta do *host*? - -Sim, isso é possível e bastante utilizado. - -Vamos conhecer um pouco mais sobre isso em um exemplo utilizando aquela -nossa imagem "linuxtips/apache". - -Primeira coisa que temos que saber é a porta pela qual o Apache2 se -comunica. Isso é fácil, né? Se estiver com as configurações padrões de -porta de um *web server*, o Apache2 do *container* estará respondendo na -porta 80/TCP, correto? - -Agora vamos fazer com que a porta 8080 do nosso *host* responda pela -porta 80 do nosso *container*, ou seja, sempre que alguém bater na porta -8080 do nosso *host*, a requisição será encaminhada para a porta 80 do -*container*. Simples, né? - -Para conseguir fazer esse encaminhamento, precisamos utilizar o -parâmetro "-p" do comando "docker container run", conforme faremos no -exemplo a seguir: - -```bash -root@linuxtips:~# # docker container run -ti -p 8080:80 linuxtips/apache:1.0 /bin/bash -root@4a0645de6d94:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 1 18:18 ? 00:00:00 /bin/bash -root 6 1 0 18:18 ? 00:00:00 ps -ef - -root@4a0645de6d94:/# /etc/init.d/apache2 start -[....] Starting web server: apache2AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message -. ok - -root@4a0645de6d94:/# ps -ef -UID PID PPID C STIME TTY TIME CMD -root 1 0 0 18:18 ? 00:00:00 /bin/bash -root 30 1 0 18:19 ? 00:00:00 /usr/sbin/apache2 -k start -www-data 33 30 0 18:19 ? 00:00:00 /usr/sbin/apache2 -k start -www-data 34 30 0 18:19 ? 00:00:00 /usr/sbin/apache2 -k start -root 109 1 0 18:19 ? 00:00:00 ps -ef - -root@4a0645de6d94:/# ip addr -1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default - link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 - inet 127.0.0.1/8 scope host lo - valid_lft forever preferred_lft forever - inet6 ::1/128 scope host - valid_lft forever preferred_lft forever -74: eth0: mtu 1500 qdisc noqueue state UP group default - link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff - inet 172.17.0.3/16 scope global eth0 - valid_lft forever preferred_lft forever - inet6 fe80::42:acff:fe11:3/64 scope link - valid_lft forever preferred_lft forever - -root@4a0645de6d94:/# -``` - -Repare que passamos o parâmetro "-p" da seguinte forma: - -- **-p 8080:80** -- Onde "8080" é a porta do host e "80" a do container. - -Com isso, estamos dizendo que toda requisição que chegar na porta 8080 -do meu *host* deverá ser encaminhada para a porta 80 do *container.* - -Já no *container*, subimos o Apache2 e verificamos o IP do *container*, -correto? - -Agora vamos sair do *container* com o atalho "Ctrl + p + q". :) - -A partir do *host*, vamos realizar um "curl" com destino ao IP do -*container* na porta 80, depois com destino à porta 8080 do *host* e em -seguida analisar as saídas: - -```bash -root@linuxtips:~# curl :80 -``` - -Se tudo ocorreu bem até aqui, você verá o código da página de -boas-vindas do Apache2. - -O mesmo ocorre quando executamos o "curl" novamente, porém batendo no IP -do *host*. Veja: - -```bash -root@linuxtips:~# curl :8080 -``` - -Muito fácil, chega a ser lacrimejante! \\o/ - -## 10.2. E como ele faz isso? Mágica? - -Não, não é mágica! Na verdade, o comando apenas utiliza um módulo -bastante antigo do *kernel* do Linux chamado *netfilter*, que -disponibiliza a ferramenta *iptables*, que todos nós já cansamos de -usar. - -Vamos dar uma olhada nas regras de *iptables* referentes a esse nosso -*container*. Primeiro a tabela *filter*: - -```bash -root@linuxtips:~# iptables -L -n -Chain INPUT (policy ACCEPT) -target prot opt source destination - -Chain FORWARD (policy ACCEPT) -target prot opt source destination -DOCKER-ISOLATION all -- 0.0.0.0/0 0.0.0.0/0 -DOCKER all -- 0.0.0.0/0 0.0.0.0/0 -ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED -ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 -ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination - -Chain DOCKER (1 references) -target prot opt source destination -ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:5000 -ACCEPT tcp -- 0.0.0.0/0 172.17.0.3 tcp dpt:80 - -Chain DOCKER-ISOLATION (1 references) -target prot opt source destination -RETURN all -- 0.0.0.0/0 0.0.0.0/0 - -root@linuxtips:~# -``` - -Agora a tabela NAT: - -```bash -root@linuxtips:~# iptables -L -n -t nat - -Chain PREROUTING (policy ACCEPT) -target prot opt source destination -DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL - -Chain INPUT (policy ACCEPT) -target prot opt source destination - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL - -Chain POSTROUTING (policy ACCEPT) -target prot opt source destination -MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 -MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:5000 -MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:80 - -Chain DOCKER (2 references) -target prot opt source destination -RETURN all -- 0.0.0.0/0 0.0.0.0/0 -DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5000 to:172.17.0.2:5000 -DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.3:80 - -root@linuxtips:~# -``` - -Como podemos notar, temos regras de NAT configuradas que permitem o DNAT -da porta 8080 do *host* para a 80 do *container.* Veja a seguir: - -```bash -MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:80 -DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.3:80 -``` - -Tudo isso feito "automagicamente" pelo Docker, sem a necessidade de -precisar configurar diversas regras de *iptables*. \<3 - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_11.md b/capitulos/CHAPTER_11.md deleted file mode 100644 index 35f9617..0000000 --- a/capitulos/CHAPTER_11.md +++ /dev/null @@ -1,185 +0,0 @@ -
- -# 11. Controlando o *daemon* do Docker - -Antes de tudo, vamos tentar entender o que é um *daemon*. Sabemos que, -em sistemas operacionais *multitask*, isto é, em um sistema operacional -capaz de executar mais de uma tarefa por vez (*not really*), um *daemon* -é um software que roda de forma independente em *background*. Ele -executa certas ações predefinidas em resposta a certos eventos. Pois -bem, o *daemon* do Docker é exatamente isso: uma espécie de processo-pai -que controla tudo, *containers*, imagens, etc., etc., etc. - -Até o Docker 1.7 as configurações referentes especificamente ao *daemon* -se confundiam bastante com configurações globais -- isso porque quando -você digitava lá o "docker -help" um monte de coisas retornava, e você -não sabia o que era o quê. A partir da versão 1.8 tivemos o "docker -daemon", e agora, mais recentemente, acreditamos que na versão 18.03 do -Docker, ele foi substituído pelo "dockerd", que resolve de vez esse -problema e trata especificamente de configurações referentes, -obviamente, ao *daemon* do Docker. - -## 11.1. O Docker sempre utiliza 172.16.X.X ou posso configurar outro intervalo de IP? - -Sim, você pode configurar outro *range* para serem utilizados pela -*bridge* "docker0" e também pelas interfaces dos *containers*. - -Para que você consiga configurar um *range* diferente para utilização do -Docker é necessário iniciá-lo com o parâmetro "\--bip". - -```bash -# dockerd --bip 192.168.0.1/24 -``` - -Assim, você estará informando ao Docker que deseja utilizar o IP -"192.168.0.1" para sua *bridge* "docker0" e, consequentemente, para a -*subnet* dos *containers*. - -Você também poderá utilizar o parâmetro "\--fixed-cidr" para restringir -o *range* que o Docker irá utilizar para a *bridge* "docker0" e para a -*subnet* dos *containers*. - -```bash -# dockerd --fixed-cidr 192.168.0.0/24 -``` - -## 11.2. Opções de *sockets* - -*Sockets* são *end-points* com as quais duas ou mais aplicações ou -processos se comunicam em um ambiente, geralmente um "IP:porta" ou um -arquivo, como no caso do *Unix Domain Sockets*. - -Atualmente o Docker consegue trabalhar com três tipos de *sockets*, -Unix, TCP e FD, e por *default* ele usa *unix sockets*. Você deve ter -notado que, ao *startar* seu Docker, foi criado um arquivo em -"/var/run/docker.sock". Para fazer alterações nele você vai precisar ou -de permissão de *root* ou de que o usuário que esteja executando as -ações faça parte do grupo "docker", como dissemos no começo deste livro, -lembra? - -Por mais prático que isso seja, existem algumas limitações, como, por -exemplo, o *daemon* só poder ser acessado localmente. Para resolver isso -usamos geralmente o TCP. Nesse modelo nós definimos um IP, que pode ser -tanto "qualquer um" (0.0.0.0 e uma porta) como um IP específico e uma -porta. - -Nos sistemas baseados em *systemd* você ainda pode se beneficiar do -*systemd socket activation*, uma tecnologia que visa economia de -recursos. Consiste basicamente em ativar um *socket* somente enquanto -uma conexão nova chega e desativar quando não está sendo mais usado. - -Além disso tudo, dependendo do seu ambiente, você também pode fazer o -Docker escutar em diferentes tipos de *sockets*, o que é feito através -do parâmetro "-H" do comando "dockerd". - -Exemplos: - -### 11.2.1. *Unix Domain Socket* - -```bash -root@linuxtips:~# dockerd -H unix:///var/run/docker.sock -INFO[0000] [graphdriver] using prior storage driver "aufs" -INFO[0000] Graph migration to content-addressability took 0.00 seconds -INFO[0000] Firewalld running: false -INFO[0000] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP -address -WARN[0000] Your kernel does not support swap memory limit. -INFO[0000] Loading containers: start. -.......................... -INFO[0000] Loading containers: done. -INFO[0000] Daemon has completed initialization -INFO[0000] Docker daemon commit=c3959b1 execdriver=native-0.2 graphdriver=aufs version=1.10.2 -INFO[0000] API listen on /var/run/docker.sock -``` - -### 11.2.2. TCP - -```bash -root@linuxtips:~# dockerd -H tcp://0.0.0.0:2375 -WARN[0000] /! DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /! -INFO[0000] [graphdriver] using prior storage driver "aufs" -INFO[0000] Graph migration to content-addressability took 0.01 seconds -INFO[0000] Firewalld running: false -INFO[0000] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address -WARN[0000] Your kernel does not support swap memory limit. -INFO[0000] Loading containers: start. -.......................... -INFO[0000] Loading containers: done. -INFO[0000] Daemon has completed initialization -INFO[0000] Docker daemon commit=c3959b1 execdriver=native-0.2 graphdriver=aufs version=1.10.2 -INFO[0000] API listen on [::]:2375 -``` - -## 11.3. Opções de *storage* - -Sendo o cara que controla tudo, naturalmente é possível passar opções -que mudam a forma como o Docker se comporta ao trabalhar com *storages*. -Como falamos anteriormente, o Docker suporta alguns *storage drivers*, -todos baseados no esquema de *layers*. - -Essas opções são passadas para o *daemon* pelo parâmetro -"\--storage-opt", com o qual itens relacionados ao *Device Mapper* -recebem o prefixo "dm" e "zfs" para (adivinha?) o ZFS. A seguir vamos -demonstrar algumas opções mais comuns: - -- **dm.thinpooldev** -- Com esta opção você consegue especificar o *device* que será usado pelo *Device Mapper* para desenvolver o *thin-pool* que ele usa para criar os *snapshots* usados por *containers* e imagens. - -Exemplo: - -```bash -root@linuxtips:~# dockerd --storage-opt dm.thinpooldev=/dev/mapper/thin-pool -INFO[0000] [graphdriver] using prior storage driver "aufs" -INFO[0000] Graph migration to content-addressability took 0.00 seconds -INFO[0000] Firewalld running: false -INFO[0000] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address -WARN[0000] Your kernel does not support swap memory limit. -INFO[0000] Loading containers: start. -................................ -INFO[0000] Loading containers: done. -INFO[0000] Daemon has completed initialization -INFO[0000] Docker daemon commit=c3959b1 execdriver=native-0.2 graphdriver=aufs version=1.10.2 -INFO[0000] API listen on /var/run/docker.sock -``` - -- **dm.basesize** -- Este parâmetro define o tamanho máximo do *container*. O chato disso é que você precisa deletar tudo dentro de "/var/lib/docker" (o que implica em matar todos os *containers* e imagens) e *restartar* o serviço do Docker. - - -```bash -root@linuxtips:~# dockerd --storage-opt dm.basesize=10G -INFO[0000] [graphdriver] using prior storage driver "aufs" -INFO[0000] Graph migration to content-addressability took 0.00 seconds -INFO[0000] Firewalld running: false -INFO[0000] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address -WARN[0000] Your kernel does not support swap memory limit. -INFO[0000] Loading containers: start. -.......................... -INFO[0000] Loading containers: done. -INFO[0000] Daemon has completed initialization -INFO[0000] Docker daemon commit=c3959b1 execdriver=native-0.2 graphdriver=aufs version=1.10.2 -INFO[0000] API listen on /var/run/docker.sock -``` - -- **dm.fs** -- Especifica o *filesystem* do *container*. As opções suportadas são: **EXT4** e **XFS**. - -## 11.4. Opções de rede - -Também é possível controlar como o *daemon* se comportará em relação à -rede: - -- **\--default-gateway** -- Autoexplicativo, né? Todos os *containers* receberão esse IP como *gateway*. - -- **\--dns** -- Também sem segredo: é o DNS que será usado para consultas. - -- **\--dns-search** -- Especifica o domínio a ser procurado, assim você consegue pesquisar máquinas sem usar o fqdn. - -- **\--ip-forward** -- Esta opção habilita o roteamento entre *containers.* Por padrão, ela já vem *setada* como *true*. - -## 11.5. Opções diversas - -- **\--default-ulimit** -- Passando isso para o *daemon*, todos os *containers* serão iniciados com esse valor para o "ulimit". Esta opção é sobrescrita pelo parâmetro "\--ulimit" do comando "docker container run", que geralmente vai dar uma visão mais específica. - -- **\--icc** -- "icc" vem de *inter container comunication*. Por padrão, ele vem marcado como *true*; caso você não queira esse tipo de comunicação, você pode marcar no *daemon* como *false*. - -- **\--log-level** -- É possível alterar também a forma como o Docker trabalha com *log*; em algumas situações (geralmente *troubleshoot*) você pode precisar de um *log* mais "verboso", por exemplo. - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_12.md b/capitulos/CHAPTER_12.md deleted file mode 100644 index 1a26346..0000000 --- a/capitulos/CHAPTER_12.md +++ /dev/null @@ -1,344 +0,0 @@ -
- -# 12. Docker Machine - -## 12.1. Ouvi dizer que minha vida ficaria melhor com o Docker Machine! - -Certamente! - -Com o Docker Machine você consegue, com apenas um comando, iniciar o seu -projeto com Docker! - -Antes do Docker Machine, caso quiséssemos montar um Docker Host, era -necessário fazer a instalação do sistema operacional, instalar e -configurar o Docker e outras ferramentas que se fazem necessárias. - -Perderíamos um tempo valoroso com esses passos, sendo que já poderíamos -trabalhar efetivamente com o Docker e seus *containers*. - -Porém, tudo mudou com o Docker Machine! Com ele você consegue criar o -seu Docker Host com apenas um comando. O Docker Machine consegue -trabalhar com os principais *hypervisors* de VMs, como o VMware, Hyper-V -e Oracle VirtualBox, e também com os principais provedores de -infraestrutura, como AWS, Google Compute Engine, DigitalOcean, -Rackspace, Azure, etc. - -Para que você possa ter acesso a todos os *drivers* que o Docker Machine -suporta, acesse: -[https://docs.docker.com/machine/drivers/](https://docs.docker.com/machine/drivers/). - -Quando você utiliza o Docker Machine para instalar um Docker Host na -AWS, por exemplo, ele disponibilizará uma máquina com Linux e com o -Docker e suas dependências já instaladas. - -### 12.1.1. Vamos instalar? - -A instalação do Docker Machine é bastante simples, por isso, vamos parar -de conversa e brincar! Vale lembrar que é possível instalar o Docker -Machine no Linux, MacOS ou Windows. - -Para fazer a instalação do Docker Machine no Linux, faça: - -```bash -# curl -L https://github.com/docker/machine/releases/download/v0.12.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine -# chmod +x /tmp/docker-machine -# sudo cp /tmp/docker-machine /usr/local/bin/docker-machine -``` - -Para seguir com a instalação no MacOS: - -```bash -$ curl -L https://github.com/docker/machine/releases/download/v0.15.0/docker-machine-`uname -s`-`uname -m` >/usr/local/bin/docker-machine -$ chmod +x /usr/local/bin/docker-machine -``` - -Para seguir com a instalação no Windows caso esteja usando o Git *bash*: - -```bash -$ if [[ ! -d "$HOME/bin" ]]; then mkdir -p "$HOME/bin"; fi -$ curl -L https://github.com/docker/machine/releases/download/v0.15.0/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" -$ chmod +x "$HOME/bin/docker-machine.exe" -``` - -Para verificar se ele foi instalado e qual a sua versão, faça: - -```bash -root@linuxtips:~# docker-machine version -docker-machine version 0.15.0, build b48dc28 - -root@linuxtips:~# -``` - -Pronto. Como tudo que é feito pelo Docker, é simples de instalar e fácil -de operar. :) - -### 12.1.2. Vamos iniciar nosso primeiro projeto? - -Agora que já temos o Docker Machine instalado em nossa máquina, já -conseguiremos fazer a instalação do Docker Host de forma bastante -simples -- lembrando que, mesmo que tivéssemos feito a instalação do -Docker Machine no Windows, conseguiríamos tranquilamente comandar a -instalação do Docker Hosts na AWS em máquinas Linux. Tenha em mente que -a máquina na qual você instalou o Docker Machine é o maestro que -determina a criação de novos Docker Hosts, seja em VMs ou em alguma -nuvem como a AWS. - -Em nosso primeiro projeto, vamos fazer com que o Docker Machine instale -o Docker Host utilizando o VirtualBox. - -Como utilizaremos o VirtualBox, é evidente que precisamos ter instalado -o VirtualBox em nossa máquina para que tudo funcione. ;) - -Portanto: - -```bash -root@linuxtips:~# apt-get install virtualbox -``` - -Para fazer a instalação de um novo Docker Host, utilizamos o comando -"docker-machine create". Para escolher onde criaremos o Docker Host, -utilizamos o parâmetro "\--driver", conforme segue: - -```bash -root@linuxtips:~# docker-machine create --driver virtualbox linuxtips -Running pre-create checks... -(linuxtips) Default Boot2Docker ISO is out-of-date, downloading the latest release... -(linuxtips) Latest release for github.com/boot2docker/boot2docker is v17.05.0-ce -(linuxtips) Downloading /Users/linuxtips/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v17.05.0-ce/boot2docker.iso... -(linuxtips) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100% -Creating machine... -(linuxtips) Copying /Users/linuxtips/.docker/machine/cache/boot2docker.iso to /Users/linuxtips/.docker/machine/machines/linuxtips/boot2docker.iso... -(linuxtips) Creating VirtualBox VM... -(linuxtips) Creating SSH key... -(linuxtips) Starting the VM... -(linuxtips) Check network to re-create if needed... -(linuxtips) Waiting for an IP... -Waiting for machine to be running, this may take a few minutes... -Detecting operating system of created instance... -Waiting for SSH to be available... -Detecting the provisioner... -Provisioning with boot2docker... -Copying certs to the local machine directory... -Copying certs to the remote machine... -Setting Docker configuration on the remote daemon... -Checking connection to Docker... -Docker is up and running! - -To see how to connect your Docker Client to the Docker Engine running on -this virtual machine, run: docker-machine env linuxtips - -root@linuxtips:~# -``` - -Onde: - -- **docker-machine create** -- Cria um novo Docker Host. - -- **\--driver virtualbox** -- Irá criá-lo utilizando o VirtualBox. - -- **linuxtips** -- Nome da VM que será criada. - -Para visualizar o *host* que acabou de criar, basta digitar o seguinte -comando: - -```bash -root@linuxtips:~# docker-machine ls -NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS -linuxtips - virtualbox Running tcp://192.168.99.100:2376 v18.06.0 - -``` - -Como podemos notar, o nosso *host* está sendo executado perfeitamente! -Repare que temos uma coluna chamada URL, correto? Nela temos a URL para -que possamos nos comunicar com o nosso novo *host*. - -Outra forma de visualizar informações sobre o *host*, mais -especificamente sobre as variáveis de ambiente dele, é digitar: - -```bash -root@linuxtips:~# docker-machine env linuxtips -export DOCKER_TLS_VERIFY="1" -export DOCKER_HOST="tcp://192.168.99.100:2376" -export DOCKER_CERT_PATH="/Users/linuxtips/.docker/machine/machines/linuxtips" -export DOCKER_MACHINE_NAME="linuxtips" -# Run this command to configure your shell: -# eval "$(docker-machine env linuxtips)" - -root@linuxtips:~# -``` - -Serão mostradas todas as variáveis de ambiente do *host*, como URL, -certificado e nome. - -Para que você possa acessar o ambiente desse *host* que acabamos de -criar, faça: - -```bash -root@linuxtips:~# eval "$(docker-machine env linuxtips)" -``` - -O comando "eval" serve para definir variáveis de ambiente através da -saída de um comando, ou seja, as variáveis que visualizamos na saída do -"docker-machine env linuxtips". - -Agora que já estamos no ambiente do *host* que criamos, vamos visualizar -os *containers* em execução: - -```bash -root@linuxtips:~# docker container ls -``` - -Claro que ainda não temos nenhum *container* em execução; vamos iniciar -o nosso primeiro agora: - -```bash -root@linuxtips:~# docker container run busybox echo "LINUXTIPS, VAIIII" -Unable to find image 'busybox:latest' locally -latest: Pulling from library/busybox -385e281300cc: Pull complete -a3ed95caeb02: Pull complete -Digest: sha256:4a887a2326ec9e0fa90cce7b4764b0e627b5d6afcb81a3f73c85dc29cea00048 -Status: Downloaded newer image for busybox:latest -LINUXTIPS, VAIIII - -root@linuxtips:~# -``` - -Como podemos observar, o *container* foi executado e imprimiu a mensagem -"**LINUXTIPS, VAIIII**", conforme solicitamos. - -Lembre-se de que o *container* foi executado em nosso Docker Host, que -criamos através do Docker Machine. - -Para verificar o IP do *host* que criamos, faça: - -```bash -root@linuxtips:~# docker-machine ip linuxtips -192.168.99.100 - -root@linuxtips:~# -``` - -Para que possamos acessar o nosso *host*, utilizamos o parâmetro "ssh" -passando o nome do *host* que queremos acessar: - -```bash -root@linuxtips:~# docker-machine ssh linuxtips -``` - -Para saber mais detalhes sobre o *host*, podemos utilizar o parâmetro -"inspect": - -```bash -root@linuxtips:~# docker-machine inspect linuxtips -{ - "ConfigVersion": 3, - "Driver": { - "IPAddress": "192.168.99.100", - "MachineName": "linuxtips", - "SSHUser": "docker", - "SSHPort": 57249, - "SSHKeyPath": "/Users/jeferson/.docker/machine/machines/linuxtips/id_rsa", - "StorePath": "/Users/jeferson/.docker/machine", - "SwarmMaster": false, - "SwarmHost": "tcp://0.0.0.0:3376", - "SwarmDiscovery": "", - "VBoxManager": {}, - "HostInterfaces": {}, - "CPU": 1, - "Memory": 1024, - "DiskSize": 20000, - "NatNicType": "82540EM", - "Boot2DockerURL": "", - "Boot2DockerImportVM": "", - "HostDNSResolver": false, - "HostOnlyCIDR": "192.168.99.1/24", - "HostOnlyNicType": "82540EM", - "HostOnlyPromiscMode": "deny", - "UIType": "headless", - "HostOnlyNoDHCP": false, - "NoShare": false, - "DNSProxy": true, - "NoVTXCheck": false, - "ShareFolder": "" - }, - "DriverName": "virtualbox", - "HostOptions": { - "Driver": "", - "Memory": 0, - "Disk": 0, - "EngineOptions": { - "ArbitraryFlags": [], - "Dns": null, - "GraphDir": "", - "Env": [], - "Ipv6": false, - "InsecureRegistry": [], - "Labels": [], - "LogLevel": "", - "StorageDriver": "", - "SelinuxEnabled": false, - "TlsVerify": true, - "RegistryMirror": [], - "InstallURL": "https://get.docker.com" - }, - "SwarmOptions": { - "IsSwarm": false, - "Address": "", - "Discovery": "", - "Agent": false, - "Master": false, - "Host": "tcp://0.0.0.0:3376", - "Image": "swarm:latest", - "Strategy": "spread", - "Heartbeat": 0, - "Overcommit": 0, - "ArbitraryFlags": [], - "ArbitraryJoinFlags": [], - "Env": null, - "IsExperimental": false - }, - "AuthOptions": { - "CertDir": "/Users/jeferson/.docker/machine/certs", - "CaCertPath": "/Users/jeferson/.docker/machine/certs/ca.pem", - "CaPrivateKeyPath": "/Users/jeferson/.docker/machine/certs/ca-key.pem", - "CaCertRemotePath": "", - "ServerCertPath": "/Users/jeferson/.docker/machine/machines/linuxtips/server.pem", - "ServerKeyPath": "/Users/jeferson/.docker/machine/machines/linuxtips/server-key.pem", - "ClientKeyPath": "/Users/jeferson/.docker/machine/certs/key.pem", - "ServerCertRemotePath": "", - "ServerKeyRemotePath": "", - "ClientCertPath": "/Users/jeferson/.docker/machine/certs/cert.pem", - "ServerCertSANs": [], - "StorePath": "/Users/jeferson/.docker/machine/machines/linuxtips" - } - }, - "Name": "linuxtips" -} -``` - -Para parar o *host* que criamos: - -```bash -root@linuxtips:~# docker-machine stop linuxtips -``` - -Para que você consiga visualizar o status do seu *host* Docker, digite: - -```bash -root@linuxtips:~# docker-machine ls -``` - -Para iniciá-lo novamente: - -```bash -root@linuxtips:~# docker-machine start linuxtips -``` - -Para removê-lo definitivamente: - -```bash -root@linuxtips:~# docker-machine rm linuxtips -Successfully removed linuxtips -``` - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_13.md b/capitulos/CHAPTER_13.md deleted file mode 100644 index 0bcd70e..0000000 --- a/capitulos/CHAPTER_13.md +++ /dev/null @@ -1,607 +0,0 @@ -
- -# 13. Docker Swarm - -Bom, agora temos uma ferramenta muito interessante e que nos permite -construir *clusters* de *containers* de forma nativa e com extrema -facilidade, como já é de costume com os produtos criados pelo time do -Docker. ;) - -Com o Docker Swarm você consegue construir *clusters* de *containers* -com características importantes como balanceador de cargas e *failover*. - -Para criar um *cluster* com o Docker Swarm, basta indicar quais os -*hosts* que ele irá supervisionar e o restante é com ele. - -Por exemplo, quando você for criar um novo *container*, ele irá criá-lo -no *host* que possuir a menor carga, ou seja, cuidará do balanceamento -de carga e garantirá sempre que o *container* será criado no melhor -*host* disponível no momento. - -A estrutura de *cluster* do Docker Swarm é bastante simples e se resume -a um *manager* e diversos *workers*. O *manager* é o responsável por -orquestrar os *containers* e distribuí-los entre os *hosts workers*. Os -*workers* são os que carregam o piano, que hospedam os *containers*. - -## 13.1. Criando o nosso *cluster*! - -Uma coisa importante que começou após a versão 1.12 foi a inclusão do -Docker Swarm dentro do Docker, ou seja, hoje quando você realiza a -instalação do Docker, automaticamente você está instalando o Docker -Swarm, que nada mais é do que uma forma de orquestrar seus *containers* -através da criação de um *cluster* com alta disponibilidade, -balanceamento de carga e comunicação criptografada, tudo isso nativo, -sem qualquer esforço ou dificuldade. - -Para o nosso cenário, vamos utilizar três máquinas Ubuntu. A ideia é -fazer com que tenhamos dois *managers* e 1 *worker*. - -Precisamos ter sempre mais do que um *node* representando o *manager*, -pois, se ficarmos sem *manager*, nosso *cluster* estará totalmente -indisponível. - -Com isso temos o seguinte cenário: - -- **LINUXtips-01** -- *Manager* ativo. - -- **LINUXtips-02** -- *Manager*. - -- **LINUXtips-03** -- *Worker*. - -Não precisa falar que precisamos ter o Docker instalado em todas essas -máquinas, certo, amiguinho? :D - -Para iniciar, vamos executar o seguinte comando na "LINUXtips-01": - -```bash -root@linuxtips-01:~# docker swarm init -Swarm initialized: current node (2qacv429fvnret8v09fqmjm16) is now a manager. - -To add a worker to this swarm, run the following command: - - docker swarm join --token SWMTKN-1-100qtga34hfnf14xdbbhtv8ut6ugcvuhsx427jtzwaw1td2otj-18wccykydxte59gch2pix 172.31.58.90:2377 - -To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. - -root@linuxtips-01:~# -``` - -Com o comando anterior, iniciamos o nosso *cluster*! - -Repare no seguinte trecho da saída do último comando: - -```bash -# docker swarm join --token SWMTKN-1-100qtga34hfnf14xdbbhtv8ut6ugcvuhsx427jtzwaw1td2otj-18wccykydxte59gch2pix 172.31.58.90:2377 -``` - -Essa linha nada mais é do que toda informação que você precisa para -adicionar *workers* ao seu *cluster*! Como assim? - -Simples: o que você precisa agora é executar exatamente esse comando na -próxima máquina que você deseja incluir no *cluster* como *worker*! -Simples como voar, não? - -De acordo com o nosso plano, a única máquina que seria *worker* é a -máquina "LINUXtips-03", correto? Então vamos acessá-la e executar -exatamente a linha de comando recomendada na saída do "docker swarm -init". - -```bash -root@linuxtips-03:~# docker swarm join --token SWMTKN-1-100qtga34hfnf14xdbbhtv8ut6ugcvuhsx427jtzwaw1td2otj-18wccykydxte59gch2pix 172.31.58.90:2377 -This node joined a swarm as a worker. - -root@linuxtips-03:~# -``` - -Maravilha! Mais um *node* adicionado ao *cluster*! - -Para que você possa ver quais os *nodes* que existem no *cluster*, basta -digitar o seguinte comando no ***manager* ativo**: - -```bash -root@linuxtips-01:~# docker node ls -ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION -2qac LINUXtips-01 Ready Active Leader 18.03.1-ce -nmxl LINUXtips-03 Ready Active 18.03.1-ce - -root@linuxtips-01:~# -``` - -Como podemos notar na saída do comando, temos dois *nodes* em nosso -*cluster*, um como *manager* e outro como *worker*. A coluna "MANAGER -STATUS" traz a informação de quem é o "Leader", ou seja, quem é o nosso -*manager*. - -Em nosso plano nós teríamos dois *managers*, correto? - -Agora a pergunta é: como eu sei qual é o *token* que preciso utilizar -para adicionar mais um *node* em meu *cluster*, porém dessa vez como -outro *manager*? - -Lembra que, quando executamos o comando para adicionar o *worker* ao -*cluster*, nós tínhamos no comando um *token*? Pois bem, esse *token* é -quem define se o *node* será um *worker* ou um *manager*, e naquela -saída ele nos trouxe somente o *token* para adicionarmos *workers*. - -Para que possamos visualizar o comando e o *token* referente aos -*managers*, precisamos executar o seguinte comando no *manager* ativo: - -```bash -root@linuxtips-01:~# docker swarm join-token manager -To add a manager to this swarm, run the following command: - - docker swarm join --token SWMTKN-1-100qtga34hfnf14xdbbhtv8ut6ugcvuhsx427jtzwaw1td2otj-3i4jsv4i70odu1mes0ebe1l1e 172.31.58.90:2377 - -root@linuxtips-01:~# -``` - -Para visualizar o comando e o *token* referente aos *workers*: - -```bash -root@linuxtips-01:~# docker swarm join-token worker -To add a worker to this swarm, run the following command: - - docker swarm join --token SWMTKN-1-100qtga34hfnf14xdbbhtv8ut6ugcvuhsx427jtzwaw1td2otj-18wccykydxte59gch2pixq9av 172.31.58.90:2377 - -root@linuxtips-01:~# -``` - -Fácil, não? - -Agora o que precisamos é executar na "LINUXtips-02" o comando para -inclusão de mais um *node* como *manager*. Portanto, execute: - -```bash -root@linuxtips-02:~# docker swarm join --token SWMTKN-1-100qtga34hfnf14xdbbhtv8ut6ugcvuhsx427jtzwaw1td2otj-3i4jsv4i70odu1mes0ebe1l1e 172.31.58.90:2377 - -This node joined a swarm as a manager. - -root@linuxtips-02:~# -``` - -Pronto! Agora temos o nosso *cluster* completo com dois *managers* e um -*worker*! - -Vamos visualizar os *nodes* que fazem parte de nosso *cluster*. -Lembre-se: qualquer comando para administração do *cluster* ou criação -de serviços deverá obrigatoriamente ser executado no *manager* ativo, -sempre! - -```bash -root@linuxtips-01:~# docker node ls -ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION -2qac LINUXtips-01 Ready Active Leader 18.03.1-ce -j6lm LINUXtips-02 Ready Active Reachable 18.03.1-ce -nmxl LINUXtips-03 Ready Active 18.03.1-ce - -root@linuxtips-01:~# -``` - -Perceba que o "MANAGER STATUS" da "LINUXtips-02" é "Reachable". Isso -indica que ela é um *manager*, porém não é o *manager* ativo, que sempre -carrega o "MANAGER STATUS" como "Leader". - -Se nós quisermos saber detalhes sobre determinado *node*, podemos usar o -subcomando "inspect": - -```bash -root@linuxtips-01:~# docker node inspect LINUXtips-02 -[ - { - "ID": "x3fuo6tdaqjyjl549r3lu0vbj", - "Version": { - "Index": 27 - }, - "CreatedAt": "2017-06-09T18:09:48.925847118Z", - "UpdatedAt": "2017-06-09T18:09:49.053416781Z", - "Spec": { - "Labels": {}, - "Role": "worker", - "Availability": "active" - }, - "Description": { - "Hostname": "LINUXtips-02", - "Platform": { - "Architecture": "x86_64", - "OS": "linux" - }, - "Resources": { - "NanoCPUs": 1000000000, - "MemoryBytes": 1038807040 - }, - "Engine": { - "EngineVersion": "17.05.0-ce", - "Plugins": [ - { - "Type": "Network", - "Name": "bridge" - }, - { - "Type": "Network", - "Name": "host" - }, - { - "Type": "Network", - "Name": "null" - }, - { - "Type": "Network", - "Name": "overlay" - }, - { - "Type": "Volume", - "Name": "local" - } - ] - } - }, - "Status": { - "State": "ready", - "Addr": "172.31.53.23" - } - } -] - -root@linuxtips-01:~# -``` - -E se nós quisermos promover um *node worker* para *manager*, como -devemos fazer? Simples como voar, confira a seguir: - -```bash -root@linuxtips-01:~# docker node promote LINUXtips-03 -Node LINUXtips-03 promoted to a manager in the swarm. - -root@linuxtips-01:~# docker node ls -ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION -2qac LINUXtips-01 Ready Active Leader 18.03.1-ce -j6lm LINUXtips-02 Ready Active Reachable 18.03.1-ce -nmxl LINUXtips-03 Ready Active Reachable 18.03.1-ce - -root@linuxtips-01:~# -``` - -Se quiser tornar um *node manager* em *worker*, faça: - -```bash -root@linuxtips-01:~# docker node demote LINUXtips-03 -Node LINUXtips-03 demoted to a manager in the swarm. -``` - -Vamos conferir: - -```bash -root@linuxtips-01:~# docker node ls - -ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION -2qac LINUXtips-01 Ready Active Leader 18.03.1-ce -j6lm LINUXtips-02 Ready Active Reachable 18.03.1-ce -nmxl LINUXtips-03 Ready Active 18.03.1-ce - -root@linuxtips-01:~# -``` - -Agora, caso você queira remover um *node* do *cluster*, basta digitar o -seguinte comando no *node* desejado: - -```bash -root@linuxtips-03:~# docker swarm leave -Node left the swarm. - -root@linuxtips-03:~# -``` - -E precisamos ainda executar o comando de remoção desse *node* também em -nosso *manager* ativo da seguinte forma: - -```bash -root@linuxtips-01:~# docker node rm LINUXtips-03 -LINUXtips-03 - -root@linuxtips-01:~# -``` - -Com isso, podemos executar o "docker node ls" e constatar que o *node* -foi realmente removido do *cluster*. Caso queira adicioná-lo novamente, -basta repetir o processo que foi utilizado para adicioná-lo, está -lembrado? :D - -Para remover um *node* *manager* de nosso *cluster*, precisamos -adicionar a *flag* "\--force" ao comando "docker swarm leave", como -mostrado a seguir: - -```bash -root@linuxtips-02:~# docker swarm leave --force -Node left the swarm. - -root@linuxtips-02:~# -``` - -Agora, basta removê-lo também em nosso *node manager*: - -```bash -root@linuxtips-01:~# docker node rm LINUXtips-02 -LINUXtips-02 - -root@linuxtips-01:~# -``` - -## 13.2. O sensacional *services*! - -Uma das melhores coisas que o Docker Swarm nos oferece é justamente a -possibilidade de fazer o uso dos *services*. - -O *services* nada mais é do que um VIP ou DNS que realizará o -balanceamento de requisições entre os *containers*. Podemos estabelecer -um número x de *containers* respondendo por um *service* e esses -*containers* estarão espalhados pelo nosso *cluster*, entre nossos -*nodes*, garantindo alta disponibilidade e balanceamento de carga, tudo -isso nativamente! - -O *services* é uma forma, já utilizada no Kubernetes, de você conseguir -gerenciar melhor seus *containers*, focando no serviço que esses -*containers* estão oferecendo e garantindo alta disponibilidade e -balanceamento de carga. É uma maneira muito simples e efetiva para -escalar seu ambiente, aumentando ou diminuindo a quantidade de -*containers* que responderá para um determinado *service*. - -Meio confuso? Sim eu sei, mas vai ficar fácil. :) - -Imagine que precisamos disponibilizar o serviço do Nginx para ser o novo -*web server*. Antes de criar esse *service*, precisamos de algumas -informações: - -- Nome do *service* que desejo criar - >**webserver**. - -- Quantidade de *containers* que desejo debaixo do *service* - > **5**. - -- Portas que iremos "bindar", entre o *service* e o *node* - > **8080:80**. - -- Imagem dos *containers* que irei utilizar - > **nginx**. - -Agora que já temos essas informações, 'bora criar o nosso primeiro -service. :) - -```bash -root@linuxtips-01:~# docker service create --name webserver --replicas 5 -p 8080:80 nginx -0azz4psgfpkf0i5i3mbfdiptk - -root@linuxtips-01:~# -``` - -Agora já temos o nosso *service* criado. Para testá-lo, basta executar: - -```bash -root@linuxtips-01:~# curl QUALQUER_IP_NODES_CLUSTER:8080 -``` - -O resultado do comando anterior lhe trará a página de boas-vindas do -Nginx. - -Como estamos utilizando o *services*, cada conexão cairá em um -*container* diferente, fazendo assim o balanceamento de cargas -"automagicamente"! - -Para visualizar o *service* criado, execute: - -```bash -root@linuxtips-01:~# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS -0azz4p webserver replicated 5/5 nginx:lates *:8080->80/tcp -``` - -Conforme podemos notar, temos o *service* criado e com ele cinco -réplicas em execução, ou seja, cinco *containers* em execução. - -Se quisermos saber onde estão rodando nossos *containers*, em quais -*nodes* eles estão sendo executados, basta digitar o seguinte comando: - -```bash -root@linuxtips-01:~# docker service ps webserver -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -zbt1j webserver.1 nginx:latest LINUXtips-01 Running Running 8 minutes ago -iqm9p webserver.2 nginx:latest LINUXtips-02 Running Running 8 minutes ago -jliht webserver.3 nginx:latest LINUXtips-01 Running Running 8 minutes ago -qcfth webserver.4 nginx:latest LINUXtips-03 Running Running 8 minutes ago -e17um webserver.5 nginx:latest LINUXtips-02 Running Running 8 minutes ago - -root@linuxtips-01:~# -``` - -Assim conseguimos saber onde está rodando cada *container* e ainda o seu -*status*. - -Se eu preciso saber maiores detalhes sobre o meu *service*, basta -utilizar o subcomando "inspect". - -```bash -root@linuxtips-01:~# docker service inspect webserver -[ - { - "ID": "0azz4psgfpkf0i5i3mbfdiptk", - "Version": { - "Index": 29 - }, - "CreatedAt": "2017-06-09T19:35:58.180235688Z", - "UpdatedAt": "2017-06-09T19:35:58.18899891Z", - "Spec": { - "Name": "webserver", - "Labels": {}, - "TaskTemplate": { - "ContainerSpec": { - "Image": "nginx:latest@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268", - "StopGracePeriod": 10000000000, - "DNSConfig": {} - }, - "Resources": { - "Limits": {}, - "Reservations": {} - }, - "RestartPolicy": { - "Condition": "any", - "Delay": 5000000000, - "MaxAttempts": 0 - }, - "Placement": {}, - "ForceUpdate": 0 - }, - "Mode": { - "Replicated": { - "Replicas": 5 - } - }, - "UpdateConfig": { - "Parallelism": 1, - "FailureAction": "pause", - "Monitor": 5000000000, - "MaxFailureRatio": 0, - "Order": "stop-first" - }, - "RollbackConfig": { - "Parallelism": 1, - "FailureAction": "pause", - "Monitor": 5000000000, - "MaxFailureRatio": 0, - "Order": "stop-first" - }, - "EndpointSpec": { - "Mode": "vip", - "Ports": [ - { - "Protocol": "tcp", - "TargetPort": 80, - "PublishedPort": 8080, - "PublishMode": "ingress" - } - ] - } - }, - "Endpoint": { - "Spec": { - "Mode": "vip", - "Ports": [ - { - "Protocol": "tcp", - "TargetPort": 80, - "PublishedPort": 8080, - "PublishMode": "ingress" - } - ] - }, - "Ports": [ - { - "Protocol": "tcp", - "TargetPort": 80, - "PublishedPort": 8080, - "PublishMode": "ingress" - } - ], - "VirtualIPs": [ - { - "NetworkID": "89t2aobeik8j7jcre8lxhj04l", - "Addr": "10.255.0.5/16" - } - ] - } - } -] - -root@linuxtips-01:~# -``` - -Na saída do "inspect" conseguiremos pegar informações importantes sobre -nosso *service*, como portas expostas, volumes, *containers*, -limitações, entre outras coisas. - -Uma informação muito importante é o endereço do VIP do *service*: - -```json - "VirtualIPs": [ - { - "NetworkID": "89t2aobeik8j7jcre8lxhj04l", - "Addr": "10.255.0.5/16" - } - ] -``` - -Esse é o endereço IP do "balanceador" desse *service*, ou seja, sempre -que acessarem via esse IP, ele distribuirá a conexão entre os -*containers*. Simples, não? - -Agora, se quisermos aumentar o número de *containers* debaixo desse -*service*, é muito simples. Basta executar o comando a seguir: - -```bash -root@linuxtips-01:~# docker service scale webserver=10 -webserver scaled to 10 - -root@linuxtips-01:~# -``` - -Pronto, simples assim! - -Agora já temos dez *containers* respondendo requisições debaixo do nosso -*service* *webserver*! Simples como voar! - -Para visualizar, basta executar: - -```bash -root@linuxtips-01:~# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS -0azz webserver replicated 10/10 nginx:latest *:8080->80/tcp - -root@linuxtips-01:~# -``` - -Para saber em quais *nodes* eles estão em execução, lembre-se do "docker -service ls webserver". - -Para acessar os *logs* desse *service*, basta digitar: - -```bash -root@linuxtips-01:~# docker service logs -f webserver -webserver.5.e17umj6u6bix@LINUXtips-02 | 10.255.0.2 - - [09/Jun/2017:19:36:12 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-" -``` - -Assim, você terá acesso aos *logs* de todos os *containers* desse -*service*. Muito prático! - -"Cansei de brincar! Quero remover esse meu *service*!" É tão simples -quanto criá-lo. Digite: - -```bash -root@linuxtips-01:~# docker service rm webserver -webserver - -root@linuxtips-01:~# -``` - -Pronto! Seu *service* foi excluído e você pode conferir na saída do -comando a seguir: - -```bash -root@linuxtips-01:~# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS - -root@linuxtips-01:~# -``` - -Criar um *service* com um volume conectado é bastante simples. Faça: - -```bash -root@linuxtips-01:~# docker service create --name webserver --replicas 5 -p 8080:80 --mount type=volume,src=teste,dst=/app nginx -yfheu3k7b8u4d92jemglnteqa - -root@linuxtips-01:~# -``` - -Quando eu crio um *service* com um volume conectado a ele, isso indica -que esse volume estará disponível em todos os meus *containers* desse -*service*, ou seja, o volume com o nome de "teste" estará montado em -todos os *containers* no diretório "/app"*.* - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_14.md b/capitulos/CHAPTER_14.md deleted file mode 100644 index 46c0302..0000000 --- a/capitulos/CHAPTER_14.md +++ /dev/null @@ -1,244 +0,0 @@ -
- -# 14. Docker Secrets - -Ninguém tem dúvida de que a arquitetura de microsserviços já se provou -eficiente. Porém, implementar segurança, principalmente em um contexto -de infraestrutura imutável, tem sido um belo desafio. - -Com questões que envolvem desde como separar a senha do *template* em -uma imagem até como trocar a senha de acesso a um serviço sem -interrompê-lo, *workarounds* não faltam. Mas como sempre dá para -melhorar, na versão 1.13 nossos queridos amigos do Docker lançaram o que -foi chamado de Docker Secrets. - -O Docker Secrets é a solução do Docker para trabalhar com toda a parte -de *secrets* em um ambiente *multi-node* e *multi-container.* Em outras -palavras, um *"swarm mode" cluster*. A *secret* pode conter qualquer -coisa, porém deve ter um tamanho máximo de 500 KB. Por enquanto essa -belezinha não está disponível fora do contexto do Docker Swarm -- na -verdade, não é claro se vai algum dia ser diferente. Por enquanto somos -encorajados a usar um *service* para fazer *deploy* de *containers* -individuais. - -## 14.1. O comando *docker secret* - -O comando "docker secret" vem com alguns subcomandos. São eles: - -```bash -docker secret --help - -Usage: docker secret COMMAND - -Manage Docker secrets - -Options: - --help Print usage - -Commands: - create Create a secret from a file or STDIN as content - inspect Display detailed information on one or more secrets - ls List secrets - rm Remove one or more secrets - -Run 'docker secret COMMAND --help' for more information on a command. -``` - -- **create** -- Cria uma *secret* a partir do conteúdo de um arquivo ou STDIN. - -- **inspect** -- Mostra informações detalhadas de uma ou mais *secrets*. - -- **ls** -- Lista as *secrets* existentes. - -- **rm** -- Remove uma ou mais *secrets*. - -**Create** - -Como dito, o "create" aceita conteúdo tanto do STDIN\... - -```bash -root@linuxtips:~# echo 'minha secret' | docker secret create minha_secret - -jxr0pilzhtqsiqi1f1fjmmg4t - -root@linuxtips:~# -``` - -...quanto de um arquivo: - -```bash -root@linuxtips:~# docker secret create minha_secret minha_secret.txt -ci7mse43i5ak378sg3qc4xt04 - -root@linuxtips:~# -``` - -**Inspect** - -Fique tranquilo, o "inspect" não mostra o conteúdo da sua *secret*! :P - -Em vez disso, ele mostra uma série de informações sobre a *secret*, -incluindo sua criação e modificação (apesar de não ter, na verdade, como -modificar uma *secret*; uma vez criada, ela não pode ser atualizada via -CLI, porém já há um *endpoint* na API do Docker Swarm para *update* de -*secret* -- "/secrets/{id}/update", vamos aguardar!) - -```bash -root@linuxtips:~# docker secret inspect minha_secret -[ - { - "ID": "ci7mse43i5ak378sg3qc4xt04", - "Version": { - "Index": 808 - }, - "CreatedAt": "2017-07-02T17:17:18.143116694Z", - "UpdatedAt": "2017-07-02T17:17:18.143116694Z", - "Spec": { - "Name": "minha_secret", - "Labels": {} - } - } -] - -root@linuxtips:~# -``` - -O "inspect" aceita mais de uma *secret* por vez e mostrará o resultado -na mesma sequência. - -**ls && rm** - -Servem respectivamente para listar suas *secrets* e removê-las. - -```bash -root@linuxtips:~# docker secret ls -ID NAME CREATED UPDATED -ci7mse43i5ak378sg3qc4xt04 minha_secret About a minute ago About a minute ago - -root@linuxtips:~# -root@linuxtips:~# docker secret rm minha_secret -minha_secret - -root@linuxtips:~# -``` - -## 14.2. Tudo bem, mas como uso isso? - -As *secrets* são consumidas por serviços, como já citamos, e isso -acontece através de associação explícita, usando a *flag* "\--secret" na -hora de criar um serviço. Vamos para um exemplo. - -Primeiro vamos criar uma *secret* com a senha do banco de dados da nossa -aplicação *fake.* - -```bash -root@linuxtips:~# echo 'senha_do_banco' | docker secret create db_pass - -kxzgmhlu3ytv64hbqzg30nc8u - -root@linuxtips:~# -``` - -Agora, vamos associá-la à nossa *app*, criando um serviço. - -```bash -root@linuxtips:~# docker service create --name app --detach=false --secret db_pass minha_app:1.0 -npfmry3vcol61cmcql3jiljk2 -overall progress: 1 out of 1 tasks -1/1: running [==================================================>] -verify: Waiting 1 seconds to verify that tasks are stable... - -root@linuxtips:~# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS -npfmry3vcol6 app replicated 1/1 minha_app:1.0 - -root@linuxtips:~# docker container ls -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -65d1533f5b50 minha_app:1.0 "/bin/sh -c ./scri..." 40 seconds ago Up 39 seconds app.1.molbmj0649c7xkzfermkuwrx2 - -root@linuxtips:~# -``` - -Também é possível dar acesso a *keys* para serviços já criados, através -da *flag* "\--secret-add" do comando "docker service update", assim como -revogá-las, usando a *flag* "\--secret-rm" no mesmo comando. Ver o -tópico "Atualizando a *secret* de um serviço". - -## 14.3. Acessando a *secret* - -Com o serviço criado, a *secret* ficará disponível para todos os -*containers* daquele *service* e estará em arquivos dentro do diretório -"/run/secrets", montado em *tmpfs*. Se a sua *secret* chamar "db\_pass", -como no exemplo, o conteúdo dela estará em "/run/secrets/db\_pass". - -É possível incluir alguns parâmetros na hora de adicionar uma *secret* a -um serviço, como, por exemplo, o *target*, que altera o nome do arquivo -no destino e até itens de segurança, como *uid*, *gid* e *mode*: - -docker service create \--detach=false \--name app \--secret -source=db\_pass,target=password,uid=2000,gid=3000,mode=0400 -minha\_app:1.0 - -Dentro do *container* ficaria assim: - -```bash -root@4dd6b9cbff1a:/app# ls -lhart /run/secrets/ -total 12K --r-------- 1 2000 3000 15 Jul 2 17:44 password -drwxr-xr-x 7 root root 4.0K Jul 2 17:44 .. -drwxr-xr-x 2 root root 4.0K Jul 2 17:44 . - -root@4dd6b9cbff1a:/app# -``` - -E aí basta que a sua aplicação leia o conteúdo do arquivo. - -```bash -root@8b16b5335334:/app# python -Python 2.7.12 (default, Nov 19 2016, 06:48:10) -[GCC 5.4.0 20160609] on linux2 -Type "help", "copyright", "credits" or "license" for more information. ->>> ->>> secret = open('/run/secrets/password').read() ->>> ->>> print "minha secret e: %s" % (secret) -minha secret e: nova_senha ->>> -``` - -## 14.4. Atualizando a *secret* de um serviço - -*Secrets* foram criadas para serem imutáveis, ou seja, caso você queira -trocar a *secret* de um serviço, você precisará criar outra *secret*. A -troca da *secret* é bem fácil. Por exemplo, para trocar a *secret* -"db\_pass" do exemplo anterior, teríamos que fazer o seguinte: - -Criar uma nova *secret*: - -```bash -root@linuxtips:~# echo 'nova_senha' | docker secret create db_pass_1 - -221uzilbsl1ybna7g7014hoqr - -root@linuxtips:~# -``` - -Adicionar à *secret* a *app* criada anteriormente: - -```bash -root@linuxtips:~# docker service update --secret-rm db_pass --detach=false --secret-add source=db_pass_1,target=password app -app -overall progress: 1 out of 1 tasks -1/1: running [==================================================>] -verify: Waiting 1 seconds to verify that tasks are stable... - -root@linuxtips:~# -``` - -Após a atualização, basta remover a *secret* antiga: - -```bash -root@linuxtips:~# docker secret rm db_pass -db_pass - -root@linuxtips:~# -``` - -
\ No newline at end of file diff --git a/capitulos/CHAPTER_15.md b/capitulos/CHAPTER_15.md deleted file mode 100644 index 8e4843d..0000000 --- a/capitulos/CHAPTER_15.md +++ /dev/null @@ -1,859 +0,0 @@ -
- -# 15. Docker Compose - -Bem, agora chegamos em uma das partes mais importantes do livro, o -sensacional e completo Docker Compose! - -O Docker Compose nada mais é do que uma forma de você conseguir escrever -em um único arquivo todos os detalhes do ambiente de sua aplicação. -Antes nós usávamos o *dockerfile* apenas para criar imagens, seja da -minha aplicação, do meu BD ou do meu *webserver*, mas sempre de forma -unitária, pois tenho um *dockerfile* para cada "tipo" de *container*: um -para a minha *app*, outro para o meu BD e assim por diante. - -Com o Docker Compose nós falamos sobre o ambiente inteiro. Por exemplo, -no Docker Compose nós definimos quais os *services* que desejamos criar -e quais as características de cada *service* (quantidade de *containers* -debaixo daquele *service*, volumes, *network*, *secrets*, etc.). - -O padrão que os *compose files* seguem é o YML, supersimples e de fácil -entendimento, porém sempre é bom ficar ligado na sintaxe que o padrão -YML lhe impõe. ;) - -Bem, vamos parar de falar e começar a brincadeira! - -Antes a gente precisava instalar o Docker Compose para utilizá-lo. -Porém, hoje nós temos o subcomando "docker stack", já disponível junto à -instalação do Docker. Ele é responsável por realizar o *deploy* de -nossos *services* através do Docker Compose de maneira simples, rápida e -muito efetiva. - -'Bora começar! A primeira coisa que devemos realizar é a própria criação -do *compose file*. Vamos começar por um mais simples e vamos aumentando -a complexidade conforme evoluímos. - -Lembre-se: para que possamos seguir com os próximos exemplos, o seu -*cluster* *swarm* deverá estar funcionando perfeitamente. Portanto, se -ainda não estiver com o *swarm* ativo, execute: - -```bash -# docker swarm init -``` - -Vamos criar um diretório chamado "Composes", somente para que possamos -organizar melhor nossos arquivos. - -```bash -# mkdir /root/Composes -# mkdir /root/Composes/1 -# cd /root/Composes/1 -# vim docker-compose.yml -``` - -```yaml -version: "3" - -services: - web: - image: nginx - deploy: - replicas: 5 - resources: - limits: - cpus: "0.1" - memory: 50M - restart_policy: - condition: on-failure - ports: - - "8080:80" - networks: - - webserver - -networks: - webserver: -``` - -Pronto! Agora já temos o nosso primeiro *docker-compose*. O que -precisamos agora é realizar o *deploy*, porém antes vamos conhecer -algumas opções que utilizamos anteriormente: - -- **version: \"3\" --** Versão do *compose* que estamos utilizando. - -- **services:** -- Início da definição de meu serviço. - -- **web: *--*** Nome do serviço. - -- **image: nginx** -- Imagem que vamos utilizar. - -- **deploy: --** Início da estratégia de *deploy*. - -- **replicas: 5** -- Quantidade de réplicas. - -- **resources:** -- Início da estratégia de utilização de recursos. - -- **limits:** -- Limites. - -- **cpus: \"0.1\"** -- Limite de CPU. - -- **memory: 50M** -- Limite de memória. - -- **restart\_policy:** -- Políticas de *restart*. - -- **condition: on-failure** -- Somente irá "restartar" o *container* em caso de falha. - -- **ports:** -- Quais portas desejamos expor. - -- **- \"8080:80\"** -- Portas expostas e "bindadas". - -- **networks:** -- Definição das redes que irei utilizar nesse serviço. - -- ***-* webserver** -- Nome da rede desse serviço. - -- **networks:** -- Declarando as redes que usaremos nesse *docker-compose*. - -- **webserver:** -- Nome da rede a ser criada, caso não exista. - -Simples como voar, não? :D - -## 15.1. O comando *docker stack* - -Agora precisamos realizar o *deploy* desse *service* através do *compose -file* que criamos. Para isso, vamos utilizar o sensacional "docker -stack": - -```bash -root@linuxtips-01:~/Composes/1# docker stack deploy -c docker-compose.yml primeiro -Creating network primeiro_webserver -Creating service primeiro_web - -root@linuxtips-01:~/Composes/1# -``` - -Simples assim, e nosso service já está disponível para uso. Agora vamos -verificar se realmente o *service* subiu e se está respondendo conforme -esperado: - -```bash -root@linuxtips-01:~/Composes/1# curl 0:8080 - - - - Welcome to nginx! - - - -

Welcome to nginx!

-

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

-

For online documentation and support please refer to - nginx.org.
- Commercial support is available at - nginx.com.

-

Thank you for using nginx.

- - - -root@linuxtips-01:~/Composes/1# -``` - -Sensacional, o nosso *service* está em pé, pois recebemos a página de -boas-vindas do Nginx! - -Vamos verificar se está tudo certo com o *service*: - -```bash -root@linuxtips-01:~/Composes/1# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS -mw95t primeiro_web replicated 5/5 nginx:latest *:8080->80/tcp - -root@linuxtips-01:~/Composes/1# docker service ps primeiro_web -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -lrcqo8ifultq primeiro_web.1 nginx:latest LINUXtips-02 Running Running 2 minutes ago -ty16mkcqdwyl primeiro_web.2 nginx:latest LINUXtips-03 Running Running 2 minutes ago -dv670shw22o2 primeiro_web.3 nginx:latest LINUXtips-01 Running Running 2 minutes ago -sp0k1tnjftnr primeiro_web.4 nginx:latest LINUXtips-01 Running Running 2 minutes ago -4fpl35llq1ih primeiro_web.5 nginx:latest LINUXtips-03 Running Running 2 minutes ago - -root@linuxtips-01:~/Composes/1# -``` - -Para listar todos os *stacks* criados, basta executar: - -```bash -root@linuxtips-01:~/Composes/1# docker stack ls -NAME SERVICES -primeiro 1 - -root@linuxtips-01:~/Composes/1# -``` - -Perceba: a saída diz que possuímos somente um *stack* criado e esse -*stack* possui um *service*, que é exatamente o nosso do Nginx. - -Para visualizar os *services* que existem em determinado *stack*, -execute: - -```bash -root@linuxtips-01:~/Composes/1# docker stack services primeiro -ID NAME MODE REPLICAS IMAGE PORTS -mx0p4vbrzfuj primeiro_web replicated 5/5 nginx:latest *:8080->80/tcp - -root@linuxtips-01:~/Composes/1# -``` - -Podemos verificar os detalhes do nosso *stack* criado através do comando -a seguir: - -```bash -root@linuxtips-01:~/Composes/1# docker stack ps primeiro -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -x3u03509w9u3 primeiro_web.1 nginx:latest LINUXtips-03 Running Running 5 seconds ago -3hpu5lo6yvld primeiro_web.2 nginx:latest LINUXtips-02 Running Running 5 seconds ago -m82wbwuwoza0 primeiro_web.3 nginx:latest LINUXtips-03 Running Running 5 seconds ago -y7vizedqvust primeiro_web.4 nginx:latest LINUXtips-02 Running Running 5 seconds ago -wk0acjnyl6jm primeiro_web.5 nginx:latest LINUXtips-01 Running Running 5 seconds ago - -root@linuxtips-01:~/Composes/1# -``` - -Maravilha! Nosso *service* está *UP* e tudo está em paz! - -Em poucos minutos subimos o nosso *service* do Nginx em nosso *cluster* -utilizando o *docker-compose* e o "docker stack", simples como voar! - -Agora vamos imaginar que eu queira remover esse meu *service*. Como eu -faço? Simples: - -```bash -root@linuxtips-01:~/Composes/1# docker stack rm primeiro -Removing service primeiro_web -Removing network primeiro_webserver - -root@linuxtips-01:~/Composes/1# -``` - -Para verificar se realmente removeu o *service*: - -```bash -root@linuxtips-01:~/Composes/1# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS - -root@linuxtips-01:~/Composes/1# -``` - -Pronto! Nosso *service* está removido! - -Vamos aumentar um pouco a complexidade na criação de nosso -*docker-compose* nesse novo exemplo. - -Vamos criar mais um diretório, onde criaremos o nosso novo *compose -file*: - -```bash -root@linuxtips-01:~/Composes# mkdir 2 -root@linuxtips-01:~/Composes# cd 2 -root@linuxtips-01:~/Composes# vim docker-compose.yml -``` - -```yaml -version: '3' - services: - db: - image: mysql:5.7 - volumes: - - db_data:/var/lib/mysql - environment: - MYSQL_ROOT_PASSWORD: somewordpress - MYSQL_DATABASE: wordpress - MYSQL_USER: wordpress - MYSQL_PASSWORD: wordpress - - wordpress: - depends_on: - - db - image: wordpress:latest - ports: - - "8000:80" - environment: - WORDPRESS_DB_HOST: db:3306 - WORDPRESS_DB_USER: wordpress - WORDPRESS_DB_PASSWORD: wordpress - -volumes: - db_data: -``` - -Perfeito! - -Nesse exemplo estamos conhecendo mais algumas opções que podemos -utilizar no *docker-compose*. São eles: - -- **volumes:** -- Definição dos volumes utilizados pelo *service*. - -- **- db\_data:/var/lib/mysql** -- Volume e destino. - -- **environment:** -- Definição de variáveis de ambiente utilizados pelo *service.* - -- **MYSQL\_ROOT\_PASSWORD: somewordpress** -- Variável e valor. - -- **MYSQL\_DATABASE: wordpress** -- Variável e valor. - -- **MYSQL\_USER: wordpress** -- Variável e valor. - -- **MYSQL\_PASSWORD: wordpress** -- Variável e valor. - -- **depends\_on:** -- Indica que esse *service* depende de outro para subir. - -- **- db** -- Nome do service que necessário para sua execução. - -Muito simples, não?!? - -Agora vamos realizar o *deploy* desse exemplo. Como se pode perceber, o -nosso *stack* é composto por dois *services*, o Wordpress e o MySQL. - -```bash -root@linuxtips-01:~/Composes/2# docker stack deploy -c docker-compose.yml segundo -Creating network segundo_default -Creating service segundo_db -Creating service segundo_wordpress - -root@linuxtips-01:~/Composes/2# -``` - -Conforme esperado, ele realizou a criação dos dois *services* e da rede -do *stack*. - -Para acessar o seu Wordpress, basta acessar em um navegador: - -***http://SEU\_IP:8000*** - -Seu Wordpress está pronto para uso! - -Para verificar se correu tudo bem com os *services*, lembre-se dos -comandos: - -```bash -root@linuxtips-01:~/Composes/1# docker stack ls -root@linuxtips-01:~/Composes/1# docker stack services segundo -root@linuxtips-01:~/Composes/1# docker service ls -root@linuxtips-01:~/Composes/1# docker service ps segundo_db -root@linuxtips-01:~/Composes/1# docker service ps segundo_wordpress -``` - -Para visualizar os *logs* de determinado *service*: - -```bash -root@linuxtips-01:~/Composes/2# docker service logs segundo_wordpress -segundo_wordpress.1.r6reuq8fsil0@LINUXtips-01 | WordPress not found in /var/www/html - copying now... -segundo_wordpress.1.r6reuq8fsil0@LINUXtips-01 | Complete! WordPress has been successfully copied to /var/www/html -segundo_wordpress.1.r6reuq8fsil0@LINUXtips-01 | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.0.4.5. Set the 'ServerName' directive globally to suppress this message -segundo_wordpress.1.r6reuq8fsil0@LINUXtips-01 | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.0.4.5. Set the 'ServerName' directive globally to suppress this message -segundo_wordpress.1.r6reuq8fsil0@LINUXtips-01 | [Sun Jun 11 10:32:47.392836 2017] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.6.30 configured -- resuming normal operations -segundo_wordpress.1.r6reuq8fsil0@LINUXtips-01 | [Sun Jun 11 10:32:47.392937 2017] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND' - -root@linuxtips-01:~/Composes/2# -``` - -E se for necessária uma modificação em meu *stack* e depois um -*re-deploy*, como eu faço? É possível? - -Claro! Afinal, Docker é muita vida! - -```bash -root@linuxtips-01:~/Composes# mkdir 3 -root@linuxtips-01:~/Composes# cd 3 -root@linuxtips-01:~/Composes/3# vim docker-compose.yml -``` - -```yaml -version: "3" - services: - web: - image: nginx - deploy: - replicas: 5 - resources: - limits: - cpus: "0.1" - memory: 50M - restart_policy: - condition: on-failure - ports: - - "8080:80" - networks: - - webserver - - visualizer: - image: dockersamples/visualizer:stable - ports: - - "8888:8080" - volumes: - - "/var/run/docker.sock:/var/run/docker.sock" - deploy: - placement: - constraints: [node.role == manager] - - networks: - - webserver - -networks: - webserver: -``` - -Perceba que apenas adicionamos um novo *service* ao nosso *stack*, o -*visualizer*. A ideia é realizar o *update* somente no *stack* para -adicionar o *visualizer*, sem deixar indisponível o *service* *web.* - -Antes de realizarmos o *update* desse *stack*, vamos conhecer as novas -opções que estão no *compose file* desse exemplo: - -**deploy:** - -- **placement:** -- Usado para definir a localização do nosso *service.* - -- **constraints: \[node.role == manager\]** -- Regra que obriga a criação desse *service* somente nos *nodes manager*. - -Agora vamos atualizar o nosso *stack*: - -```bash -root@linuxtips-01:~/Composes/3# docker stack deploy -c docker-compose.yml primeiro -Creating service primeiro_visualizer -Updating service primeiro_web (id: mx0p4vbrzfujk087c3xe2sjvo) - -root@linuxtips-01:~/Composes/3# -``` - -Perceba que, para realizar o *update* do *stack*, utilizamos o mesmo -comando que usamos para realizar o primeiro *deploy* do *stack*, o -"docker stack deploy". - -Que tal aumentar ainda mais a complexidade e o número de *services* de -um *stack*? 'Bora? - -Para esse exemplo, vamos utilizar um projeto do próprio Docker -([https://github.com/dockersamples/example-voting-app](https://github.com/dockersamples/example-voting-app)), -onde teremos diversos *services*. Vamos criar mais um diretório para -receber o nosso projeto: - -```bash -root@linuxtips-01:~/Composes# mkdir 4 -root@linuxtips-01:~/Composes# cd 4 -root@linuxtips-01:~/Composes/4# vim compose-file.yml -``` - -```yaml -version: "3" - -services: - redis: - image: redis:alpine - ports: - - "6379" - networks: - - frontend - deploy: - replicas: 2 - update_config: - parallelism: 2 - delay: 10s - restart_policy: - condition: on-failure - - db: - image: postgres:9.4 - volumes: - - db-data:/var/lib/postgresql/data - networks: - - backend - deploy: - placement: - constraints: [node.role == manager] - - vote: - image: dockersamples/examplevotingapp_vote:before - ports: - - 5000:80 - networks: - - frontend - depends_on: - - redis - deploy: - replicas: 2 - update_config: - parallelism: 2 - restart_policy: - condition: on-failure - - result: - image: dockersamples/examplevotingapp_result:before - ports: - - 5001:80 - networks: - - backend - depends_on: - - db - deploy: - replicas: 1 - update_config: - parallelism: 2 - delay: 10s - restart_policy: - condition: on-failure - - worker: - image: dockersamples/examplevotingapp_worker - networks: - - frontend - - backend - deploy: - mode: replicated - replicas: 1 - labels: [APP=VOTING] - restart_policy: - condition: on-failure - delay: 10s - max_attempts: 3 - window: 120s - placement: - constraints: [node.role == manager] - - visualizer: - image: dockersamples/visualizer:stable - ports: - - "8080:8080" - stop_grace_period: 1m30s - volumes: - - "/var/run/docker.sock:/var/run/docker.sock" - deploy: - placement: - constraints: [node.role == manager] -networks: - frontend: - backend: - -volumes: - db-data: -``` - -Ficou mais complexo ou não? Acho que não, pois no Docker tudo é bastante -simples! - -Temos algumas novas opções nesse exemplo, vamos conhecê-las: - -**deploy:** - -- **mode: replicated** -- Qual é o tipo de deployment? Temos dois, o *global* e o *replicated*. No *replicated* você escolhe a quantidade de réplicas do seu *service*, já no *global* você não escolhe a quantidade de réplicas, ele irá subir uma réplica por *node* de seu *cluster* (uma réplica em cada *node* de seu *cluster*). - -**update\_config:** - -- **parallelism: 2** -- Como irão ocorrer os updates (no caso, de 2 em 2). - -- **delay: 10s** -- Com intervalo de 10 segundos. - -**restart\_policy:** - -- **condition: on-failure** -- Em caso de falha, *restart.* - -- **delay: 10s** -- Com intervalo de 10 segundos. - -- **max\_attempts: 3** -- Com no máximo três tentativas. - -- **window: 120s** -- Tempo para definir se o *restart* do *container* ocorreu com sucesso. - -Agora vamos realizar o *deploy* do nosso *stack*: - -```bash -root@linuxtips-01:~/Composes/4# docker stack deploy -c docker-compose.yml quarto -Creating network quarto_default -Creating network quarto_frontend -Creating network quarto_backend -Creating service quarto_worker -Creating service quarto_visualizer -Creating service quarto_redis -Creating service quarto_db -Creating service quarto_vote -Creating service quarto_result - -root@linuxtips-01:~/Composes/4# -``` - -Verificando os *services*: - -```bash -root@linuxtips-01:~/Composes/4# docker service ls -ID NAME MODE REPLICAS IMAGE PORTS -3hi3sx2on3t5 quarto_worker replicated 1/1 dockersamples/examplevotingapp_worker:latest -hbsp4fdcvgnz quarto_visualizer replicated 1/1 dockersamples/visualizer:stable :8080->8080/tcp -k6xuqbq7g55a quarto_db replicated 1/1 postgres:9.4 -p2reijydxnsw quarto_result replicated 1/1 dockersamples/examplevotingapp_result:before :5001->80/tcp -rtwnnkwftg9u quarto_redis replicated 2/2 redis:alpine :0->6379/tcp -w2ritqiklpok quarto_vote replicated 2/2 dockersamples/examplevotingapp_vote:before :5000->80/tcp - -root@linuxtips-01:~/Composes/4# -``` - -Lembre-se de sempre utilizar os comandos que já conhecemos para -visualizar *stack*, *services*, volumes, *container*, etc. - -Para acessar os services em execução, abra um navegador e vá aos -seguintes endereços: - -- **Visualizar a página de votação:** http://IP_CLUSTER:5000/ - -- **Visualizar a página de resultados:** http://IP_CLUSTER:5001/ - -- **Visualizar a página de com os *containers* e seus *nodes*:** http://IP_CLUSTER:8080/ - -Vamos para mais um exemplo. Agora vamos realizar o *deploy* de um -*stack* completo de monitoração para o nosso *cluster* e todas as demais -máquinas de nossa infraestrutura. Nesse exemplo vamos utilizar um -arquivo YML que realizará o *deploy* de diversos *containers* para que -possamos ter as seguintes ferramentas integradas: - -- **Prometheus** -- Para armazenar todas as métricas de nosso ambiente. - -- **cAdvisor** -- Para coletar informações dos *containers*. - -- **Node Exporter** -- Para coletar informações dos *nodes* do *cluster* e demais máquinas do ambiente. - -- **Netdata** -- Para coletar mais de 5 mil métricas de nossas máquinas, além de prover um *dashboard* sensacional. - -- **Rocket.Chat** -- Para que possamos nos comunicar com outros times e pessoas e também para integrá-lo ao sistema de monitoração, notificando quando os alertas acontecem. O Rocket.Chat é uma excelente alternativa ao Slack. - -- **AlertManager** -- Integrado ao Prometheus e ao Rocket.Chat, é o responsável por gerenciar nossos alertas. - -- **Grafana** -- Integrado à nossa solução de monitoração, ele é o responsável pelos *dashboards* que são produzidos através das métricas que estão armazenadas no Prometheus. - -Com esse *stack* é possível monitorar *containers*, VMs e máquinas -físicas. Porém, o nosso foco agora é somente no que se refere ao livro e -a este capítulo, ou seja, as informações contidas no *compose file* que -definirão nosso *stack*. - -Para maiores detalhes em relação ao *Giropops-Monitoring*, acesse o -repositório no endereço: -[https://github.com/badtuxx/giropops-monitoring](https://github.com/badtuxx/giropops-monitoring). - -Antes de conhecer nosso *compose file*, precisamos realizar o clone do -projeto: - -```bash -# git clone https://github.com/badtuxx/giropops-monitoring.git -``` - -Acesse o diretório "giropops-monitoring": - -```bash -# cd giropops-monitoring -``` - -O nosso foco aqui será em três caras: o arquivo "grafana.config", o -diretório "conf" e o nosso querido e idolatrado "docker-compose.yml". - -O arquivo "grafana.config" contém variáveis que queremos passar ao nosso -Grafana. Nesse momento a única informação importante é o *password* do -*admin*, usuário que utilizaremos para logar na interface web do -Grafana. - -O diretório "conf" possui os arquivos necessários para que a integração -entre as aplicações de nosso *stack* funcionem corretamente. - -Já o nosso *compose file* traz todas as informações necessárias para que -nós possamos realizar o *deploy* de nosso *stack*. - -Como o nosso foco é o *compose file*, 'bora lá conhecê-lo! - -```bash -# cat docker-compose.yml -version: '3.3' -services: - prometheus: - image: linuxtips/prometheus_alpine - volumes: - - ./conf/prometheus/:/etc/prometheus/ - - prometheus_data:/var/lib/prometheus - networks: - - backend - ports: - - 9090:9090 - - node-exporter: - image: linuxtips/node-exporter_alpine - hostname: '{{.Node.ID}}' - volumes: - - /proc:/usr/proc - - /sys:/usr/sys - - /:/rootfs - deploy: - mode: global - networks: - - backend - ports: - - 9100:9100 - - alertmanager: - image: linuxtips/alertmanager_alpine - volumes: - - ./conf/alertmanager/:/etc/alertmanager/ - networks: - - backend - ports: - - 9093:9093 - - cadvisor: - image: google/cadvisor - hostname: '{{.Node.ID}}' - volumes: - - /:/rootfs:ro - - /var/run:/var/run:rw - - /sys:/sys:ro - - /var/lib/docker/:/var/lib/docker:ro - - /var/run/docker.sock:/var/run/docker.sock:ro - networks: - - backend - deploy: - mode: global - ports: - - 8080:8080 - - grafana: - image: nopp/grafana_alpine - depends_on: - - prometheus - volumes: - - ./conf/grafana/grafana.db:/grafana/data/grafana.db - env_file: - - grafana.config - networks: - - backend - - frontend - ports: - - 3000:3000 - - # If you already has a RocketChat instance running, just comment the code of rocketchat, mongo and mongo-init-replica services bellow - rocketchat: - image: rocketchat/rocket.chat:latest - volumes: - - rocket_uploads:/app/uploads - environment: - - PORT=3080 - - ROOT_URL=http://YOUR_IP:3080 - - MONGO_URL=mongodb://giropops_mongo:27017/rocketchat - - MONGO_OPLOG_URL=mongodb://giropops_mongo:27017/local - depends_on: - - giropops_mongo - ports: - - 3080:3080 - - mongo: - image: mongo:3.2 - volumes: - - mongodb_data:/data/db - #- ./data/dump:/dump - command: mongod --smallfiles --oplogSize 128 --replSet rs0 - mongo-init-replica: - image: mongo:3.2 - command: 'mongo giropops_mongo/rocketchat --eval "rs.initiate({_id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017''} ]})"' - depends_on: - - giropops_mongo - -networks: - frontend: - backend: - -volumes: - prometheus_data: - grafana_data: - rocket_uploads: - mongodb_data: -``` - -Perceba que já conhecemos todas as opções que estão nesse exemplo, nada -de novo. :D - -O que precisamos agora é realizar o *deploy* de nosso *stack*: - -```bash -# docker stack deploy -c docker-compose.yml giropops -Creating network giropops_backend -Creating network giropops_frontend -Creating network giropops_default -Creating service giropops_grafana -Creating service giropops_rocketchat -Creating service giropops_mongo -Creating service giropops_mongo-init-replica -Creating service giropops_prometheus -Creating service giropops_node-exporter -Creating service giropops_alertmanager -Creating service giropops_cadvisor -``` - -Caso queira verificar se os *services* estão em execução: - -```bash -# docker service ls -``` - -Para listar os *stacks*: - -```bash -# docker stack ls -``` - -Para acessar os serviços do quais acabamos de realizar o *deploy*, basta -acessar os seguintes endereços: - -- **Prometheus**: http://SEU_IP:9090 - -- **AlertManager**: http://SEU_IP:9093 - -- **Grafana**: http://SEU_IP:3000 - -- **Node\_Exporter**: http://SEU_IP:9100 - -- **Rocket.Chat:** http://SEU_IP:3080 - -- **cAdivisor**: http://SEU_IP:8080 - -Para remover o *stack*: - -```bash -# docker stack rm giropops -``` - -Lembrando: para conhecer mais sobre o *giropops-monitoring* acesse o -repositório no GitHub e assista à série de vídeos em que o Jeferson fala -detalhadamente como montou essa solução: - -- **Repo**: - > [https://github.com/badtuxx/giropops-monitoring](https://github.com/badtuxx/giropops-monitoring) - -- **Vídeos**: - > [https://www.youtube.com/playlist?list=PLf-O3X2-mxDls9uH8gyCQTnyXNMe10iml](https://www.youtube.com/playlist?list=PLf-O3X2-mxDls9uH8gyCQTnyXNMe10iml) - -E assim termina a nossa jornada no mundo do Docker. Esperamos que você -tenha aprendido e, mais do que isso, tenha gostado de dividir esse tempo -conosco para falar sobre o que nós mais amamos, tecnologia! - -## 15.2. E já acabou? :( - -Esperamos que você tenha curtido viajar conosco durante o seu -aprendizado sobre *containers* e principalmente sobre o ecossistema do -Docker, que é sensacional! - -Não pare de aprender mais sobre Docker! Continue acompanhando o Canal -LinuxTips no [https://www.youtube.com/linuxtips](https://www.youtube.com/linuxtips) -e fique ligado no site do Docker, pois sempre tem novidades e ótima -documentação! - -Junte-se a nós no Discord para que possa acompanhar e tirar dúvidas que -possam ter surgido durante seus estudos! - -\#VAIIII - -
\ No newline at end of file diff --git a/_chapters/CHAPTER_00.md b/chapters/chapter_00.md similarity index 100% rename from _chapters/CHAPTER_00.md rename to chapters/chapter_00.md diff --git a/_chapters/CHAPTER_01.md b/chapters/chapter_01.md similarity index 100% rename from _chapters/CHAPTER_01.md rename to chapters/chapter_01.md diff --git a/_chapters/CHAPTER_02.md b/chapters/chapter_02.md similarity index 100% rename from _chapters/CHAPTER_02.md rename to chapters/chapter_02.md diff --git a/_chapters/CHAPTER_03.md b/chapters/chapter_03.md similarity index 100% rename from _chapters/CHAPTER_03.md rename to chapters/chapter_03.md diff --git a/_chapters/CHAPTER_04.md b/chapters/chapter_04.md similarity index 100% rename from _chapters/CHAPTER_04.md rename to chapters/chapter_04.md diff --git a/_chapters/CHAPTER_05.md b/chapters/chapter_05.md similarity index 100% rename from _chapters/CHAPTER_05.md rename to chapters/chapter_05.md diff --git a/_chapters/CHAPTER_06.md b/chapters/chapter_06.md similarity index 100% rename from _chapters/CHAPTER_06.md rename to chapters/chapter_06.md diff --git a/_chapters/CHAPTER_07.md b/chapters/chapter_07.md similarity index 100% rename from _chapters/CHAPTER_07.md rename to chapters/chapter_07.md diff --git a/_chapters/CHAPTER_08.md b/chapters/chapter_08.md similarity index 100% rename from _chapters/CHAPTER_08.md rename to chapters/chapter_08.md diff --git a/_chapters/CHAPTER_09.md b/chapters/chapter_09.md similarity index 100% rename from _chapters/CHAPTER_09.md rename to chapters/chapter_09.md diff --git a/_chapters/CHAPTER_10.md b/chapters/chapter_10.md similarity index 100% rename from _chapters/CHAPTER_10.md rename to chapters/chapter_10.md diff --git a/_chapters/CHAPTER_11.md b/chapters/chapter_11.md similarity index 100% rename from _chapters/CHAPTER_11.md rename to chapters/chapter_11.md diff --git a/_chapters/CHAPTER_12.md b/chapters/chapter_12.md similarity index 100% rename from _chapters/CHAPTER_12.md rename to chapters/chapter_12.md diff --git a/_chapters/CHAPTER_13.md b/chapters/chapter_13.md similarity index 100% rename from _chapters/CHAPTER_13.md rename to chapters/chapter_13.md diff --git a/_chapters/CHAPTER_14.md b/chapters/chapter_14.md similarity index 100% rename from _chapters/CHAPTER_14.md rename to chapters/chapter_14.md diff --git a/_chapters/CHAPTER_15.md b/chapters/chapter_15.md similarity index 100% rename from _chapters/CHAPTER_15.md rename to chapters/chapter_15.md diff --git a/index.markdown b/index.markdown deleted file mode 100644 index 235576c..0000000 --- a/index.markdown +++ /dev/null @@ -1,70 +0,0 @@ ---- -layout: default ---- - -# Prefácio - -If you are a developer, you probably have heard about Docker by now: -Docker is the ideal platform to run applications in containers. Fine, -but what are those containers? Containers are a lightweight -virtualization technique providing us with lots of possibilities: thanks -to them, we can ship applications faster; we can easily implement CI/CD -(continuous integration and continuous delivery); we can set up -development environments faster than ever; we can ensure parity between -those development environments and our production servers; and much -more. If you write code, if you deploy code, if you operate code, then I -promise that containers are going to make your life easier. - -But containers have been around for *decades*, and Docker was only -released in 2013. So what's the big deal? Why is everybody so excited -about Docker, if the technology behind it is more than ten years old? - -Because the main innovation of Docker is not the technology. The main -innovation of Docker is to make this technology available to every -developer and sysadmin, very easily, without having to spend years of -practice to become an expert, and without requiring to develop tons of -custom tools. - -I will share a secret with you: the really important thing is not Docker -and containers. What is really important is to improve the quality of -our software, reduce our development and deployment costs, release -better, more reliable code, faster. It turns out that Docker is an -insanely efficient way to achieve those goals. That's why it is so -popular. - -This book will teach you all you need to know to get started with -Docker, and use it to build, ship, and run your applications. It will be -your guide in the world of containers, and on the path to ship code -better than you ever did before. - -***Jérôme Petazzoni*** - -Docker Tinkerer Extraordinaire - -# Sobre o Livro - -A proposta deste livro é ajudá-lo a construir ambientes utilizando -*containers* com a ferramenta que está revolucionando as empresas de -tecnologia ao redor do mundo: vamos aprender e brincar bastante com o -sensacional Docker! - -De maneira leve e totalmente prática, vamos aprender desde o que é o -Docker até a criação de um *cluster* Docker com diversos *containers* em -execução! Sempre de forma prática, vamos abordar temas importantes para -que consiga administrar ambientes que utilizam ou pretendam utilizar o -Docker. - -Inclusive, vamos aprender a montar *dockerfiles* personalizados para -construção de imagens de *containers*, além de conhecer como melhor -administrá-las. - -Também veremos na prática como utilizar o Docker Machine para criação de -*hosts* Docker, seja local ou na nuvem. Vamos criar um *cluster* -utilizando o Swarm e aprender como escalar o nosso ambiente através do -Compose. - -Nesta segunda edição adicionamos muitas novidades, como o 'docker -secret' e o 'docker stack', e atualizamos praticamente todo o -restante do livro, visando torna-lo super atual e didático. Adicionamos -mais exemplos práticos, para que sua experiência possa ser ainda mais -agradável e proveitosa. diff --git a/package.json b/package.json new file mode 100644 index 0000000..8a25681 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "honkit": "^3.6.20" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..180edf4 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2235 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@asciidoctor/cli@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@asciidoctor/cli/-/cli-3.4.0.tgz#586e9133f3367c7b3236631197f4b621890d9227" + integrity sha512-jOtxA0I6zB+6z+GGwm9+xhlmGTqCTkFPE902L6fauFlE6v7LxjhLYNxvjDVyn0zMrFLybvoSRcAnM3DcticNoQ== + dependencies: + yargs "15.3.1" + +"@asciidoctor/core@2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@asciidoctor/core/-/core-2.2.5.tgz#b2874aff4d6733ba0819dbc8de9aaf1ae444aa11" + integrity sha512-jtQPQ5EivgFbwvSyGKas4ANnMGGHPbmu791H9xrZKooA65JNI30jM2em5MvUXTTetSPgb6saUf+PJibEuSB6uw== + dependencies: + asciidoctor-opal-runtime "0.3.3" + unxhr "1.0.1" + +"@honkit/asciidoc@^3.6.17": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@honkit/asciidoc/-/asciidoc-3.7.0.tgz#836ec0271fe4cec0682331f30df99a1e3c839214" + integrity sha512-pa0Uy0HFuRBY5NmATPTJTmiffP8kosJoN8Ilc+WgJNxZdG146LcDQ5KroggT5/kZDHZBFlAyuNFSbMRe1dgV+Q== + dependencies: + "@honkit/html" "^3.7.0" + asciidoctor "^2.2.0" + lodash "^4.13.1" + +"@honkit/honkit-plugin-highlight@^3.6.19": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@honkit/honkit-plugin-highlight/-/honkit-plugin-highlight-3.7.0.tgz#e07b7819ee18fb5f5ce98c8b58d9247b7434eeab" + integrity sha512-8qkpEnnYfFRtL+WpFSVSxwYQD0M28mRRxFULBXyQRbR2wBhMS9neKZ2uImgPKa7+tlhQsD+PvJnxfN1rslhbhw== + dependencies: + highlight.js "^10.7.1" + +"@honkit/honkit-plugin-theme-default@^3.6.20": + version "3.6.20" + resolved "https://registry.yarnpkg.com/@honkit/honkit-plugin-theme-default/-/honkit-plugin-theme-default-3.6.20.tgz#5160432afeae3471ba84b1cedef060bfb4f8b162" + integrity sha512-1JVaZk/8TYuauNEse+uDaZjje/Za1CwElHLuMZx5K9IZy9isqD/du/AHxESprIypMzxD6DFr0jsHx2F+C7l6Fg== + +"@honkit/html@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@honkit/html/-/html-3.7.0.tgz#6f2db571cd68c87b790f4bb99a6aefa73249311d" + integrity sha512-+D+BItUys90LTmLnU2dyqtnJoLKfv+ge+Qcj7x0LBMxGfL8wkY4GJD2rS+J+y+cyUPmueTxjvg2yoli61KvodQ== + dependencies: + cheerio "^0.20.0" + lodash "^4.13.1" + q "^1.1.2" + +"@honkit/markdown-legacy@^3.6.17": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@honkit/markdown-legacy/-/markdown-legacy-3.7.0.tgz#4c43242cefb25028da5cfbdfd0f7b2dcff7c1a4b" + integrity sha512-iLgLszjG5wVzsOvgpZBi6S/lnWyNq20uMrWfDYapgW8U0feXo7L6i7KAJSqp8EBKSs7Ae+v1q2SDjZfyikJtYQ== + dependencies: + "@honkit/html" "^3.7.0" + kramed "0.5.6" + lodash "^4.13.1" + +a-sync-waterfall@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" + integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== + +abab@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" + integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= + +acorn-globals@^1.0.4: + version "1.0.9" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" + integrity sha1-VbtemGkVB7dFedBRNBMhfDgMVM8= + dependencies: + acorn "^2.1.0" + +acorn@^2.1.0, acorn@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" + integrity sha1-q259nYhqrKiwhbwzEreaGYQz8Oc= + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-difference@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-difference/-/array-difference-0.0.1.tgz#c7cafd9b54b35eb82f72e7ba319e938a3fd32b07" + integrity sha1-x8r9m1SzXrgvcue6MZ6Tij/TKwc= + +asap@^2.0.0, asap@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +asciidoctor-opal-runtime@0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz#2667635f858d3eb3fdfcf6795cf68138e2040174" + integrity sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ== + dependencies: + glob "7.1.3" + unxhr "1.0.1" + +asciidoctor@^2.2.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/asciidoctor/-/asciidoctor-2.2.5.tgz#dfc2ba4fdee2f0d3b28759b21d57a5f302d79982" + integrity sha512-rrmCK34faw+w+xGFQggjwPB0/pcISnwOXaulfJvn7j4Nm0bFwz+x4tG3ZANIA9+9i6Csex/PO0fSLBO8CSdzVA== + dependencies: + "@asciidoctor/cli" "3.4.0" + "@asciidoctor/core" "2.2.5" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +async@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8" + integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bash-color@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/bash-color/-/bash-color-0.0.4.tgz#e9be8ce33540cada4881768c59bd63865736e913" + integrity sha1-6b6M4zVAytpIgXaMWb1jhlc26RM= + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +body@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069" + integrity sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk= + dependencies: + continuable-cache "^0.3.1" + error "^7.0.0" + raw-body "~1.1.0" + safe-json-parse "~1.0.1" + +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +buffer@^5.1.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bytes@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" + integrity sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g= + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +cheerio@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.20.0.tgz#5c710f2bab95653272842ba01c6ea61b3545ec35" + integrity sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU= + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "~3.8.1" + lodash "^4.1.0" + optionalDependencies: + jsdom "^7.0.2" + +cheerio@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + +chokidar@^3.3.0: + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^2.15.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +continuable-cache@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f" + integrity sha1-vXJ6f67XfnH/OYWskzUakSczrQ8= + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cp@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/cp/-/cp-0.2.0.tgz#a0874183a09e885eb72792582ab68ce3932b135d" + integrity sha1-oIdBg6CeiF63J5JYKraM45MrE10= + +cpr@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cpr/-/cpr-3.0.1.tgz#b9a55038b7cd81a35c17b9761895bd8496aef1e5" + integrity sha1-uaVQOLfNgaNcF7l2GJW9hJau8eU= + dependencies: + graceful-fs "^4.1.5" + minimist "^1.2.0" + mkdirp "~0.5.1" + rimraf "^2.5.4" + +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-what@2.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + +cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0": + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +"cssstyle@>= 0.2.29 < 0.3.0": + version "0.2.37" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" + integrity sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ= + dependencies: + cssom "0.3.x" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +datauri@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/datauri/-/datauri-2.0.0.tgz#ff0ee23729935a6bcc81f301621bed3e692bf3c7" + integrity sha512-zS2HSf9pI5XPlNZgIqJg/wCJpecgU/HA6E/uv2EfaWnW1EiTGLfy/EexTIsC9c99yoCOTXlqeeWk4FkCSuO3/g== + dependencies: + image-size "^0.7.3" + mimer "^1.0.0" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +destroy@^1.0.4, destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +dezalgo@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= + dependencies: + asap "^2.0.0" + wrappy "1" + +direction@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/direction/-/direction-0.1.5.tgz#ce5d797f97e26f8be7beff53f7dc40e1c1a9ec4c" + integrity sha1-zl15f5fib4vnvv9T99xA4cGp7Ew= + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@^0.1.0, dom-serializer@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + +dom-serializer@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= + dependencies: + domelementtype "1" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domhandler@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" + integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== + dependencies: + domelementtype "^2.0.1" + +domhandler@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" + integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== + dependencies: + domelementtype "^2.2.0" + +domutils@1.5, domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^2.0.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.7.0.tgz#8ebaf0c41ebafcf55b0b72ec31c56323712c5442" + integrity sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + integrity sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY= + +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +error@7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02" + integrity sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI= + dependencies: + string-template "~0.2.1" + xtend "~4.0.0" + +error@^7.0.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894" + integrity sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA== + dependencies: + string-template "~0.2.1" + +escape-html@^1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^1.6.1: + version "1.14.3" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +faye-websocket@~0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" + integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= + dependencies: + websocket-driver ">=0.5.1" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +front-matter@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.3.0.tgz#7203af896ce357ee04e2aa45169ea91ed7f67504" + integrity sha1-cgOviWzjV+4E4qpFFp6pHtf2dQQ= + dependencies: + js-yaml "^3.10.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +gitbook-plugin-fontsettings@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gitbook-plugin-fontsettings/-/gitbook-plugin-fontsettings-2.0.0.tgz#835f900ae3dd111086fe7ed4425ee3de024861ab" + integrity sha1-g1+QCuPdERCG/n7UQl7j3gJIYas= + +gitbook-plugin-livereload@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/gitbook-plugin-livereload/-/gitbook-plugin-livereload-0.0.1.tgz#c0c9dc6f55f82fc24f97532b25287abbbb416b96" + integrity sha1-wMncb1X4L8JPl1MrJSh6u7tBa5Y= + +gitbook-plugin-lunr@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gitbook-plugin-lunr/-/gitbook-plugin-lunr-1.2.0.tgz#f3e80ec76512fbdb75eb0524aa82b8dff12a50ab" + integrity sha1-8+gOx2US+9t16wUkqoK43/EqUKs= + dependencies: + gitbook-plugin-search "*" + html-entities "1.2.0" + lunr "0.5.12" + +gitbook-plugin-search@*, gitbook-plugin-search@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/gitbook-plugin-search/-/gitbook-plugin-search-2.2.1.tgz#6d25b5a776990fa98fdfdfa37de331f78e0f6b13" + integrity sha1-bSW1p3aZD6mP39+jfeMx944PaxM= + +github-slugid@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/github-slugid/-/github-slugid-1.0.1.tgz#bccdd0815bfad69d8a359fa4fd65947d606ec3c0" + integrity sha1-vM3QgVv61p2KNZ+k/WWUfWBuw8A= + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1, glob@^7.1.3: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-npm@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/global-npm/-/global-npm-0.4.1.tgz#9035d5bd1e38db44d503d96da2e3120ca5a5dcf2" + integrity sha512-/XasD4hg2kbBfxxLjCaqa4acGeaO4WshW7Mo7CCfZLgpHH3Jpdl0OKxhgob/8s842Sd9VrU7+E6ph65Yzn5wmQ== + dependencies: + which latest + +graceful-fs@^4.1.2, graceful-fs@^4.1.5: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +highlight.js@^10.7.1: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +honkit@^3.6.20: + version "3.6.20" + resolved "https://registry.yarnpkg.com/honkit/-/honkit-3.6.20.tgz#9842b8421e16b385753000945eef6b19325e17b9" + integrity sha512-8Y0dRyIhfF7vSJ/QL9E70Blr45mCgCcj4xtzc83z8bni0NvXtpXS2IsFQb/t/8aXGDElaEThgdEvL1o1UA1WnA== + dependencies: + "@honkit/asciidoc" "^3.6.17" + "@honkit/honkit-plugin-highlight" "^3.6.19" + "@honkit/honkit-plugin-theme-default" "^3.6.20" + "@honkit/markdown-legacy" "^3.6.17" + bash-color "^0.0.4" + cheerio "^0.20.0" + chokidar "^3.3.0" + commander "^5.1.0" + cp "^0.2.0" + cpr "^3.0.1" + crc "^3.8.0" + destroy "^1.0.4" + direction "^0.1.5" + dom-serializer "^0.1.0" + error "7.0.2" + escape-html "^1.0.3" + escape-string-regexp "^4.0.0" + extend "^3.0.0" + flat-cache "^2.0.1" + front-matter "^2.1.0" + gitbook-plugin-fontsettings "^2.0.0" + gitbook-plugin-livereload "^0.0.1" + gitbook-plugin-lunr "^1.2.0" + gitbook-plugin-search "^2.2.1" + github-slugid "^1.0.1" + global-npm "^0.4.0" + i18n-t "^1.0.1" + ignore "^5.1.8" + immutable "^3.8.1" + is "^3.1.0" + js-yaml "^3.6.1" + json-schema-defaults "^0.1.1" + jsonschema "1.1.0" + juice "^6.0.0" + memoize-one "^5.1.1" + mkdirp "^1.0.4" + moment "^2.24.0" + nunjucks "^3.2.0" + nunjucks-do "^1.0.0" + object-path "^0.11.5" + omit-keys "^0.1.0" + open "^7.0.0" + q "^1.5.1" + read-installed "^4.0.3" + request "^2.88.0" + resolve "^1.17.0" + semver "^5.1.0" + send "^0.17.1" + spawn-cmd "0.0.2" + tiny-lr "^1.1.1" + tmp "0.0.28" + try-resolve "^1.0.1" + urijs "^1.19.6" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-entities@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2" + integrity sha1-QZSMr4XOgv7Tbk5qDtNxpmZDeeI= + +htmlparser2@^3.9.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +htmlparser2@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + +htmlparser2@~3.8.1: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + integrity sha1-mWwosZFRaovoZQGn15dX5ccMEGg= + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-parser-js@>=0.5.1: + version "0.5.3" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +i18n-t@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/i18n-t/-/i18n-t-1.0.1.tgz#b7bf4b003e395dc747843e8fca5de477658b0b1c" + integrity sha1-t79LAD45XcdHhD6Pyl3kd2WLCxw= + dependencies: + lodash "^4.13.1" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.1.8: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +image-size@^0.7.3: + version "0.7.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.7.5.tgz#269f357cf5797cb44683dfa99790e54c705ead04" + integrity sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g== + +immutable@^3.8.1: + version "3.8.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" + integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" + integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== + dependencies: + has "^1.0.3" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +is@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" + integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-0.2.0.tgz#a3432192f39b910b5f02cc989487836ec70aa85e" + integrity sha1-o0MhkvObkQtfAsyYlIeDbscKqF4= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +js-yaml@^3.10.0, js-yaml@^3.6.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@^7.0.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" + integrity sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4= + dependencies: + abab "^1.0.0" + acorn "^2.4.0" + acorn-globals "^1.0.4" + cssom ">= 0.3.0 < 0.4.0" + cssstyle ">= 0.2.29 < 0.3.0" + escodegen "^1.6.1" + nwmatcher ">= 1.3.7 < 2.0.0" + parse5 "^1.5.1" + request "^2.55.0" + sax "^1.1.4" + symbol-tree ">= 3.1.0 < 4.0.0" + tough-cookie "^2.2.0" + webidl-conversions "^2.0.0" + whatwg-url-compat "~0.6.5" + xml-name-validator ">= 2.0.1 < 3.0.0" + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-defaults@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/json-schema-defaults/-/json-schema-defaults-0.1.1.tgz#1c6c6103c4349b71b6f4aa382c3dd9aa1c8bada3" + integrity sha1-HGxhA8Q0m3G29Ko4LD3ZqhyLraM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsonschema@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.1.0.tgz#039cc219ed524b06e71daf12ca60d02639faf29a" + integrity sha1-A5zCGe1SSwbnHa8SymDQJjn68po= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +juice@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/juice/-/juice-6.0.0.tgz#cd8f8fe5210ef129d186fe2c41c0ec169f7b07b6" + integrity sha512-5T3JPgXYiw6A6axsb9E09Gzq46WbfJeDirY6nMrqY55iAdqEoPDxSr1GpXqYfoyndx4ujpBPXGLzBRzbiqOOaw== + dependencies: + cheerio "^0.22.0" + commander "^2.15.1" + cross-spawn "^6.0.5" + deep-extend "^0.6.0" + mensch "^0.3.4" + slick "^1.12.2" + web-resource-inliner "^4.3.3" + +kramed@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/kramed/-/kramed-0.5.6.tgz#5c37979bcbb59cbb7a8d231049409298857b5162" + integrity sha1-XDeXm8u1nLt6jSMQSUCSmIV7UWI= + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +livereload-js@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.4.0.tgz#447c31cf1ea9ab52fc20db615c5ddf678f78009c" + integrity sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= + +lodash.defaults@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + +lodash.merge@^4.4.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= + +lodash.some@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + +lodash.unescape@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + +lodash@^4.1.0, lodash@^4.13.1: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lunr@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-0.5.12.tgz#a2f6b7d7801cbe2ccb1696da67f1f7788f89e0c8" + integrity sha1-ova314AcvizLFpbaZ/H3eI+J4Mg= + +memoize-one@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +mensch@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/mensch/-/mensch-0.3.4.tgz#770f91b46cb16ea5b204ee735768c3f0c491fecd" + integrity sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g== + +mime-db@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" + integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.32" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" + integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== + dependencies: + mime-db "1.49.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimer@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/mimer/-/mimer-1.1.1.tgz#f880cef5009e58d4755a98bfd7b3f6de1ce168f4" + integrity sha512-ye7CWOnSgiX3mqOLJ0bNGxRAULS5a/gzjj6lGSCnRTkbLUhNvt/7dI80b6GZRoaj4CsylcWQzyyKKh1a3CT74g== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +moment@^2.24.0: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +normalize-package-data@^2.0.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-normalize-package-bin@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +nunjucks-do@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nunjucks-do/-/nunjucks-do-1.0.0.tgz#506bbd4b42db29ab3dada41b455546b9907ef1df" + integrity sha1-UGu9S0LbKas9raQbRVVGuZB+8d8= + +nunjucks@^3.2.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.3.tgz#1b33615247290e94e28263b5d855ece765648a31" + integrity sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ== + dependencies: + a-sync-waterfall "^1.0.0" + asap "^2.0.3" + commander "^5.1.0" + +"nwmatcher@>= 1.3.7 < 2.0.0": + version "1.4.4" + resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e" + integrity sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-inspect@^1.9.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + +object-path@^0.11.5: + version "0.11.5" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a" + integrity sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg== + +omit-keys@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/omit-keys/-/omit-keys-0.1.0.tgz#e14ec5ca09cd4ae07fc39e8ca35939738449bec8" + integrity sha1-4U7FygnNSuB/w56Mo1k5c4RJvsg= + dependencies: + array-difference "0.0.1" + isobject "^0.2.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +open@^7.0.0: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +os-tmpdir@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse5@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" + integrity sha1-m387DeMr543CQBsXVzzK8Pb1nZQ= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +q@^1.1.2, q@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@^6.4.0: + version "6.10.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" + integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425" + integrity sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU= + dependencies: + bytes "1" + string_decoder "0.10" + +read-installed@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" + integrity sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc= + dependencies: + debuglog "^1.0.1" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + semver "2 || 3 || 4 || 5" + slide "~1.1.3" + util-extend "^1.0.1" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-json@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a" + integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA== + dependencies: + glob "^7.1.1" + json-parse-even-better-errors "^2.3.0" + normalize-package-data "^2.0.0" + npm-normalize-package-bin "^1.0.0" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + integrity sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^3.1.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdir-scoped-modules@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" + integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +request@^2.55.0, request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve@^1.10.0, resolve@^1.17.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.5.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-json-parse@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" + integrity sha1-PnZyPjjf3aE8mx0poeB//uSzC1c= + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.1.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +send@^0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +slick@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7" + integrity sha1-vQSN23TefRymkV+qSldXCzVQwtc= + +slide@~1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spawn-cmd@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/spawn-cmd/-/spawn-cmd-0.0.2.tgz#6d5e251fad0eab00b0f193d245669a7a228ec0de" + integrity sha1-bV4lH60OqwCw8ZPSRWaaeiKOwN4= + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.10" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" + integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +string-template@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" + integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0= + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string_decoder@0.10, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +"symbol-tree@>= 3.1.0 < 4.0.0": + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +tiny-lr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.1.1.tgz#9fa547412f238fedb068ee295af8b682c98b2aab" + integrity sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA== + dependencies: + body "^5.1.0" + debug "^3.1.0" + faye-websocket "~0.10.0" + livereload-js "^2.3.0" + object-assign "^4.1.0" + qs "^6.4.0" + +tmp@0.0.28: + version "0.0.28" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.28.tgz#172735b7f614ea7af39664fa84cf0de4e515d120" + integrity sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA= + dependencies: + os-tmpdir "~1.0.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +tough-cookie@^2.2.0, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.1: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +try-resolve@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/try-resolve/-/try-resolve-1.0.1.tgz#cfde6fabd72d63e5797cfaab873abbe8e700e912" + integrity sha1-z95vq9ctY+V5fPqrhzq76OcA6RI= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +unxhr@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unxhr/-/unxhr-1.0.1.tgz#92200322d66c728993de771f9e01eeb21f41bc7b" + integrity sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urijs@^1.19.6: + version "1.19.7" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.7.tgz#4f594e59113928fea63c00ce688fb395b1168ab9" + integrity sha512-Id+IKjdU0Hx+7Zx717jwLPsPeUqz7rAtuVBRLLs+qn+J2nf9NGITWVCxcijgYxBqe83C7sqsQPs6H1pyz3x9gA== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + integrity sha1-p8IW0mdUUWljeztu3GypEZ4v+T8= + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +valid-data-url@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/valid-data-url/-/valid-data-url-2.0.0.tgz#2220fa9f8d4e761ebd3f3bb02770f1212b810537" + integrity sha512-dyCZnv3aCey7yfTgIqdZanKl7xWAEEKCbgmR7SKqyK6QT/Z07ROactrgD1eA37C69ODRj7rNOjzKWVPh0EUjBA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +web-resource-inliner@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/web-resource-inliner/-/web-resource-inliner-4.3.4.tgz#07e1b4bcbcbee1021251b018e902bac5713f1be0" + integrity sha512-agVAgRhOOi4GVlvKK34oM23tDgH8390HfLnZY2HZl8OFBwKNvUJkH7t89AT2iluQP8w9VHAAKX6Z8EN7/9tqKA== + dependencies: + async "^3.1.0" + chalk "^2.4.2" + datauri "^2.0.0" + htmlparser2 "^4.0.0" + lodash.unescape "^4.0.1" + request "^2.88.0" + safer-buffer "^2.1.2" + valid-data-url "^2.0.0" + xtend "^4.0.2" + +webidl-conversions@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506" + integrity sha1-O/glj30xjHRDw28uFpQCoaZwNQY= + +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-url-compat@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz#00898111af689bb097541cd5a45ca6c8798445bf" + integrity sha1-AImBEa9om7CXVBzVpFymyHmERb8= + dependencies: + tr46 "~0.0.1" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@latest: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +"xml-name-validator@>= 2.0.1 < 3.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" + integrity sha1-TYuPHszTQZqjYgYb7O9RXh5VljU= + +xtend@^4.0.2, xtend@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1"