1. 程式人生 > 其它 >Docker之Docker Compose

Docker之Docker Compose

為什麼需要Docker Compose

Docker幫助我們解決服務的打包安裝的問題,隨著而來的問題就是服務過多的帶來如下問題,

  1. 多次使用Dockerfile Build Image或者DockerHub拉取Image;
  2. 需要建立多個Container,多次編寫啟動命令;
  3. Container互相依賴的如何進行管理和編排;

當我們服務數量增多的時候,上面三個問題就會更加的被放大,如果這三個問題不解決,其實從虛擬機器到容器化除了機器減少一些浪費以外,好像沒有更多的變化。Docker有沒有什麼好的方法,可以讓我們通過一個配置就搞定容器編排和執行呢?這個時候Docker Compose就站出來了。

Docker Compose可以做到以下幾點:

  1. 提供工具用於定義和執行多個docker容器應用;
  2. 使用yaml檔案來配置應用服務(docker-compse.yml);
  3. 可以通過一個簡單的命令docker-compse up可以按照依賴關係啟動所有服務;
  4. 可以通過一個簡單的命令docker-compose down停止所有服務;
  5. 當一個服務需要的時候,可以很簡單地通過--scale進行擴容;

Docker Compose有以下特徵:

  1. 更高的可移植性,Docker Compose僅需一個docker-compse up可以完成按照依賴關係啟動所有服務,然後使用docker-compose down輕鬆將其拆解。幫助我們更輕鬆地部署複雜的應用程式;
  2. 單個主機上的多個隔離環境,Compose可以使用專案名稱將環境彼此隔離,這帶可以在一臺計算機上運行同一環境的多個副本,它可以防止不同的專案和服務相互干擾;

Docker Compose介紹

  1. Docker Compose是一個工具,用於定義和執行多容器應用程式的工具;

  2. Docker Compose通過yml檔案定義多容器的docker應用;

  3. Docker Compose通過一條命令根據yml檔案的定義去建立或管理多容器;

Docker Compose 是用來做Docker 的多容器控制,是一個用來把 Docker 自動化的東西。有了 Docker Compose 你可以把所有繁複的 Docker 操作全都一條命令,自動化的完成。

Docker Compose安裝

Docker Compose安裝的最新的版本1.29.2,對於Mac和Windows安裝好Docker以後,就已經安裝好Docker Compose,不需要手動安裝,這裡的安裝方式是基於Linux的Cnetos的,大家也可以參考官方網站去安裝,

具體步驟如下:

  1. 下載 Docker Compose 二進位制檔案,版本1.29.2是目前最新最穩定的版本,要下載舊版本的大家可以更改版本號,可以參考github的版本號進行選擇;

    sudocurl-L"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname-s)-$(uname-m)"-o/usr/local/bin/docker-compose
    
  2. 對二進位制檔案應用可執行許可權;

    sudochmod+x/usr/local/bin/docker-compose
    
  3. 安裝以後通過docker-compose --version命令檢查是否安裝成功;

Docker Compose版本介紹

Docker Compose版本與引擎的對應關係如下,可以看到中間主要有兩個版本2和版本3兩種格式,目前大家使用比較多也就是這兩種,對於這兩個版本的差別給大家介紹一下:

  1. v3 版本不支援 volume_from 、extends、group_add等屬性;
  2. cpu 和 記憶體屬性的設定移到了 deploy 中;
  3. v3 版本支援 Docker Swarm,而 v2 版本不支援;

注意:官方目前在 1.20.0 引入了一個新--compatibility標誌,幫助開發人員輕鬆的過渡到v3,目前還有些問題官方還不建議直接使用到生產,建議大家直接上手v3版本。

Docker Compose基本命令介紹

Docker Compose命令基本上和Docker相差不多,主要就是對Docker Compose生命週期控制、日誌格式等相關命令,可以通過docker-compose --help進行幫助。

#構建建啟動nignx容器
docker-composeup-dnginx

#進入nginx容器中
docker-composeexecnginxbash

#將會停止UP命令啟動的容器,並刪除容器
docker-composedown

#顯示所有容器
docker-composeps

#重新啟動nginx容器
docker-composerestartnginx

#構建映象
docker-composebuildnginx

#不帶快取的構建
docker-composebuild--no-cachenginx

#檢視nginx的日誌
docker-composelogsnginx

#檢視nginx的實時日誌
docker-composelogs-fnginx

#驗證(docker-compose.yml)檔案配置,
#當配置正確時,不輸出任何內容,當檔案配置錯誤,輸出錯誤資訊
docker-composeconfig-q

