本文是《Docker必知必會系列》第十二篇,原文發佈於個人博客:悟塵紀。
前言
Compose 配置文件採用 YAML 格式,用於定義 services(服務), networks(網絡)和 volumes(卷)。
文件的默認路徑爲./docker-compose.yml
。有多種版本格式——1、2、2.x 和3.x。 有關每個版本與Docker的兼容性、包含哪些內容以及如何升級的最新信息,請參閱官方文檔: 關於版本和升級。
服務定義包含應用於該服務啓動的每個容器的配置,就像將命令行參數傳遞給 docker run
一樣。同樣,網絡和卷定義類似於 docker network create
和docker volume create
。
與 docker run
一樣,Dockerfile 中指定的選項,例如 CMD
、 EXPOSE
、 VOLUME
、 ENV
,在缺省情況下都是遵守的——不需要再次以 docker-compose
方式指定它們。
您可以使用類似 Bash 的${VARIABLE}
語法在配置值中使用環境變量 - 有關完整詳細信息,請參見變量替換。
文件結構和示例
這是一個投票應用程序的 Compose 文件示例:
version: "3.8"
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:
配置指令
build
指定 Dockerfile
所在文件夾的路徑,Compose
將會利用它自動構建鏡像。如:
version: '3.8'
services:
webapp:
build: ./dir
context、dockerfile和args
可以使用 context
指定文件夾路徑(可以是包含 Dockerfile 的目錄路徑,也可以是 git 存儲庫的 url),使用 dockerfile
指定 Dockerfile
文件名,使用 arg
爲 Dockerfile
中的變量賦值。如:
version: '3.8'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
如果在 build
同時指定了 image
,那麼 Compose 會使用在 image
中指定的名字和標籤來命名最終構建的鏡像。如:
build: ./dir
image: webapp:tag
這將從 ./dir
構建,生成名爲 webapp
,標籤爲:tag
的鏡像。
cache_from
可以使用 cache_from
指定構建鏡像時使用的緩存:
build:
context: .
cache_from:
- alpine:latest
- corp/web_app:3.14
labels
通過標籤向生成的鏡像添加元數據:
build:
context: .
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
build:
context: .
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
network
設置構建期間 run
指令要鏈接的網絡:
build:
context: .
network: host # 可以設置爲 none 禁用網絡
sim_size
設置所構建容器的/dev/shm
分區大小:
build:
context: .
shm_size: '2gb'
target
按照在 Dockerfile
中定義的方式構建指定的階段。 有關詳細信息,請參閱 多階段構建 文檔。
build:
context: .
target: prod
cap_add, cap_drop
添加或刪除容器的內核能力:
cap_add:
- ALL # 讓容器擁有所有能力
cap_drop:
- NET_ADMIN # 移除 NET_ADMIN 功能
- SYS_ADMIN # 移除 SYS_ADMIN 功能
cgroup_parent
指定父 cgroup
組,意味着將繼承該組的資源限制,如:cgroup_parent: m-executor-abcd
command
覆蓋容器啓動後默認執行的命令。如:command: echo "hello world"
configs
使用configs
按服務授予對配置的訪問權限。詳細內容請查看 官方文檔。
container_name
指定容器名稱。默認將會使用 項目名稱_服務名稱_序號
這樣的格式。
container_name: lixl-web-container
注意: 指定容器名稱後,該服務將無法進行擴展(scale),因爲 Docker 不允許多個容器具有相同的名稱。
depends_on
指定服務之間的依賴關係,以便按順序啓動服務。以下例子中會先啓動 redis
db
再啓動 web
version: '3.8'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
注意:
web
服務不會等待redis
db
「完全啓動」之後才啓動。如果需要等待服務準備就緒,請參閱控制啓動順序 獲取有關此問題的更多信息以及解決該問題的策略。
deploy
僅用於 Swarm mode
,詳細內容請查看 官方文檔。
devices
指定設備映射關係。使用與 docker 客戶端 --device
相同的選項格式:
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
dns
自定義 DNS
服務器,可以是單個值或列表。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 114.114.114.114
dns_search
配置 DNS
搜索域,可以是單個值或列表。
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
entrypoint
重寫默認入口點,如:entrypoint: ["php", "-d", "memory_limit=-1", "vendor/bin/phpunit"]
env_file
從文件中添加環境變量。可以是單個值或列表。
如果通過 docker-compose -f FILE
方式來指定了 Compose 文件,則 env_file
中變量的路徑相對於文件所在目錄。
在 environment
聲明的變量,會覆蓋這些值。即使這些值爲空或未定義。
env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
env文件中每一行必須符合 VAL=VAL
格式,以 #
開頭的行被視爲註釋,並被忽略。空行也會被忽略。
# 設置環境
PRCK_ENV=development
environment
設置環境變量。你可以使用數組或字典兩種格式。任何布爾值(True、 False、 yes、 no)都需要用引號括起來,以確保 YML 解析器不會將它們轉換爲 True 或 False。
只有名稱的變量會自動解析爲 Compose 運行主機上對應變量的值,可以用來防止泄露不必要的數據。
environment:
RACK_ENV: development
SESSION_SECRET:
environment:
- RACK_ENV=development
- SESSION_SECRET
expose
在不將端口發佈到主機的情況下公開端口——它們只能被鏈接的服務訪問。 只能指定內部端口。
expose:
- "3000"
- "8000"
external_links
注意:不推薦使用,建議使用
networks
指令代替。
鏈接到 docker-compose.yml
外部的容器,甚至並非 Compose
管理的外部容器。
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
extra_hosts
添加主機名映射,使用與 Docker 中的 --add-host
參數相同的值:
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
會在啓動後的服務容器的 /etc/hosts
文件中添加如下兩條條目。
162.242.195.82 somehost
50.31.209.229 otherhost
healthcheck
通過命令檢查容器是否健康運行。
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
test
必須是字符串或列表。 如果是一個列表,則第一個參數必須是 NONE
、 CMD
或 CMD-shell
。 如果它是一個字符串,那麼它等價於指定 CMD-SHELL
,然後指定該字符串。以下寫法效果是一樣的。
# Hit the local web app
test: ["CMD", "curl", "-f", "http://localhost"]
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
test: curl -f https://localhost || exit 1
要禁用鏡像默認健康檢查設置,可以使用 disable: true
。 這相當於指定 test: [“NONE”]。
image
指定要從哪個鏡像啓動容器。如果鏡像在本地不存在,也沒有指定了 build
,Compose
將會嘗試拉取這個鏡像。
image: ubuntu
image: example-registry.com:4000/postgresql
image: a4bc65fd
init
在容器中運行一個 init,用於轉發信號和回收進程。 將此選項設置爲 true,以便爲服務啓用此特性。
version: "3.8"
services:
web:
image: alpine:latest
init: true
默認使用的 init 二進制文件是 Tini,並安裝在守護進程主機上的
/usr/libexec/docker-init
中。 可以通過init-path
配置選項將守護進程配置爲使用自定義 init 二進制文件。
labels
爲容器添加 Docker 元數據(metadata)信息。
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
logging
配置日誌選項。
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.0.42:123"
驅動程序名稱爲服務的容器指定了一個日誌驅動程序,與 docker 運行 ---log-driver
選項一樣。
driver: "json-file" # 默認值
driver: "syslog"
driver: "none"
只有
json-file
和journald
驅動程序可以直接從docker-compose up
和docker-compose logs
中獲得日誌。 使用其他驅動程序都不打印日誌。
可以使用 options
配置日誌驅動的相關參數。與 docker run
的 --log-opt
選項一樣。如 json-file
支持的:
options:
max-size: "200k"
max-file: "10"
network_mode
設置網絡模式。和 docker run
的 --network
參數一樣。
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
networks
配置容器連接的網絡。
services:
some-service:
networks:
- some-network
- other-network
networks:
some-network:
other-network:
aliases
同一網絡上的其他容器可以使用服務名稱或這個別名連接到服務的一個容器。由於別名是網絡範圍的,同一個服務在不同的網絡上可以有不同的別名。
version: "3.8"
services:
web:
image: "nginx:alpine"
networks:
- new
worker:
image: "my-worker-image:latest"
networks:
- legacy
db:
image: mysql
networks:
new:
aliases:
- database
legacy:
aliases:
- mysql
networks:
new:
legacy:
在上面的示例中,提供了三個服務(web
、 worker
和 db
)以及兩個網絡(new
和 legacy
)。 db
服務在 new
網絡上的主機名爲 db
或 database
,在 legacy
網絡上主機名爲 db
或 mysql
。
pid
將 PID 模式設置爲 host
,將與主機系統共享進程命名空間。使用此標誌啓動的容器可以訪問和操作宿主機名稱空間中的其他容器,反之亦然。
ports
暴露端口信息。使用 HOST:CONTAINER
格式,或者僅指定容器端口(宿主機將隨機選擇端口)都可以。
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"
- "12400-12500:1240"
當使用
HOST:CONTAINER
格式來映射端口時,如果使用的容器端口小於 60 並且沒放到引號裏,可能會得到錯誤結果,因爲YAML
會自動解析xx:yy
這種數字格式爲 60 進制。爲避免出現這種問題,建議數字串都採用引號包括起來的字符串格式。
secrets
存儲敏感數據,例如 mysql
服務密碼。
version: "3.8"
services:
redis:
image: redis:latest
deploy:
replicas: 1
secrets:
- my_secret
- my_other_secret
secrets:
my_secret:
file: ./my_secret.txt
my_other_secret:
external: true
以上示例授予redis
服務對my_secret
和my_other_secret
祕密的訪問權限。 my_secret
的值設置爲文件./my_secret.txt
的內容,並將 my_other_secret
定義爲外部資源,這意味着它已經在Docker中定義,可以通過運行docker secret create
命令進行定義。如果外部機密不存在,則部署將失敗並顯示secret not found
錯誤。
security_opt
指定容器模板標籤(label)機制的默認屬性(用戶、角色、類型、級別等)。例如配置標籤的用戶名和角色名。
security_opt:
- label:user:USER
- label:role:ROLE
stop_grace_period
指定 stop_signal
在發送 SIGKILL
之前,如果容器無法處理 SIGTERM
(或已使用指定的任何停止信號)而試圖停止容器的等待時間 。
stop_grace_period: 1s
stop_grace_period: 1m30s
默認情況下,stop
在發送 SIGKILL
之前等待10秒以退出容器。
stop_signal
設置替代信號來停止容器。在默認情況下使用的是 SIGTERM 停止容器。
stop_signal: SIGUSR1
sysctls
配置容器內核參數。
sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0
sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
tmpfs
掛載一個臨時文件系統到容器。
tmpfs: /run
tmpfs:
- /run
- /tmp
ulimits
指定容器的 ulimits 限制值。
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
volumes
數據卷所掛載路徑設置。可以設置爲宿主機路徑(HOST:CONTAINER
)或者數據卷名稱(VOLUME:CONTAINER
),並且可以設置訪問模式 (HOST:CONTAINER:ro
)。
該指令中路徑支持相對路徑。
volumes:
- /var/lib/mysql
- cache/:/tmp/cache
- ~/configs:/etc/configs/:ro
如果路徑爲數據卷名稱,必須在文件中配置數據卷。
version: "3"
services:
my_sql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
其它指令
此外,還有包括 domainname, hostname, ipc, mac_address, privileged, read_only, shm_size, restart, stdin_open, tty, user, working_dir
等指令,基本跟 docker run
中對應參數的功能一致。
指定容器中運行應用的用戶名。
user: nginx
指定容器中工作目錄。
working_dir: /code
指定容器中搜索域名、主機名、mac 地址等。
domainname: your_website.com
hostname: test
mac_address: 08-00-27-00-0C-0A
允許容器中運行一些特權命令。
privileged: true
指定容器退出後的重啓策略爲始終重啓。該命令對保持服務始終運行十分有效,在生產環境中推薦配置爲 always
或者 unless-stopped
。
restart: always
以只讀模式掛載容器的 root 文件系統,意味着不能對容器內容進行修改。
read_only: true
打開標準輸入,可以接受外部輸入。
stdin_open: true
模擬一個僞終端。
tty: true
讀取變量
Compose 模板文件支持動態讀取主機的系統環境變量和當前目錄下的 .env
文件中的變量。
例如,下面的 Compose 文件將從運行它的環境中讀取變量 ${MONGO_VERSION}
的值,並寫入執行的指令中。
version: "3"
services:
db:
image: "mongo:${MONGO_VERSION}"
如果執行 MONGO_VERSION=3.2 docker-compose up
則會啓動一個 mongo:3.2
鏡像的容器。
若當前目錄存在 .env
文件,執行 docker-compose
命令時將從該文件中讀取變量。
在當前目錄新建 .env
文件並寫入以下內容。
# 支持註釋
MONGO_VERSION=3.6
執行 docker-compose up
則會啓動一個 mongo:3.6
鏡像的容器。
參考
- 官方文檔: Compose file
- Compose文件示例:Awesome compose
- Compose模板文件
相關文章
- 上一篇:Docker必知必會系列(附錄3):Docker-compose 命令使用指南
- 下一篇:沒有了
寫在最後
至此,本系列文章已經閱讀完成。
獲取最新內容,請訪問我的個人博客:悟塵紀。