Dockerfile最佳實踐

前言

本文參考Docker官方文檔
撰寫Dockerfile我們有幾個大前提

  1. 變化最少的部分放在Dockerfile的前面,變化大的放在後面,這樣持續集成的時候可以重複使用之前的layer
  2. 一個容器應該只運行單個應用,不要寫一個腳本在一個容器中同時運行多個應用

構建高效和可維護的鏡像

.dockerignore

  1. 防止不需要的文件拷貝到build context
  2. 寫法和.gitignore相似,請參考

使用多階段構建

FROM golang:1.11.1-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"]

FROM

  1. FROM基礎鏡像時最好精確到最小範圍的版本,而不要直接使用大版本和latest。比如FROM golang:1.12.1, 而不是FROM golang:1.12, FROM golang:latest
  2. 可以根據需要選擇alpine鏡像,不過編譯時可能要添加CGO_ENABLED=0

RUN

  1. 將多個RUN指令合併到一個
  2. 每個RUN指令後刪除多餘文件,例如:
FROM ubuntu:16.04

RUN apt-get update \
    && apt-get install -y nodejs \
    # added lines
    && rm -rf /var/lib/apt/lists/*

ADD . /app
RUN cd /app && npm install

CMD npm start

COPY&ADD

  1. 儘量將多個COPY指令合併到一個
  2. 儘量將多個ADD指令合併到一個
  3. COPY指令非常簡單,僅用於將文件拷貝到鏡像中。ADD相對來講複雜一些,可以用於下載遠程文件以及解壓壓縮包
  • 如果你確定只是拷貝文件進入鏡像中,那麼直接使用COPY
  • 如果你是需要下載文件等,那麼使用ADD

COPY&RUN

我們應該把變化最少的部分放在 Dockerfile 的前面,這樣可以充分利用鏡像緩存。

示例中,源代碼會經常變化,則每次構建鏡像時都需要重新安裝 NPM 模塊,這顯然不是我們希望看到的。因此我們可以先拷貝package.json,然後安裝 NPM 模塊,最後才拷貝其餘的源代碼。這樣的話,即使源代碼變化,也不需要重新安裝 NPM 模塊。

FROM node:10.18.1-alpine3.9

WORKDIR /app

COPY package.json /app
RUN npm install
COPY . /app

ENTRYPOINT ["./entrypoint.sh"]
CMD ["start"]

LABEL

  1. 儘量把多個LABEL標籤合併
    例如:
# Set multiple labels on one line
LABEL com.example.version="0.0.1-beta" com.example.release-date="2015-02-12"
# Set multiple labels at once, using line-continuation characters to break long lines
LABEL vendor=ACME\ Incorporated \
      com.example.is-beta= \
      com.example.is-production="" \
      com.example.version="0.0.1-beta" \
      com.example.release-date="2015-02-12"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章