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,我的服务器运维以及微服务感兴趣的话,能够关注我
相关文章
相关标签/搜索