Dockerfile詳解
0. Dockerfile的作用
docker可以根據Dockerfile中的指令來構建docker鏡像。Dockerfile是一個文本文件,其應當包含用戶想要構建一個鏡像的所有指令。
1. 構建鏡像的流程
真正執行構建任務的(就是讀取Dockerfile中的指令構建新的鏡像)是docker deamon。
- 執行 docker build -t images-name:tag .
- docker client會先將 當前目錄下的所有文件遞歸的發送給docker deamon
- docker deamon檢查Dockerfile是否有有語法錯誤,有錯誤則停止構建並將錯誤發送給docker client,沒有錯誤繼續執行
- docker deamon根據Dockerfile中的指令,一行一行的進行鏡像的構建
- 構建成功后,docker deamon自動清理context.
1. Dockerfile支持的指令
- FROM <image>[:tag] #代表着一個新的build stage的開始,並確定這個build是基於哪個鏡像來構建新的鏡像,在所有的指令中只有這個是必須要有的。
- ENV <key>=<value> | <key> <value> #配置環境變量,注意此配置會在container中生效。前一種可以一行聲明多個環境變量,后一種一行一個。
- ARG <key>[=<value>] #變量,此變量的聲明周期與dockerfile構建過程一致,不會在container中生效。可以通過build時添加--build-arg <key>=<value>進行覆蓋。注意:ARG時唯一可以放到FROM之前的指令,當ARG放到FROM之前時,它的作用於只到FROM這一行。
- COPY src dest # 將src代表的文件或者文件夾拷貝到dest代表的目錄下。src支持通配符* ?
- ADD src dest #將src代表的文件或者文件夾或者網絡資源 拷貝到 dest代表的base-image的目錄下。src支持通配符 * ?
- RUN command #docker deamon在構建新的鏡像時,是通過先基於FROM的鏡像開啟一個container,然后在這個container里執行。RUN指令就是是你想在container中執行的command。
- ENTRYPOINT ["executable", "param1", "param2"] | command param1 param2 # 將鏡像變成一個executable。推薦用CMD來代替。
- CMD ["executable", "param1", "parama2"] | ["param1", "param2"] | command param1 param2 # 最后有一個CMD指令才有效,它代表這個image被用來創建container成功后執行的命令。第二種形式需要個ENTRYPOINT指令結合使用。
- LABEL <key>=<value> <key>=<value> #代表着這個image的元信息,比如此image的描述,版本,作者信息等等。
- EXPOSE port[/protocol] #通過這個image啟動的container將會監聽這些端口。但是注意這個只是在container內部監聽的端口,當你想通過主機訪問時需要在啟動container時用-p這進行映射。
- USER <user>[:<group>] | <UID>[:<GID>] #在這個指令之后的操作,以及運行container時,指定為此用戶。
- WORKDIR /path #在此指令之后的操作,以及container的默認進入路徑都將時 /path目錄。
- VOLUME ['/path1', '/path2'] #基於此鏡像創建的container都將擁有VOLUME中指定的掛在目錄。注意映射的主機目錄無法指定,有docker deamon自動生成,可以通過docker inspect查看Mounts屬性。
2. Dockerfile編寫優化
1. 一個docker image只負責一個職責。當有多個服務時,請將服務分別docker化,然后組合使用這些docker images。
2. 就像編程一樣,當一個字符串出現多次時,請用ARG來聲明變量取代hard code。
3. 拷貝文件到鏡像時,ADD負責網絡資源的拷貝,COPY負責本地文件的COPY。
4. 盡量使用cache,docker在build鏡像時可以利用緩存,緩存的原則時:當重復構建時,如果單個指令的內容沒有變化,則docker會默認使用cache。
5. 將相同變化頻率的RUN指令合並成一個。注意,一定要是相同變化頻率的RUN命令才能合並成一個,不然緩存的特性就無法使用了。
6. 合理使用.dockerignore,減少images的體積。
7. 盡量使用CMD,VOLUME將image進行服務化。
8. 使用LABEL對image進行元信息的描述。
9. 單一服務的基礎鏡像如何可以請使用alpine版本的鏡像來減少image的體積。