docker-machime和compose、swarm被稱為docker三劍客。docker-machine是解決docker運行環境問題,之前已經研究過,下面研究compose和swarm。
1.Docker Compose
dcoker-compose主要是解決本地docker容器編排問題。當然也可以自己編寫shell腳本來解決此類問題。
一般是通過yaml配置文件來使用它,這個yaml文件里能記錄多個容器啟動的配置信息(鏡像、啟動命令、端口映射等),最后只需要執行docker-compose
對應的命令就會像執行腳本一樣地批量創建和銷毀容器。
1.使用步驟
一般分為3步:
使用 Dockerfile 定義應用程序的環境。
使用 docker-compose.yml 定義構成應用程序的服務,這樣它們可以在隔離環境中一起運行。
最后,執行 docker-compose up 命令來啟動並運行整個應用程序。
2.安裝compose
linux下面安裝:
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose #下載 sudo chmod +x /usr/local/bin/docker-compose #賦予可運行權 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose #創建軟連接
windows安裝docker的時候默認會安裝。
查看版本:
$ docker-compose --version docker-compose version 1.20.1, build 5d8c71b2
3.開始使用--構造基於tomcat服務和mysql服務的javaweb項目
(1)准備一個JavaWeb項目,如下:
Administrator@MicroWin10-1535 MINGW64 /e/docker/dockerTest/dockertest4 $ pwd /e/docker/dockerTest/dockertest4 Administrator@MicroWin10-1535 MINGW64 /e/docker/dockerTest/dockertest4 $ ls docker-compose.yml Dockerfile ssm.war
(2)文件內容分別如下:
docker-compose.yml內容如下:
# yaml 配置 version: '2' services: #tomcat服務 tomcat: # 指定基於當前./Dockerfile 構建的鏡像,這時候無需指定image,如果指定image會代替當前build指定的鏡像 build: . # 指定容器名稱 container_name: tomcat_web # 指定端口映射 ports: - "8080:8080" #volumes: #- "$PWD/tomcat/webapps:/usr/local/tomcat/webapps" #指定依賴的服務,會先啟動依賴服務,后啟動自身。停止的時候順序相反。 depends_on: - mysql #mysql服務 mysql: # 指定鏡像 image: "hub.c.163.com/library/mysql" container_name: msql_ssm ports: - "3306:3306" # 指定環境變量 environment: MYSQL_ROOT_PASSWORD: "123456" MYSQL_DATABASE: ssm # 覆蓋容器啟動的默認命令。 command: [ '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci' ]
該文件定義了兩個服務。tomcat和mysql。
tomcat:該服務使用從當前目錄下Dockerfile構建的鏡像(build指定至於當前目錄下Dockerfile的鏡像)。端口暴露在8080。
mysql:該服務基於mysql鏡像,
Dockerfile內容如下:(tomcat服務的鏡像制作Dockerfile。也就是運行tomcat服務的時候會先基於下面Dockerfile構建鏡像,然后啟動容器)
FROM hub.c.163.com/library/tomcat MAINTAINER qlq COPY ./ssm.war /usr/local/tomcat/webapps
ssm.war是一個javaweb項目,和上一篇文章自己手動構造的Javaweb鏡像一樣。
(3)使用 Compose 命令構建和運行您的應用
到 /e/docker/dockerTest/dockertest4目錄,也就是docker-compose.yml文件所在的目錄。
docker-compose up
如果你想在后台執行該服務可以加上 -d 參數:
docker-compose up -d
(4)我們運行 docker-compose up -d 之后查看鏡像和容器信息
Administrator@MicroWin10-1535 MINGW64 /e/docker/dockerTest/dockertest4 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE dockertest4_tomcat latest ace88b521179 About an hour ago 350MB hello_dockerfile latest 779eab29d6dc 4 days ago 5.59MB alpine latest e7d92cdc71fe 4 weeks ago 5.59MB ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB hello-world latest fce289e99eb9 13 months ago 1.84kB hub.c.163.com/library/tomcat latest 72d2be374029 2 years ago 292MB hub.c.163.com/library/nginx latest 46102226f2fd 2 years ago 109MB hub.c.163.com/library/mysql latest 9e64176cd8a2 2 years ago 407MB Administrator@MicroWin10-1535 MINGW64 /e/docker/dockerTest/dockertest4 $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7aa9b3cb61ee dockertest4_tomcat "catalina.sh run" About an hour ago Up 41 minutes 0.0.0.0:8080->8080/tcp tomcat_web 279551a99051 hub.c.163.com/library/mysql "docker-entrypoint.s…" About an hour ago Up 41 minutes 0.0.0.0:3306->3306/tcp msql_ssm
實際上docker compose幫我們創建了一個tomcat鏡像,也就是我們Dockerfile中聲明的鏡像,並且啟動了新建的鏡像和mysql鏡像。
補充:yml配置文件參考
(1)version 指定本 yml 依從的 compose 哪個版本制定的。
(2)build 指定為構建鏡像上下文路徑:
例如 webapp 服務,指定為從上下文路徑 ./dir/Dockerfile 所構建的鏡像:
version: "3.7"
services:
webapp:
build: ./dir
或者,作為具有在上下文指定的路徑的對象,以及可選的 Dockerfile 和 args:
version: "3.7" services: webapp: build: context: ./dir dockerfile: Dockerfile-alternate args: buildno: 1 labels: - "com.example.description=Accounting webapp" - "com.example.department=Finance" - "com.example.label-with-empty-value" target: prod
context:上下文路徑。
dockerfile:指定構建鏡像的 Dockerfile 文件命。
args:添加構建參數,這是只能在構建過程中訪問的環境變量。
labels:設置構建鏡像的標簽。
target:多層構建,可以指定構建哪一層。
(3)cap_add,cap_drop
添加或刪除容器擁有的宿主機的內核功能。
cap_add: - ALL # 開啟全部權限 cap_drop: - SYS_PTRACE # 關閉 ptrace權限
(4) cgroup_parent
為容器指定父 cgroup 組,意味着將繼承該組的資源限制。
cgroup_parent: m-executor-abcd
(5)command
覆蓋容器啟動的默認命令。
command: ["bundle", "exec", "thin", "-p", "3000"]
(6)container_name
指定自定義容器名稱,而不是生成的默認名稱
container_name: my-web-container
(6)depends_on
設置依賴關系。
docker-compose up :以依賴性順序啟動服務。在以下示例中,先啟動 db 和 redis ,才會啟動 web。
docker-compose up SERVICE :自動包含 SERVICE 的依賴項。在以下示例中,docker-compose up web 還將創建並啟動 db 和 redis。
docker-compose stop :按依賴關系順序停止服務。在以下示例中,web 在 db 和 redis 之前停止。
version: "3.7" services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
注意:web 服務不會等待 redis db 完全啟動 之后才啟動。
(7) devices
指定設備映射列表。
devices: - "/dev/ttyUSB0:/dev/ttyUSB0"
(8)dns 自定義 DNS 服務器,可以是單個值或列表的多個值
dns: 8.8.8.8 dns: - 8.8.8.8 - 9.9.9.9
(9)dns_search
自定義 DNS 搜索域。可以是單個值或列表。
dns_search: example.com dns_search: - dc1.example.com - dc2.example.com
(10) entrypoint
覆蓋容器默認的 entrypoint。
entrypoint: /code/entrypoint.sh
也可以是以下格式:
entrypoint: - php - -d - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so - -d - memory_limit=-1 - vendor/bin/phpunit
(11) env_file
從文件添加環境變量。可以是單個值或列表的多個值。
env_file: .env
也可以是列表格式:
env_file: - ./common.env - ./apps/web.env - /opt/secrets.env
(12) environment
添加環境變量。您可以使用數組或字典、任何布爾值,布爾值需要用引號引起來,以確保 YML 解析器不會將其轉換為 True 或 False。
environment: RACK_ENV: development SHOW: 'true'
(13) expose
暴露端口,但不映射到宿主機,只被連接的服務訪問。
僅可以指定內部端口為參數:
expose: - "3000" - "8000"
(14)image
指定容器運行的鏡像。以下格式都可以:
image: redis image: ubuntu:14.04 image: tutum/influxdb image: example-registry.com:4000/postgresql image: a4bc65fd # 鏡像id
(15)volumes
將主機的數據卷或着文件掛載到容器里。
version: "3.7" services: db: image: postgres:latest volumes: - "/localhost/postgres.sock:/var/run/postgres/postgres.sock" - "/localhost/data:/var/lib/postgresql/data"
(16)network_mode
設置網絡模式。
network_mode: "bridge" network_mode: "host" network_mode: "none" network_mode: "service:[service name]" network_mode: "container:[container name/id]"
2.Swarm
docker-swarm是解決多主機多個容器調度部署得問題。
swarm是基於docker平台實現的集群技術,他可以通過幾條簡單的指令快速的創建一個docker集群,接着在集群的共享網絡上部署應用,最終實現分布式的服務。swarm技術相當不成熟,很多配置功能都無法實現,只能說是個半成品,目前更多的是使用Kubernetes來管理集群和調度容器。
Docker Swarm 是 Docker 的集群管理工具。它將 Docker 主機池轉變為單個虛擬 Docker 主機。 Docker Swarm 提供了標准的 Docker API,所有任何已經與 Docker 守護程序通信的工具都可以使用 Swarm 輕松地擴展到多個主機。
支持的工具包括但不限於以下各項:
Dokku
Docker Compose
Docker Machine
Jenkins
1.原理
如下圖所示,swarm 集群由管理節點(manager)和工作節點(work node)構成。
swarm mananger:負責整個集群的管理工作包括集群配置、服務管理等所有跟集群有關的工作。
work node:即圖中的 available node,主要負責運行相應的服務來執行任務(task)。
2.使用
以下示例,以 Docker Machine 和 virtualbox 進行介紹。
1.創建 swarm 集群管理節點(manager)
創建 docker 機器:
docker-machine create -d virtualbox swarm-manager
查看機器:
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS default * virtualbox Running tcp://192.168.99.100:2376 v19.03.5 swarm-manager - virtualbox Running tcp://192.168.99.102:2376 v19.03.5
2.初始化 swarm 集群,進行初始化的這台機器,就是集群的管理節點。
(1)查看機器的IP
$ docker-machine ip swarm-manager 192.168.99.102
(2)初始化為集群管理節點(下面的 IP 為創建機器時分配的 ip。)
docker@swarm-manager:~$ docker swarm init --advertise-addr 192.168.99.102 Swarm initialized: current node (saxb3bvwb5qp68ulel1ns9oel) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-2jo0xzr3i293iscbbb1ygtfchptk6hskjee9m6q8jp3tc1togq-4j8p3hxal3ouppjf7txg88aho 192.168.99.102:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
以上輸出,證明已經初始化成功。需要把以下這行復制出來,在增加工作節點時會用到:
docker swarm join --token SWMTKN-1-2jo0xzr3i293iscbbb1ygtfchptk6hskjee9m6q8jp3tc1togq-4j8p3hxal3ouppjf7txg88aho 192.168.99.102:2377
3. 創建 swarm 集群工作節點(worker)
這里直接創建好倆台機器,swarm-worker1 和 swarm-worker2
docker-machine create -d virtualbox swarm-worker1
docker-machine create -d virtualbox swarm-worker2
分別進入倆個機器里,指定添加至上一步中創建的集群,這里會用到上一步復制的內容。
Administrator@MicroWin10-1535 MINGW64 /e/docker/dockerTest/dockertest4 $ docker-machine ssh swarm-worker1 ( '>') /) TC (\ Core is distributed with ABSOLUTELY NO WARRANTY. (/-_--_-\) www.tinycorelinux.net docker@swarm-worker1:~$ docker swarm join --token SWMTKN-1-2jo0xzr3i293iscbbb1ygtfchptk6hskjee9m6q8jp3tc1togq-4j8p3hxal3ouppjf7txg88aho 192.168.99.102:2377 This node joined a swarm as a worker.
出現This node joined 。。。 代表以經加入成功。
Administrator@MicroWin10-1535 MINGW64 /e/docker/dockerTest/dockertest4 $ docker-machine ssh swarm-worker2 ( '>') /) TC (\ Core is distributed with ABSOLUTELY NO WARRANTY. (/-_--_-\) www.tinycorelinux.net docker@swarm-worker2:~$ docker swarm join --token SWMTKN-1-2jo0xzr3i293iscbbb1ygtfchptk6hskjee9m6q8jp3tc1togq-4j8p3hxal3ouppjf7txg88aho 192.168.99.102:2377 This node joined a swarm as a worker. docker@swarm-worker2:~$
4.查看集群信息
進入管理節點,執行:docker info 可以查看當前集群的信息。
docker@swarm-manager:~$ docker info Client: Debug Mode: false Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 19.03.5 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: active NodeID: saxb3bvwb5qp68ulel1ns9oel Is Manager: true ClusterID: o6aztcxmyww6x20z0z2juuvmd Managers: 1 Nodes: 3 Default Address Pool: 10.0.0.0/8 SubnetSize: 24 Data Path Port: 4789 Orchestration: Task History Retention Limit: 5 Raft: Snapshot Interval: 10000 Number of Old Snapshots to Retain: 0 Heartbeat Tick: 1 Election Tick: 10 Dispatcher: Heartbeat Period: 5 seconds CA Configuration: Expiry Duration: 3 months Force Rotate: 0 Autolock Managers: false Root Rotation In Progress: false Node Address: 192.168.99.102 Manager Addresses: 192.168.99.102:2377 Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 init version: fec3683 Security Options: seccomp Profile: default Kernel Version: 4.14.154-boot2docker Operating System: Boot2Docker 19.03.5 (TCL 10.1) OSType: linux Architecture: x86_64 CPUs: 1 Total Memory: 989.5MiB Name: swarm-manager ID: G5DI:IQAN:ZROP:SFOZ:4U5A:VNHA:T55G:57GE:DAQX:STGM:RKKN:TCXA Docker Root Dir: /mnt/sda1/var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: provider=virtualbox Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false Product License: Community Engine
通過標紅的地方,可以知道當前運行的集群中,有三個節點,其中有一個是管理節點。
5.部署服務到集群中
注意:跟集群管理有關的任何操作,都是在管理節點上操作的。
以下例子,在一個工作節點上創建一個名為 helloworld 的服務,這里是隨機指派給一個工作節點:
docker@swarm-manager:~$ docker service create --replicas 1 --name helloworld alpine ping docker.com bwe0epdhxyr9wnhg9fdrjm261 overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
replicas 參數是指運行實例個數
name 參數指定服務名稱
alpine 指的是使用的鏡像名稱
ping docker.com 指的是容器運行的bash
6.查看服務部署情況
查看 helloworld 服務運行在哪個節點上,可以看到目前是在 swarm-manager 節點:
docker@swarm-manager:~$ docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS cf4rnafi6zam helloworld.1 alpine:latest swarm-manager Running Running 8 minutes ago
查看 helloworld 部署的具體信息:
docker@swarm-manager:~$ docker service inspect --pretty helloworld ID: bwe0epdhxyr9wnhg9fdrjm261 Name: helloworld 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: alpine:latest@sha256:ab00606a42621fb68f2ed6ad3c88be54397f981a7b70a79db3d1172b11c4367d Args: ping docker.com Init: false Resources: Endpoint Mode: vip
7.擴展集群服務
將上述的 helloworld 服務擴展到倆個節點。
docker@swarm-manager:~$ docker service scale helloworld=2 #擴展到兩個 helloworld scaled to 2 overall progress: 2 out of 2 tasks 1/2: running [==================================================>] 2/2: running [==================================================>] verify: Service converged docker@swarm-manager:~$ docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS cf4rnafi6zam helloworld.1 alpine:latest swarm-manager Running Running 15 minutes ago lvbmq8nyywir helloworld.2 alpine:latest swarm-worker1 Running Running 25 seconds ago
8.刪除服務
docker@swarm-manager:~$ docker service rm helloworld helloworld docker@swarm-manager:~$ docke
9.停止某個節點
查看所有任務的節點
docker@swarm-manager:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION saxb3bvwb5qp68ulel1ns9oel * swarm-manager Ready Active Leader 19.03.5 vipkje05pw9htalttmcgs2kxr swarm-worker1 Ready Active 19.03.5 yotdzl8j2l900ikalvx0227d1 swarm-worker2 Ready Active 19.03.5
可以看到目前所有的節點都是 Active, 可以接收新的任務分配。
停止節點 swarm-worker1:
docker@swarm-manager:~$ docker node ls # 查看節點 ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION saxb3bvwb5qp68ulel1ns9oel * swarm-manager Ready Active Leader 19.03.5 vipkje05pw9htalttmcgs2kxr swarm-worker1 Ready Active 19.03.5 yotdzl8j2l900ikalvx0227d1 swarm-worker2 Ready Active 19.03.5 <ocker node update --availability drain swarm-worker1 #停掉節點worker1 swarm-worker1 docker@swarm-manager:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION saxb3bvwb5qp68ulel1ns9oel * swarm-manager Ready Active Leader 19.03.5 vipkje05pw9htalttmcgs2kxr swarm-worker1 Ready Drain 19.03.5 yotdzl8j2l900ikalvx0227d1 swarm-worker2 Ready Active 19.03.5 docker@swarm-manager:~$ docker node update --availability active swarm-worker1 #重新激活節點worker1 swarm-worker1 docker@swarm-manager:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION saxb3bvwb5qp68ulel1ns9oel * swarm-manager Ready Active Leader 19.03.5 vipkje05pw9htalttmcgs2kxr swarm-worker1 Ready Active 19.03.5 yotdzl8j2l900ikalvx0227d1 swarm-worker2 Ready Active 19.03.5
補充:swarm集群中部署nginx
1.管理節點中運行
docker service create --name my-web --publish published=8080,target=80 --replicas 2 hub.c.163.com/library/nginx
知道了服務的名字是my-web,啟動的節點是2個,鏡像是 hub.c.163.com/library/nginx。將nginx容器中的端口80發布到群集中任何節點的端口8080。
2.查看集群上的服務
docker@swarm-manager:~$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS n48sms4g6ccv my-web replicated 2/2 hub.c.163.com/library/nginx:latest *:8080->80/tcp docker@swarm-manager:~$ docker service ps my-web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS y2hfv1i6rqgu my-web.1 hub.c.163.com/library/nginx:latest swarm-worker1 Running Running 52 minutes ago n1rkpi1m67xf \_ my-web.1 hub.c.163.com/library/nginx:latest swarm-worker1 Shutdown Rejected 53 minutes ago "No such image: hub.c.163.com/…" od7sw0ju48aa my-web.2 hub.c.163.com/library/nginx:latest swarm-manager Running Running 53 minutes ago
service 通過 ingress load balancing 來發布服務,且 swarm 集群中所有 node 都參與到 ingress 路由網格(ingress routing mesh) 中,訪問任意一個 node+PublishedPort 即可訪問到服務。
當訪問任何節點上的端口8080時,Docker將您的請求路由到活動容器。在群節點本身,端口8080可能並不實際綁定,但路由網格知道如何路由流量,並防止任何端口沖突的發生。
路由網格在發布的端口上監聽分配給節點的任何IP地址。對於外部可路由的IP地址,該端口可從主機外部獲得。對於所有其他IP地址,只能從主機內部訪問。
http://192.168.99.102:8080/、103:8080、104:8080端口都可以訪問到nginx服務,這樣就實現了負載均衡。因為我們指定--replicas 2 啟動了2個運行nginx的容器 ,所以2個節點上都運行了一個 nginx 的容器,可以通過改其中一個節點上的nginx的歡迎頁 ,然后再訪問,來檢查是否實現了負載均衡。
可以通過scale 來指定運行容器的數量。可以看到節點的副本變成1。
docker@swarm-manager:~$ docker service scale my-web=1 my-web scaled to 1 overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged docker@swarm-manager:~$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS n48sms4g6ccv my-web replicated 1/1 hub.c.163.com/library/nginx:latest *:8080->80/tcp