# Compose規范 - Build
[TOC]
*注意:*Build是Compose規范的可選部分
## 介紹
Compose規范是定義多容器應用程序的一種與平臺無關的方法。專注于開發用例以在本地計算機上運行應用程序的Compose實現顯然也將支持(重新)從源代碼構建應用程序。Compose Build規范允許以可移植的方式在Compose文件中定義構建過程。
## 定義
擴展了Compose Specification,以支持`build`關于服務的OPTIONAL小節。本部分定義了服務容器映像的構建要求。只有Compose文件服務的一個子集可以定義這樣的Build子節,其他子集是基于`Image`屬性創建的。當服務的構建子節存在時,對于Compose文件而言,錯過相應服務的屬性是*有效*的`Image`,因為Compose實現可以從源代碼構建映像。
構建可以指定為定義上下文路徑的單個字符串,也可以指定為詳細的構建定義。
在前一種情況下,整個路徑都用作Docker上下文來執行Docker構建,`Dockerfile`并在上下文根中查找規范。上下文路徑可以是絕對路徑,也可以是相對路徑,如果是這樣,則必須從Compose文件父文件夾解析相對路徑。作為防止Compose文件可移植的絕對路徑,Compose實現應相應警告用戶。
在后一種情況下,可以指定build參數,包括備用`Dockerfile`位置。此路徑可以是絕對路徑,也可以是相對路徑。如果Dockerfile路徑是相對路徑,則必須從上下文路徑解析它。作為絕對路徑,防止Compose文件可移植,如果使用絕對替代Dockerfile路徑,則Compose實現應警告用戶。
## 鏡像一致性
當服務定義同時包含`Image`屬性和`Build`部分時,Compose實現不能保證提取的鏡像嚴格等同于從源構建相同的鏡像。如果沒有任何明確的用戶指令,帶有Build支持的Compose實現必須首先嘗試拉取Image,然后在注冊表中未找到Image的情況下從源代碼進行構建。Compose實現可以提供選項,以根據用戶請求自定義此行為。
## 發布構建的鏡像
具有構建支持的組合實現應提供一個選項,可將構建的映像推送到注冊表。這樣做,它一定不要嘗試在沒有`Image`屬性的情況下推送服務映像。Compose實現應向用戶發出有關`Image`屬性缺失的警告,以防止鏡像被推送。
`Image`如果未在yaml文件中明確聲明,則撰寫實現可以提供一種計算服務屬性的機制。在這種情況下,`Image`只要實際的原始yaml文件未顯式聲明一個有效的屬性,就認為所得的Compose配置具有有效的屬性。
## 說明性的例子
下面的示例通過一個具體的示例應用程序說明了Compose規范概念。該樣本是非規范性的
~~~yaml
services:
frontend:
image: awesome/webapp
build: ./webapp
backend:
image: awesome/database
build:
context: backend
dockerfile: ../backend.Dockerfile
custom:
build: ~/custom
~~~
當用于從源代碼構建服務映像時,這樣的Compose文件將創建三個docker映像:
* `awesome/webapp`docker映像是使用`webapp`Compose文件父文件夾中的子目錄作為docker build上下文構建的。`Dockerfile`此文件夾中缺少會引發錯誤。
* `awesome/database`使用`backend`Compose文件父文件夾中的子目錄構建docker映像。`backend.Dockerfile`文件用于定義構建步驟,相對于上下文路徑搜索此文件,這意味著此示例`..`將解析為Compose文件的父文件夾,而`backend.Dockerfile`同級文件也將解析為。
* 使用`custom`用戶主目錄中的目錄作為docker上下文構建docker映像。Compose實現會警告用戶有關用于構建映像的非便攜式路徑。
在推送時,`awesome/webapp`和`awesome/database`docker鏡像都被推送到(默認)注冊表。`custom`由于未`Image`設置任何屬性,因此會跳過服務映像,并警告用戶有關此丟失的屬性。
## Build定義
The`build`element define configuration options that are applied by Compose implementations to build Docker image from source.`build`can be specified either as a string containing a path to the build context or a detailed structure:
`build`元件定義由Compose實現施加到從源代碼編譯映像配置選項。`build`可以指定為包含構建上下文路徑的字符串或詳細結構:
~~~yaml
services:
webapp:
build: ./dir
~~~
使用此字符串語法,只能將構建上下文配置為Compose文件的父文件夾的相對路徑。此路徑必須是目錄,并包含一個`Dockerfile`。
另外,`build`也可以是一個對象,其字段定義如下
### context (必須)
`context`定義包含Dockerfile的目錄的路徑或git存儲庫的URL。
如果提供的值是相對路徑,則必須將其解釋為相對于Compose文件的位置。撰寫實現必須警告用戶有關用于定義構建上下文的絕對路徑,因為它們會阻止撰寫文件可移植。
~~~yaml
build:
context: ./dir
~~~
### dockerfile
`dockerfile`允許設置備用Dockerfile。必須從構建上下文中解析相對路徑。Compose的實現必須警告用戶有關用于定義Dockerfile的絕對路徑,因為這些絕對路徑會阻止Compose的文件可移植。
~~~yaml
build:
context: .
dockerfile: webapp.Dockerfile
~~~
### args
`args`定義構建參數,即Dockerfile`ARG`值。
使用以下Dockerfile:
~~~dockerfile
ARG GIT_COMMIT
RUN echo "Based on commit: $GIT_COMMIT"
~~~
`args`可以在Compose文件中的`build`定義鍵下設置`GIT_COMMIT`。`args`可以設置映射或列表:
~~~yaml
build:
context: .
args:
GIT_COMMIT: cdc3b19
~~~
~~~yaml
build:
context: .
args:
- GIT_COMMIT=cdc3b19
~~~
在指定構建參數時可以省略值,在這種情況下,必須在構建時通過用戶交互獲取其值,否則在構建Docker映像時將不會設置build arg。
~~~yaml
args:
- GIT_COMMIT
~~~
### cache_from
`cache_from`定義圖像構建器應用于緩存解析的圖像列表。
~~~yaml
build:
context: .
cache_from:
- alpine:latest
- corp/web_app:3.14
~~~
### extra_hosts
`extra_hosts`在構建時添加主機名映射。使用與[extra_hosts](spec.md)相同的語法。
~~~yaml
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
~~~
Compose實現必須在容器的網絡配置中創建具有IP地址和主機名的匹配條目,這意味著對于Linux,這`/etc/hosts`將獲得額外的內容:
~~~
162.242.195.82 somehost
50.31.209.229 otherhost
~~~
### isolation
`isolation`指定構建的容器隔離技術。像[隔離](spec.md)(isolation)一樣,受支持的值是特定于平臺的。
### labels
`labels`將元數據添加到生成的圖像。`labels`可以設置為數組或映射。
反向DNS表示法應用于防止標簽與其他軟件使用的標簽沖突。
~~~yaml
build:
context: .
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
~~~
~~~yaml
build:
context: .
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
~~~
### shm_size
`shm_size`設置`/dev/shm`為構建Docker映像分配的共享內存(Linux上的分區)的大小。指定為表示字節數的整數值或表示[字節值](spec.md)(specifying-byte-values)的字符串。
~~~yaml
build:
context: .
shm_size: '2gb'
~~~
~~~yaml
build:
context: .
shm_size: 10000000
~~~
### target
`target`定義要在multi-stage中定義的構建階段`Dockerfile`。
~~~yaml
build:
context: .
target: prod
~~~
## 實作
* [docker-compose](https://docs.docker.com/compose)
* [buildX bake](https://docs.docker.com/buildx/working-with-buildx/)