docker-compose檔案結構
docker-compose.yml:
version: '2'
services:
web:
image: dockercloud/hello-world
ports:
- 8080
networks:
- front-tier
- back-tier
redis:
image: redis
links:
- web
networks:
- back-tier
lb:
image: dockercloud/haproxy
ports:
- 80:80
links:
- web
networks:
- front-tier
- back-tier
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
front-tier:
driver: bridge
back-tier:
driver: bridge
可以看到一份标準配置檔案應該包含 version、services、networks 三大部分,其中最關鍵的就是 services 和 networks 兩個部分,下面先來看 services 的書寫規則。
image: 指定容器啟動的鏡像,對應 Dockerfile FROM。
在 services 标簽下的第二級标簽是 :
web,這個名字是使用者自己自定義,它就是服務名稱。
image 則是指定服務的鏡像名稱或鏡像 ID。如果鏡像在本地不存在,Compose 将會嘗試拉取這個鏡像。
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
build: 服務除了可以基于指定的鏡像,還可以基于一份 Dockerfile,在使用 up 啟動之時執行建構任務,這個建構标簽就是 build,它可以指定 Dockerfile 所在檔案夾的路徑。Compose 将會利用它自動建構這個鏡像,然後使用這個鏡像啟動服務容器。
最簡單的直接利用 Dockerfile 建構,隻需要指定上下文或者 Dockerfile 位置:
version: '2'
services:
webapp:
build: .
如果需要更細粒度的配置,需要使用 context, dockerfile, args, labels 等選項
# Dockerfile
ARG buildno
ARG password
RUN echo "Build number: $buildno"
RUN script-requiring-password.sh "$password"
# docker-compose file
version: '2'
services:
webapp:
image: webapp:tag
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
password: secret
command: 使用 command 可以覆寫容器啟動後預設執行的指令。
command: bundle exec thin -p 3000
command: ["bundle", "exec", "thin", "-p", "3000"]
container_name: 指定運作時容器名稱,而不使用預設格式(<項目名稱><服務名稱><序号>)。
container_name: my-web-container
depends_on: 指明服務之間依賴,解決了容器的依賴、啟動先後的問題。
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
被依賴的服務會優先啟動(顯然)
若服務啟動時被依賴服務沒有啟動,則自動被啟動
dns: 指定 DNS 伺服器。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
tmpfs: 挂載臨時目錄到容器内部,與 run 的參數一樣效果:
tmpfs: /run tmpfs: - /run - /tmp
entrypoint: 在 Dockerfile 中有一個指令叫做 ENTRYPOINT 指令,用于指定接入點,在 docker-compose.yml 中可以定義接入點,覆寫 Dockerfile 中的定義。
entrypoint: /code/entrypoint.sh
env_file: 專門存放變量的檔案。如果通過 docker-compose -f FILE 指定了配置檔案,則 env_file 中路徑會使用配置檔案路徑。如果有變量名稱與 environment 指令沖突,則以後者為準。格式如下:
env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
檔案格式如:
RACK_ENV=development
注意的是這裡所說的環境變量是對主控端的 Compose 而言的,如果在配置檔案中有 build 操作,這些變量并不會進入建構過程中,如果要在建構中使用變量還是首選前面剛講的 arg 标簽。
environment: 與上面的 env_file 标簽完全不同,反而和 arg 有幾分類似,這個标簽的作用是設定鏡像變量,它可以儲存變量到鏡像裡面,也就是說啟動的容器也會包含這些變量設定,這是與 arg 最大的不同。
一般 arg 标簽的變量僅用在建構過程中。而 environment 和 Dockerfile 中的 ENV 指令一樣會把變量一直儲存在鏡像、容器中,類似 docker run -e 的效果。
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
expose: 這個标簽與 Dockerfile 中的 EXPOSE 指令一樣,用于指定暴露的端口,但是隻是作為一種參考,實際上 docker-compose.yml 的端口映射還得 ports 這樣的标簽。
expose:
- "3000"
- "8000"
external_links: 在使用 Docker 過程中,我們會有許多單獨使用docker run啟動的容器,為了使 Compose 能夠連接配接這些不在 docker-compose.yml 中定義的容器,我們需要一個特殊的标簽,就是 external_links,它可以讓 Compose 項目裡面的容器連接配接到那些項目配置外部的容器(前提是外部容器中必須至少有一個容器是連接配接到與項目内的服務的同一個網絡裡面)。
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
extra_hosts: 添加主機名的标簽,就是往 /etc/hosts 檔案中添加一些記錄、
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
labels: 向容器添加中繼資料,和 Dockerfile 的 LABEL 指令一個意思。
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
links: 上面的 depends_on 标簽解決的是啟動順序問題,這個标簽解決的是容器連接配接問題,與 Docker client 的 –link 一樣效果,會連接配接到其它服務中的容器。。
web:
links:
- db
- db:database
- redis
使用的别名将會自動在服務容器中的 /etc/hosts 裡建立。
相應的環境變量也将被建立。
logging: 用于配置日志服務。預設的 driver 是 json-file。
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.0.42:123"
pid: 将 PID 模式設定為主機 PID 模式,跟主機系統共享程序命名空間。容器使用這個标簽将能夠通路和操縱其他容器和主控端的名稱空間。
pid: "host"
ports: 映射端口的标簽。使用 HOST:CONTAINER 格式或者隻是指定容器的端口,主控端會随機映射端口。
ports:
- "3000"
- "8000:8000"
- "49100:22"
- "127.0.0.1:8001:8001"
注意:當使用 HOST:CONTAINER 格式來映射端口時,如果你使用的容器端口小于 60 你可能會得到錯誤得結果,因為 YAML 将會解析 xx:yy 這種數字格式為 60 進制。是以建議采用字元串格式。
security_opt: 為每個容器覆寫預設的标簽。簡單說來就是管理全部服務的标簽。比如設定全部服務的 user 标簽值為 USER:
security_opt:
- label:user:USER
- label:role:ROLE
stop_signal: 設定另一個信号來停止容器。在預設情況下使用的是 SIGTERM 停止容器。設定另一個信号可以使用 stop_signal 标簽。
stop_signal: SIGUSR1
volumes: 挂載一個目錄或者一個已存在的資料卷容器,可以直接使用 HOST:CONTAINER 這樣的格式,或者使用 HOST:CONTAINER:ro 這樣的格式,後者對于容器來說,資料卷是隻讀的,這樣可以有效保護主控端的檔案系統。
volumes:
# 隻是指定一個路徑,Docker 會自動在建立一個資料卷(這個路徑是容器内部的)。
- /var/lib/mysql
# 使用絕對路徑挂載資料卷
- /opt/data:/var/lib/mysql
# 以 Compose 配置檔案為中心的相對路徑作為資料卷挂載到容器。
- ./cache:/tmp/cache
# 使用使用者的相對路徑(~/ 表示的目錄是 /home/<使用者目錄>/ 或者 /root/)。
- ~/configs:/etc/configs/:ro
# 已經存在的命名的資料卷。
- datavolume:/var/lib/mysql
cap_add, cap_drop: 添加或删除容器的核心功能。
devices: 裝置映射清單。與 Docker client 的--device參數類似。
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
extends: 這個标簽可以擴充另一個服務,擴充内容可以是來自在目前檔案,也可以是來自其他檔案,相同服務的情況下,後來者會有選擇地覆寫原有配置。
extends:
file: common.yml
service: webapp
使用者可以在任何地方使用這個标簽,隻要标簽内容包含 file 和 service 兩個值就可以了。file 的值可以是相對或者絕對路徑,如果不指定 file 的值,那麼 Compose 會讀取目前 YML 檔案的資訊。
詳細的 Compose file 選項參見:Compose file version 3 reference
Compose file 的很多選項都類似 Dockerfile,可以對應起來學習: Dockerfile 指令
運作 Compose
這裡同時啟動 8 個 spider 服務:
$ docker-compose up -d --scale spider=8
Compose 指令行工具
使用指令docker-compose --help可檢視指令工具支援的指令和參數。
docker-compose help [COMMAND] 檢視指令詳情。
Define and run multi-container applications with Docker.
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate Compose file (default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name (default: directory name)
--verbose Show more output
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to
--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the name specified
in the client certificate (for example if your docker host
is an IP address)
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
其中,最常用的指令為:
- build: 根據 docker-compose file 指定的鏡像和選項建構鏡像,如果事先使用 Dockerfile 編譯好鏡像則無需 build,直接使用下面的 up 啟動。
$ docker-compose build .
up: 類似 Docker,Compose 使用 up 啟動容器,使用制定的參數來執行,并将所有的日志輸出合并到一起。
$ docker-compose up
如果啟動時指定-d标志,則以守護程序模式運作服務。
$ docker-compose up -d
如果要批量啟動服務(如啟動 8 個 Scrapy),則在--scale選項指定服務的個數:
$ docker-compose up -d --scale spider=8
ps: 列出本地 docker-compose.yml 檔案裡定義的正在運作的所有服務。
$ docker-compose ps
logs: 檢視服務的日志,這個指令會追蹤服務的日志檔案,類似tail -f指令,使用Ctrl+C退出。
$ docker-compose logs
stop: 停止所有服務,如果服務沒有停止,可以使用docker-compose kill強制殺死服務。
$ docker-compose stop
rm: 删除所有服務。
$ docker-compose rm
最後,以一個官方 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: