教程基於ubuntu下最新的compose版本3
參考: https://docs.docker.com/compose/overview/
1.Compose介紹
Docker Compose是一個用來定義和運行復雜應用的Docker工具。一個使用Docker容器的應用,通常由多個容器組成。使用Docker Compose不再需要使用shell腳本來啟動容器。
Compose 通過一個配置文件來管理多個Docker容器,在配置文件中,所有的容器通過services來定義,然后使用docker-compose腳本來啟動,停止和重啟應用,和應用中的服務以及所有依賴服務的容器,非常適合組合使用多個容器進行開發的場景。
2.Compose和Docker兼容性
compose文件格式版本 | docker版本 |
---|---|
3.4 | 17.09.0+ |
3.3 | 17.06.0+ |
3.2 | 17.04.0+ |
3.1 | 1.13.1+ |
3.0 | 1.13.0+ |
2.3 | 17.06.0+ |
2.2 | 1.13.0+ |
2.1 | 1.12.0+ |
2.0 | 1.10.0+ |
1.0 | 1.9.1.+ |
Docker從1.13.x版本開始,版本分為企業版EE和社區版CE,版本號也改為按照時間線來發布,比如17.03就是2017年3月。
Docker的linux發行版的軟件倉庫從以前的https://apt.dockerproject.org和https://yum.dockerproject.org變更為目前的https://download.docker.com, 軟件包名字改為docker-ce和docker-ee。
3.安裝docker
Docker的社區版(Docker Community Edition)叫做docker-ce。老版本的Docker包叫做docker或者docker-engine,如果安裝了老版本的docker得先卸載然后再安裝新版本的docker。docker的發展非常迅速,apt源的更新往往比較滯后。所以docker官網推薦的安裝方式都是下載docker安裝腳本安裝。
卸載老舊的版本(若未安裝過可省略此步):
$ sudo apt-get remove docker docker-engine docker.io
- 1
安裝最新的docker:
-
$ curl -fsSL get.docker.com -o get-docker.sh
-
$ sudo sh get-docker.sh
- 1
- 2
shell會提示你輸入sudo的密碼,然后開始執行最新的docker過程
或者
$ curl -sSL https://get.docker.com/ | sh
- 1
確認Docker成功最新的docker:
$ sudo docker run hello-world
- 1
4.安裝docker-compose
兩種最新的docker安裝方式
1.從github上下載docker-compose二進制文件安裝
- 下載最新版的docker-compose文件
$ sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
- 添加可執行權限
$ sudo chmod +x /usr/local/bin/docker-compose
- 測試安裝結果
$ docker-compose --version
docker-compose version 1.16.1, build 1719ceb
2.pip安裝
$ sudo pip install docker-compose
5.docker-compose文件結構和示例
docker-compose文件結構
docker-compose.yml:
-
-
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:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
docker-compose使用示例
通過docker-compose構建一個在docker中運行的基於python flask框架的web應用。
注意:確保你已經安裝了Docker Engine和Docker Compose。 您不需要安裝Python或Redis,因為這兩個都是由Docker鏡像提供的。
Step 1: 定義python應用
- 1 .創建工程目錄
-
$ mkdir compose_test
-
$ cd compose_test
-
$ mkdir src # 源碼文件夾
-
$ mkdir docker # docker配置文件夾
- 1
- 2
- 3
- 4
目錄結構如下:
- 2 .在compose_test/src/目錄下創建python flask應用 compose_test/src/app.py文件。
-
from flask import Flask
-
from redis import Redis
-
-
app = Flask(__name__)
-
redis = Redis(host= 'redis', port=6379)
-
-
-
def hello():
-
count = redis.incr( 'hits')
-
return 'Hello World! I have been seen {} times.\n'.format(count)
-
-
if __name__ == "__main__":
-
app.run(host= "0.0.0.0", debug=True)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 3 .創建python 需求文件 compose_test/docker/requirements.txt
-
flask
-
redis
- 1
- 2
Step 2: 創建容器的Dockerfile文件
一個容器一個Dockerfile文件
為了工程目錄更加清晰,在compose_test/docker/目錄下創建compose_test/docker/web目錄
-
$ cd docker
-
$ mkdir web
- 1
- 2
在compose_test/docker/web/目錄中創建Dockerfile文件:
FROM python:3.4
-
ADD . /docker
-
ADD ../../src /src
-
WORKDIR /src
-
RUN pip install -r /docker/requirements .txt
-
CMD ["python", "app.py"]
- 1
- 1
- 2
- 3
- 4
- 5
Dockerfile文件告訴docker了如下信息:
從Python 3.4鏡像開始構建一個容器鏡像。
復雜當前 . (即compose_test/docker)目錄到容器的/docker目錄。
復制../../src目錄(即compose_test/src) 到容器中的/src目錄(此處../../src是不合法的路徑,ADD的源路徑必須在Dockerfile文件的上下文環境中,即Dockerfile文件所在根目錄或起子目錄中,實際應該使用volumes掛載項目源文件)。
將容器的工作目錄設置為/src。
安裝Python依賴關系。
將容器的默認命令設置為python app.py。
Step 3: 定義docker-compose腳本
在compose_test/docker/目錄下創建docker-compose.yml文件,並在里面定義服務,內容如下:
-
version: '3'
-
services:
-
web:
-
build: ./web/
-
ports:
-
- "5000:5000"
-
redis:
-
image: "redis:3.0.7"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
這個compose文件定義了兩個服務,即定義了web和redis兩個容器。
web容器:
* 使用當前的web目錄(compose_test/docker/web/)中的Dockerfile構建映像。
* 將容器上的暴露端口5000映射到主機上的端口5000。 我們使用Flask Web服務器的默認端口5000。
redis容器:
* redis服務使用從Docker Hub提取的官方redis鏡像3.0.7版本。
Step 4: 使用Compose構建並運行您的應用程序
在compose_test/docker/目錄下執行docker-compose.yml文件:
-
$ docker-compose up
-
# 若是要后台運行: $ docker-compose up -d
-
# 若不使用默認的docker-compose.yml 文件名:
-
$ docker-compose -f server.yml up -d
- 1
- 2
- 3
- 4
然后在瀏覽器中輸入http://0.0.0.0:5000/查看運行的應用程序。
Step 5: 編輯compose文件以添加文件綁定掛載
上面的代碼是在構建時靜態復制到容器中的,即通過Dockerfile文件中的ADD ./src /src命令實現物理主機中的源碼復制到容器中,這樣在后續物理主機src目錄中代碼的更改不會反應到容器中。
可以通過volumes 關鍵字實現物理主機目錄掛載到容器中的功能(同時刪除Dockerfile中的ADD指令,不需要創建鏡像時將代碼打包進鏡像,而是通過volums動態掛載,容器和物理host共享數據卷):
-
version: '3'
-
services:
-
web:
-
build: .
-
ports:
-
- "5000:5000"
-
volumes:
-
- ../src :/src
-
redis:
-
image: "redis:3.0.7"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
通過volumes(卷)將主機上的項目目錄(compose_test/src)掛載到容器中的/src目錄下,允許您即時修改代碼,而無需重新構建映像。
Step 6: 重新構建和運行應用程序
使用更新的compose文件構建應用程序,然后運行它。
$ docker-compose up -d
- 1
6.compose常用服務配置參考
Compose文件是一個定義服務,網絡和卷的YAML文件。 Compose文件的默認文件名為docker-compose.yml。
**提示:您可以對此文件使用.yml或.yaml擴展名。 他們都工作。
與docker運行一樣,默認情況下,Dockerfile中指定的選項(例如,CMD,EXPOSE,VOLUME,ENV)都被遵守,你不需要在docker-compose.yml中再次指定它們。
同時你可以使用類似Bash的$ {VARIABLE} 語法在配置值中使用環境變量,有關詳細信息,請參閱變量替換。
本節包含版本3中服務定義支持的所有配置選項。
build
build 可以指定包含構建上下文的路徑:
-
version: '2'
-
services:
-
webapp:
-
build: ./dir
- 1
- 2
- 3
- 4
或者,作為一個對象,該對象具有上下文路徑和指定的Dockerfile文件以及args參數值:
-
version: '2'
-
services:
-
webapp:
-
build:
-
context: ./dir
-
dockerfile: Dockerfile-alternate
-
args:
-
buildno: 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
webapp服務將會通過./dir目錄下的Dockerfile-alternate文件構建容器鏡像。
如果你同時指定image和build,則compose會通過build指定的目錄構建容器鏡像,而構建的鏡像名為image中指定的鏡像名和標簽。
-
build: ./dir
-
image: webapp:tag
- 1
- 2
這將由./dir構建的名為webapp和標記為tag的鏡像。
context
包含Dockerfile文件的目錄路徑,或者是git倉庫的URL。
當提供的值是相對路徑時,它被解釋為相對於當前compose文件的位置。 該目錄也是發送到Docker守護程序構建鏡像的上下文。
dockerfile
備用Docker文件。Compose將使用備用文件來構建。 還必須指定構建路徑。
args
添加構建鏡像的參數,環境變量只能在構建過程中訪問。
首先,在Dockerfile中指定要使用的參數:
-
ARG buildno
-
ARG password
-
-
RUN echo "Build number: $buildno"
-
RUN script-requiring-password.sh "$password"
- 1
- 2
- 3
- 4
- 5
然后在args鍵下指定參數。 你可以傳遞映射或列表:
-
build:
-
context: .
-
args:
-
buildno: 1
-
password: secret
-
-
build:
-
context: .
-
args:
-
- buildno=1
-
- password=secret
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
** 注意:YAML布爾值(true,false,yes,no,on,off)必須用引號括起來,以便解析器將它們解釋為字符串。
image
指定啟動容器的鏡像,可以是鏡像倉庫/標簽或者鏡像id(或者id的前一部分)
-
image: redis
-
image: ubuntu:14.04
-
image: tutum/influxdb
-
image: example-registry.com:4000/postgresql
-
image: a4bc65fd
- 1
- 2
- 3
- 4
- 5
如果鏡像不存在,Compose將嘗試從官方鏡像倉庫將其pull下來,如果你還指定了build,在這種情況下,它將使用指定的build選項構建它,並使用image指定的名字和標記對其進行標記。
container_name
指定一個自定義容器名稱,而不是生成的默認名稱。
container_name: my-web-container
- 1
由於Docker容器名稱必須是唯一的,因此如果指定了自定義名稱,則無法將服務擴展到多個容器。
volumes
卷掛載路徑設置。可以設置宿主機路徑 (HOST:CONTAINER) 或加上訪問模式 (HOST:CONTAINER:ro),掛載數據卷的默認權限是讀寫(rw),可以通過ro指定為只讀。
你可以在主機上掛載相對路徑,該路徑將相對於當前正在使用的Compose配置文件的目錄進行擴展。 相對路徑應始終以 . 或者 .. 開始。
-
volumes:
-
-
- /var/lib/mysql
-
-
- /opt/data:/var/lib/mysql
-
-
- ./cache:/tmp/cache
-
-
- ~/configs:/etc/configs/:ro
-
-
- datavolume:/var/lib/mysql
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
但是,如果要跨多個服務並重用掛載卷,請在頂級volumes關鍵字中命名掛在卷,但是並不強制,如下的示例亦有重用掛載卷的功能,但是不提倡。
-
version: "3"
-
-
services:
-
web1:
-
build: ./web/
-
volumes:
-
- ../code:/opt/web/code
-
web2:
-
build: ./web/
-
volumes:
-
- ../code:/opt/web/code
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
** 注意:通過頂級volumes定義一個掛載卷,並從每個服務的卷列表中引用它, 這會替換早期版本的Compose文件格式中volumes_from。
-
version: "3"
-
-
services:
-
db:
-
image: db
-
volumes:
-
- data-volume:/var/lib/db
-
backup:
-
image: backup -service
-
volumes:
-
- data-volume:/var/lib/backup/data
-
-
volumes:
-
data-volume:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
command
覆蓋容器啟動后默認執行的命令。
command: bundle exec thin -p 3000
- 1
- 2
該命令也可以是一個類似於dockerfile的列表:
command: ["bundle", "exec", "thin", "-p", "3000"]
- 1
- 2
links
鏈接到另一個服務中的容器。 請指定服務名稱和鏈接別名(SERVICE:ALIAS),或者僅指定服務名稱。
-
web:
-
links:
-
- db
-
- db:database
-
- redis
- 1
- 2
- 3
- 4
- 5
在當前的web服務的容器中可以通過鏈接的db服務的別名database訪問db容器中的數據庫應用,如果沒有指定別名,則可直接使用服務名訪問。
鏈接不需要啟用服務進行通信 - 默認情況下,任何服務都可以以該服務的名稱到達任何其他服務。 (實際是通過設置/etc/hosts的域名解析,從而實現容器間的通信。故可以像在應用中使用localhost一樣使用服務的別名鏈接其他容器的服務,前提是多個服務容器在一個網絡中可路由聯通)
links也可以起到和depends_on相似的功能,即定義服務之間的依賴關系,從而確定服務啟動的順序。
external_links
鏈接到docker-compose.yml 外部的容器,甚至並非 Compose 管理的容器。參數格式跟 links 類似。
-
external_links:
-
- redis_1
-
- project_db_1:mysql
-
- project_db_1:postgresql
- 1
- 2
- 3
- 4
expose
暴露端口,但不映射到宿主機,只被連接的服務訪問。
僅可以指定內部端口為參數
-
expose:
-
- "3000"
-
- "8000"
- 1
- 2
- 3
ports
暴露端口信息。
常用的簡單格式:使用宿主:容器 (HOST:CONTAINER)格式或者僅僅指定容器的端口(宿主將會隨機選擇端口)都可以。
** 注意:當使用 HOST:CONTAINER 格式來映射端口時,如果你使用的容器端口小於 60 你可能會得到錯誤得結果,因為 YAML 將會解析 xx:yy 這種數字格式為 60 進制。所以建議采用字符串格式。
簡單的短格式:
-
ports:
-
- "3000"
-
- "3000-3005"
-
- "8000:8000"
-
- "9090-9091:8080-8081"
-
- "49100:22"
-
- "127.0.0.1:8001:8001"
-
- "127.0.0.1:5000-5010:5000-5010"
-
- "6060:6060/udp"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
在v3.2中ports的長格式的語法允許配置不能用短格式表示的附加字段。
長格式:
-
ports:
-
- target: 80
-
published: 8080
-
protocol: tcp
-
mode: host
- 1
- 2
- 3
- 4
- 5
target:容器內的端口
published:物理主機的端口
protocol:端口協議(tcp或udp)
mode:host 和ingress 兩總模式,host用於在每個節點上發布主機端口,ingress 用於被負載平衡的swarm模式端口。
restart
no是默認的重啟策略,在任何情況下都不會重啟容器。 指定為always時,容器總是重新啟動。 如果退出代碼指示出現故障錯誤,則on-failure將重新啟動容器。
-
restart: "no"
-
restart: always
-
restart: on-failure
-
restart: unless-stopped
- 1
- 2
- 3
- 4
environment
添加環境變量。 你可以使用數組或字典兩種形式。 任何布爾值; true,false,yes,no需要用引號括起來,以確保它們不被YML解析器轉換為True或False。
只給定名稱的變量會自動獲取它在 Compose 主機上的值,可以用來防止泄露不必要的數據。
-
environment:
-
RACK_ENV: development
-
SHOW: 'true'
-
SESSION_SECRET:
-
-
environment:
-
- RACK_ENV=development
-
- SHOW=true
-
- SESSION_SECRET
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
** 注意:如果你的服務指定了build選項,那么在構建過程中通過environment定義的環境變量將不會起作用。 將使用build的args子選項來定義構建時的環境變量。
pid
將PID模式設置為主機PID模式。 這就打開了容器與主機操作系統之間的共享PID地址空間。 使用此標志啟動的容器將能夠訪問和操作裸機的命名空間中的其他容器,反之亦然。即打開該選項的容器可以相互通過進程 ID 來訪問和操作。
pid: "host"
- 1
dns
配置 DNS 服務器。可以是一個值,也可以是一個列表。
-
dns: 8.8.8.8
-
dns:
-
- 8.8.8.8
-
- 9.9.9.9
- 1
- 2
- 3
- 4