#以json的形式輸出nginx的docker日誌
docker-composeevents--jsonnginx

#暫停nignx容器
docker-composepausenginx

#恢復ningx容器
docker-composeunpausenginx

#刪除容器
docker-composermnginx

#停止nignx容器
docker-composestopnginx

#啟動nignx容器
docker-composestartnginx

Docker Compose實戰

我們構建一個如下的應用,通過Nginx轉發給後端的兩個Java應用;

  1. 新建Spring Boot應用,增加一個HelloController,編寫一個hello方法,返回請求的埠和IP;
/**
*hello
*
*@authorwangtongzhou
*@since2021-07-2509:43
*/
@RestController
publicclassHelloController{

@GetMapping("/hello")
publicStringhello(HttpServletRequestreq)throwsUnknownHostException{
return"hello";
}

}
  1. 指定Spring Boot的啟動入口;
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--指定該MainClass為全域性的唯一入口-->
<mainClass>cn.wheel.getway.WheelGetWay</mainClass>
</configuration>
<executions>
<execution>
<goals>
<!--可以把依賴的包都打包到生成的Jar包中-->
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
  1. 打包Spring Boot應用;
mvnpackage
  1. 上傳檔案到Linux伺服器/usr/local/docker-compose-demo的目錄;
  2. 在/usr/local/docker-compose-demo的目錄編輯Dockerfile;
#指定基礎映象
FROMjava:8
LABELname="docker-compose-demo"version="1.0"author="wtz"
COPY./getway-1.0-SNAPSHOT.jar./docker-compose-demo.jar
#啟動引數
CMD["java","-jar","docker-compose-demo.jar"]
  1. 編輯docker-compose.yml檔案;
version:'3.0'

networks:
docker-compose-demo-net:
driver:bridge
ipam:
config:
-subnet:192.168.1.0/24
gateway:192.168.1.1


services:
docker-compose-demo01:
build:
#構建的地址
context:/usr/local/docker-compose-demo
dockerfile:Dockerfile
image:docker-compose-demo
container_name:docker-compose-demo01
#選擇網路
networks:
-docker-compose-demo-net
#選擇埠
ports:
-8081:8080/tcp
restart:always

docker-compose-demo02:
build:
#構建的地址
context:/usr/local/docker-compose-demo
dockerfile:Dockerfile
image:docker-compose-demo
container_name:docker-compose-demo02
#選擇網路
networks:
-docker-compose-demo-net
#選擇埠
ports:
-8082:8080/tcp
restart:always

nginx:
image:nginx:latest
container_name:nginx-demo
networks:
-docker-compose-demo-net
ports:
-80:80/tcp
restart:always
volumes:
-/usr/local/docker-compose-demo/nginx.conf:/etc/nginx/nginx.conf:rw


volumes:
docker-compose-demo-volume:{}
  1. 編寫nginx.conf,實現負載均衡到每個應用,這裡通過容器名稱訪問,因此不需要管每個容器的ip是多少,這個也是自定義網路的好處;
user nginx;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

