# Services with Docker and Compose ## 章節重點 ### 理解什麼是 service > Any processes, functionality, or data that must be discoverable and available over a network is called a service. 現今的軟體大多都包含了許多子系統,而這些子系統會彼此交互依賴溝通 利用抽象的Service可以幫助我們用更簡單的角度去理解各個系統的職責 Docker也有提供service的功能 (Swarm),幫助我們去管理service的生命週期, 以及協作和調度 ### 介紹 Docker Swarm * 名詞和定義介紹 * Automated resurrection and replication * Automated rollout * Service health and rollback ### 利用 Docker Compose 來管理 service - 介紹YAML格式 - replicas - volumes - networks ## Docker Swarm 名詞 [官方概念介紹](https://docs.docker.com/engine/swarm/key-concepts/) [Manager vs Worker nodes](https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/) * Swarm > A swarm consists of multiple Docker hosts which run in swarm mode (managers or workers) * Nodes > A node is an instance of the Docker engine participating in the swarm * Service > A service is the definition of the tasks to execute on the manager or worker nodes * Task (roughly interchangeable with container) > A task carries a Docker container and the commands to run inside the container. It is the atomic scheduling unit of swarm. ### Service 和 Task(container) 的區別 > service的功能會由一群containers來負責實作 ![](https://docs.docker.com/engine/swarm/images/services-diagram.png) ## Swarm 的功能介紹 ### 前置步驟 ``` // 把自己的機器變成一個 node docker swarm init // 啟動範例 service docker service create \ --publish 8080:80 \ --name hello-world \ dockerinaction/ch11_service_hw:v1 ``` ### Automated resurrection and replication > swarm 可以自動保持 service 的 DESIRED STATE > swarm 可以實現 service 的水平擴展 > 偵測維持 replicas 的設定,自動啟動或關閉 tasks(containers) #### 查看 service ``` // list service docker service ls // list the container associated with a specific service docker service ps hello-world ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS bm217mfvfeqa hello-world.1 dockerinaction/ch11_service_hw:v1 docker-desktop Running Running 2 minutes ago lnnk5tc3l768 \_ hello-world.1 dockerinaction/ch11_service_hw:v1 docker-desktop Shutdown Failed 2 minutes ago "task: non-zero exit (137)" ``` - DESIRED STATE: 希望的狀態 - CURRENT STATE: 系統當前狀態 #### 查看 service 的設定 ``` docker service inspect --pretty hello-world docker service inspect hello-world ``` https://docs.docker.com/engine/swarm/swarm-tutorial/rolling-update/ > Rollout parameters => UpdateConfig ``` ID: oqo4kuy9zq6p7ys41mhyg2sb6 Name: hello-world Service Mode: Replicated Replicas: 1 Placement: UpdateConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first RollbackConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-first ContainerSpec: Image: dockerinaction/ch11_service_hw:v1@sha256:4f92ec42207773b4ea97afe03469ff30598d08dd2ec4a28e05550b3ba4bc5fd5 Init: false Resources: Endpoint Mode: vip Ports: PublishedPort = 8080 Protocol = tcp TargetPort = 80 PublishMode = ingress ``` #### 水平擴展 service [service_scale](https://docs.docker.com/engine/reference/commandline/service_scale/) [replicated vs global](https://docs.docker.com/engine/swarm/how-swarm-mode-works/services/) [swarm ingress](https://docs.docker.com/engine/swarm/ingress/) - Two types of service deployments - replicated (specific replica number) - global (one replica on each node) ``` docker service scale hello-world=3 docker service ps hello-world ``` ### Automated rollout > swarm 可以自動更新 service [service_update](https://docs.docker.com/engine/reference/commandline/service_update/) ![](https://i.imgur.com/xgNDXnZ.png) ``` docker service update \ --image dockerinaction/ch11_service_hw:v2 \ --update-order stop-first \ --update-parallelism 1 \ --update-delay 30s \ hello-world ``` - update-parallelism 1 ``` Service Mode: Replicated Replicas: 3 UpdateStatus: State: completed Started: 2 minutes ago Completed: 35 seconds ago Message: update completed Placement: UpdateConfig: Parallelism: 1 Delay: 30s On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first ``` - update-parallelism 3 ``` Service Mode: Replicated Replicas: 3 UpdateStatus: State: completed Started: About a minute ago Completed: 18 seconds ago Message: update completed Placement: UpdateConfig: Parallelism: 3 Delay: 30s On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first ``` ### Service health and rollback >A successful partnership with an orchestrator means clearly communicating the expected requirements and behavior of the workload you’re asking it to orchestrate - update 成會失敗的版本 ``` docker service update \ --image dockerinaction/ch11_service_hw:start-failure \ hello-world ``` ``` overall progress: 0 out of 3 tasks 1/3: starting [============================================> ] 2/3: 3/3: starting container failed: OCI runtime create failed: container_linux.go:3… service update paused: update paused due to failure or early termination of task fjk5wq3ntlby27w7i5wlpdoy6 ``` - 手動 rollback 到上一版 ``` docker service update \ --rollback \ hello-world ``` - 在 update 的時候指定 update-failure-action - update-failure-action: ("pause"|"continue"|"rollback") ``` docker service update \ --update-failure-action rollback \ --update-max-failure-ratio 0.6 \ --image dockerinaction/ch11_service_hw:start-failure \ hello-world ``` ``` overall progress: rolling back update: 3 out of 3 tasks 1/3: running [> ] 2/3: running [> ] 3/3: running [> ] rollback: update rolled back due to failure or early termination of task y0ltb7g7a7q7ons8kjb9gjw2r verify: Service converged ``` #### Docker 如何檢查 task 的 health >Docker is application agnostic. Rather than making assumptions about how to determine whether a specific task is healthy, it lets you specify a health check command - **HEALTHCHECK** in Dockerfile https://hub.docker.com/r/dockerinaction/ch11_service_hw/tags ``` HEALTHCHECK --interval=10s CMD ["/bin/httpping"] ``` - 也可以透過 update 指定 health check 的設定 ``` docker service update \ --health-cmd /bin/httpping \ --health-interval 10s \ hello-world ``` [update 的 options](https://docs.docker.com/engine/reference/commandline/service_update/#options) ## Declarative service environments with Compose V3 >Setting all of these parameters when you’re managing a service from the command line is a mess ![](https://i.imgur.com/EzmqGni.png) - Docker Compose File 的優點 - 避免人為的下指令減少犯錯機會 - 更有系統的去設定 service 的參數 - 可以做版本控制 (git) - Docker Compose File 的缺點 - 相較於指令會不夠靈活 > When you need to model a whole environment of services, you should use a Docker stack. A stack describes collections of services, volumes, networks, and other configuration abstractions. ### A YAML primer https://zh.wikipedia.org/wiki/YAML ### Collections of services with Compose V3 https://docs.docker.com/compose/compose-file/compose-file-v3/ ```yml version: "3.7" services: postgres: image: dockerinaction/postgres:11-alpine environment: POSTGRES_PASSWORD: example mariadb: image: dockerinaction/mariadb:10-bionic environment: MYSQL_ROOT_PASSWORD: example adminer: image: dockerinaction/adminer:4 ports: - 8080:8080 ``` ### Creating and updating stack - create ``` docker stack deploy -c databases.yml my-databases ``` - update ``` adminer: image: dockerinaction/adminer:4 ports: - 8080:8080 deploy: replicas: 3 ``` ### Scaling down and removing services - scale down ``` adminer: image: dockerinaction/adminer:4 ports: - 8080:8080 deploy: replicas: 2 ``` - remove service 把 mariadb 的 definition 刪掉 ``` # 比較不好的方式 但可以成功移除 docker service remove my-databases_mariadb ``` ``` # 比較正確但會刪掉沒有在yaml定義的resources docker stack deploy -c databases.yml --prune my-databases ``` ### Stateful services and preserving data - 增加volume的設定 ```yml version: "3.7" volumes: pgdata: services: postgres: image: dockerinaction/postgres:11-alpine volumes: - type: volume source: pgdata target: /var/lib/postgresql/data environment: POSTGRES_PASSWORD: example adminer: image: dockerinaction/adminer:4 ports: - 8080:8080 deploy: replicas: 1 ``` - 重新啟動 service ``` docker service remove my-databases_postgres docker stack deploy -c databases.yml my-databases ``` ### Load balancing, service discovery, and networks with Compose >Port publishing for a service is different from publishing a port on a container. Whereas containers directly map the port on the host interface to an interface for a specific container, services might be made up of many replica containers. >Docker accommodates services by creating virtual IP (VIP) addresses and balancing requests for a specific service between all of the associated replicas. ![](https://i.imgur.com/zbV8M9N.png) #### ingress network - handles all port forwarding from the host interface to services #### my-databases_default - Docker will create a network for your stack named 'default', if not define network config in compose file #### 可以定義自己的 network - 讓不同的 stack 共用同個 network - 讓 services 不共用同個 network https://docs.docker.com/compose/compose-file/compose-file-v3/#network-configuration-reference ```yml version: "3.7" networks: foo: driver: overlay volumes: pgdata: services: postgres: image: dockerinaction/postgres:11-alpine volumes: - type: volume source: pgdata target: /var/lib/postgresql/data networks: - foo environment: POSTGRES_PASSWORD: example adminer: image: dockerinaction/adminer:4 networks: - foo ports: - 8080:8080 deploy: replicas: 1 ```