Dockerfile 最佳實踐及示例講解

Dockerfile 最佳實踐已經出如今官方文檔中,地址在 Best practices for writing Dockerfiles。若是再寫一份最佳實踐,倒有點關公門前耍大刀之意。所以本篇文章是對官方文檔的翻譯,理解,擴展與示例補充html

若是本篇文章可以對你有所幫助,能夠幫我在 shfshanyue/op-note 上點個 star前端

容器應該是短暫的

經過 Dockerfile 構建的鏡像所啓動的容器應該儘量短暫 (ephemeral)。短暫意味着能夠很快地啓動而且終止node

使用 .dockerignore 排除構建無關文件

.dockerignore 語法與 .gitignore 語法一致。使用它排除構建無關的文件及目錄,如 node_modulespython

使用多階段構建

多階段構建能夠有效減少鏡像體積,特別是對於需編譯語言而言,一個應用的構建過程每每以下nginx

  1. 安裝編譯工具
  2. 安裝第三方庫依賴
  3. 編譯構建應用

而在前兩步會有大量的鏡像體積冗餘,使用多階段構建能夠避免這一問題git

這是構建 Go 應用的一個示例github

FROM golang:1.11-alpine AS build

# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git RUN go get github.com/golang/dep/cmd/dep 
# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/ WORKDIR /go/src/project/ # Install library dependencies
RUN dep ensure -vendor-only 
# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/ RUN go build -o /bin/project 
# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project ENTRYPOINT ["/bin/project"] CMD ["--help"] 複製代碼

這是構建前端應用的一個示例,能夠參考 如何使用 docker 高效部署前端應用golang

FROM node:10-alpine as builder

ENV PROJECT_ENV production
ENV NODE_ENV production

# http-server 不變更也能夠利用緩存
WORKDIR /code 
ADD package.json /code RUN npm install --production 
ADD . /code RUN npm run build 
# 選擇更小體積的基礎鏡像
FROM nginx:10-alpine
COPY --from=builder /code/public /usr/share/nginx/html 複製代碼

避免安裝沒必要要的包

減少體積,減小構建時間。如前端應用使用 npm install --production 只裝生產環境所依賴的包。web

一個容器只作一件事

如一個web應用將會包含三個部分,web 服務,數據庫與緩存。把他們解耦到多個容器中,方便橫向擴展。若是你須要網絡通訊,則能夠將他們至於一個網絡下。面試

如在個人我的服務器中,我使用 traefik 作負載均衡與服務發現,全部應用及數據庫都在 traefik_default 網絡下,詳情參考 使用 traefik 作負載均衡與服務發現

version: '3'

services:
  # 該鏡像會暴露出自身的 `header` 信息
 whoami:
 image: containous/whoami
 restart: always
 labels:
      # 設置Host 爲 whoami.docker.localhost 進行域名訪問
 - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"

# 使用已存在的 traefik 的 network
networks:
 default:
 external:
 name: traefik_default
複製代碼

減小鏡像層數

  • 只有 RUN, COPY, ADD 會建立層數, 其它指令不會增長鏡像的體積
  • 儘量使用多階段構建

使用如下方法安裝依賴

RUN yum install -y node python go 複製代碼

錯誤的方法安裝依賴,這將增長鏡像層數

RUN yum install -y node RUN yum install -y python RUN yum install -y go 複製代碼

將多行參數排序

便於可讀性以及不當心地重複裝包

RUN apt-get update && apt-get install -y \ bzr \ cvs \ git \ mercurial \ subversion 複製代碼

充分利用構建緩存

在鏡像的構建過程當中 docker 會遍歷 Dockerfile 文件中的全部指令,順序執行。對於每一條指令,docker 都會在緩存中查找是否已存在可重用的鏡像,不然會建立一個新的鏡像

咱們可使用 docker build --no-cache 跳過緩存

  • ADDCOPY 將會計算文件的 checksum 是否改變來決定是否利用緩存
  • RUN 僅僅查看命令字符串是否命中緩存,如 RUN apt-get -y update 可能會有問題

如一個 node 應用,能夠先拷貝 package.json 進行依賴安裝,而後再添加整個目錄,能夠作到充分利用緩存的目的。

FROM node:10-alpine as builder

WORKDIR /code 
ADD package.json /code # 此步將能夠充分利用 node_modules 的緩存
RUN npm install --production 
ADD . /code 
RUN npm run build 複製代碼

我是山月,你能夠添加我微信 shanyue94 與我交流

若是你對全棧面試,前端工程化,graphql,devops,我的服務器運維以及微服務感興趣的話,能夠關注我
相關文章
相關標籤/搜索