server {
    listen 80;
    location / {
     proxy_pass http://docker-compose-demo;
     proxy_set_header  Host $host;
	     proxy_set_header  X-real-ip $remote_addr;
	     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

upstream docker-compose-demo{
   server docker-compose-demo01:8080;
   server docker-compose-demo02:8080;
}
include /etc/nginx/conf.d/*.conf;


server {
    listen 80;
    location / {
     proxy_pass http://docker-compose-demo;
     proxy_set_header  Host $host;
	     proxy_set_header  X-real-ip $remote_addr;
	     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

upstream docker-compose-demo{
   server docker-compose-demo01:8080;
   server docker-compose-demo02:8080;
}
include /etc/nginx/conf.d/*.conf;
}

  1. 檢視/usr/local/docker-compose-demo目錄,有以下確保有以下四個檔案;
  1. 檢查docker-compose.yml的語法是否正確,如果不發生報錯,說明語法沒有發生錯誤;
docker-composeconfig
  1. 啟動docker-compose.yml定義的服務;
docker-composeup
  1. 驗證服務是否正確;
#檢視宿主機ip
ipadd

#訪問對應的服務
curlhttp://172.21.122.231/hello

Docker Compose Yml檔案介紹

版本

對於版本沒什麼介紹的,就是指定使用的版本;

Services

每個Service代表一個Container,與Docker一樣,Container可以是從DockerHub中拉取到的映象,也可以是本地Dockerfile Build的映象。

image

標明image的ID,這個image ID可以是本地也可以是遠端的,如果本地不存在,Docker Compose會嘗試pull下來;

image:ubuntu
build

該引數指定Dockerfile檔案的路徑,Docker Compose會通過Dockerfile構建並生成映象,然後使用該映象;

build:
#構建的地址
context:/usr/local/docker-compose-demo
dockerfile:Dockerfile
ports

暴露埠,指定宿主機到容器的埠對映,或者只指定容器的埠,則表示對映到主機上的隨機埠,一般採用主機:容器的形式來對映埠;

#暴露埠
ports:
-8081:8080/tcp
expose

暴露埠,但不需要建立與宿主機的對映,只是會向連結的服務提供;

environment

加入環境變數,可以使用陣列或者字典,只有一個key的環境變數可以在執行compose的機器上找到對應的值;

env_file

從一個檔案中引入環境變數,該檔案可以是一個單獨的值或者一個列表,如果同時定義了environment,則environment中的環境變數會重寫這些值;

depends_on

定義當前服務啟動時,依賴的服務,當前服務會在依賴的服務啟動後啟動;

depends_on:
-docker-compose-demo02
-docker-compose-demo01
deploy

該配置項在version 3裡才引入,用於指定服務部署和執行時相關的引數;

replicas

指定副本數;

version:'3.4'
services:
worker:
image:nginx:latest
deploy:
replicas:6
restart_policy

指定重啟策略;

version:"3.4"
services:
redis:
image:redis:latest
deploy:
restart_policy:
condition:on-failure#重啟條件:on-failure,none,any
delay:5s#等待多長時間嘗試重啟
max_attempts:3#嘗試的次數
window:120s#在決定重啟是否成功之前等待多長時間
update_config

定義更新服務的方式,常用於滾動更新;

version:'3.4'
services:
vote:
image:docker-compose-demo
depends_on:
-redis
deploy:
replicas:2
update_config:
parallelism:2#一次更新2個容器
delay:10s#開始下一組更新之前,等待的時間
failure_action:pause#如果更新失敗,執行的動作:continue,rollback,pause,預設為pause
max_failure_ratio:20#在更新過程中容忍的失敗率
order:stop-first#更新時的操作順序,停止優先(stop-first,先停止舊容器,再啟動新容器)還是開始優先(start-first,先啟動新容器,再停止舊容器),預設為停止優先,從version3.4才引入該配置項
resources

限制服務資源;

version:'3.4'
services:
redis:
image:redis:alpine
deploy:
resources:
#限制CPU的使用率為50%記憶體50M
limits:
cpus:'0.50'
memory:50M
#始終保持25%的使用率記憶體20M
reservations:
cpus:'0.25'
memory:20M
healthcheck

執行健康檢查;

healthcheck:
test:["CMD","curl","-f","http://localhost"]#用於健康檢查的指令
interval:1m30s#間隔時間
timeout:10s#超時時間
retries:3#重試次數
start_period:40s#啟動多久後開始檢查
restart

重啟策略;

#預設的重啟策略,在任何情況下都不會重啟容器
restart:"no"
#容器總是重新啟動
restart:always
#退出程式碼指示失敗錯誤,則該策略會重新啟動容器
restart:on-failure
#重新啟動容器,除非容器停止
restart:unless-stopped

networks

網路型別,可指定容器執行的網路型別;

#指定對應的網路
networks:
-docker-compose-demo-net


networks:
docker-compose-demo-net:
driver:bridge
ipam:
config:
-subnet:192.168.1.0/24
gateway:192.168.1.1
ipv4_address, ipv6_address

加入網路時,為此服務指定容器的靜態 IP 地址;

version:"3.9"

services:
app:
image:nginx:alpine
networks:
app_net:
ipv4_address:172.16.238.10
ipv6_address:2001:3984:3989::10

networks:
app_net:
ipam:
driver:default
config:
-subnet:"172.16.238.0/24"
-subnet:"2001:3984:3989::/64"

Networks

網路決定了服務之間以及服務和外界之間如何去通訊,在執行docker-compose up的時候,docker會預設建立一個預設網路,建立的服務也會預設的使用這個預設網路。服務和服務之間,可以使用服務的名字進行通訊,也可以自己建立網路,並將服務加入到這個網路之中,這樣服務之間可以相互通訊,而外界不能夠與這個網路中的服務通訊,可以保持隔離性。

Volumes

掛載主機路徑或命名卷,指定為服務的子選項。可以將主機路徑掛載為單個服務定義的一部分,無需在頂級volume中定義。如果想在多個服務中重用一個卷,則在頂級volumes key 中定義一個命名卷,將命名卷與服務一起使用。