Dockerfile 最佳实践已经出现在官方文档中,地址在 Best practices for writing Dockerfiles。如果再写一份最佳实践,倒有点关公门前耍大刀之意。因此本篇文章是对官方文档的翻译,理解,扩展与示例补充

容器应该是短暂的

通过 Dockerfile 构建的镜像所启动的容器应该尽可能短暂 (ephemeral)。短暂意味着可以很快地启动并且终止

使用 .dockerignore 排除构建无关文件

.dockerignore 语法与 .gitignore 语法一致。使用它排除构建无关的文件及目录,如 node_modules

使用多阶段构建

多阶段构建可以有效减小镜像体积,特别是对于需编译语言而言,一个应用的构建过程往往如下

  1. 安装编译工具
  2. 安装第三方库依赖
  3. 编译构建应用

而在前两步会有大量的镜像体积冗余,使用多阶段构建可以避免这一问题

这是构建 Go 应用的一个示例

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 高效部署前端应用

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 服务,数据库与缓存。把他们解耦到多个容器中,方便横向扩展。如果你需要网络通信,则可以将他们至于一个网络下。

如在我的个人服务器中,我使用 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

dockerfile 最佳实践及示例的更多相关文章

  1. 【原创】Docker实战 Dockerfile最佳实践&&容器之间通信

    官方最佳实践文档 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#from Docker实战(三十) ...

  2. 《容器高手实战: Dockerfile最佳实践》

    Dockerfile最佳实践一个容器对应一个进程一个Docker容器应该只对应一个进程,也就是一个Docker 镜像一般只包含一个应用的制品包(比如.jar). 在需要组合多个进程的场景,使用容器组( ...

  3. Dockerfile 最佳实践

    之前 一篇文章介绍 docker 的镜像基本原理和概念 ,主要介绍在编写 docker 镜像的时候一些需要注意的事项和推荐的做法. 虽然 Dockerfile 简化了镜像构建的过程,并且把这个过程可以 ...

  4. go项目dockerfile最佳实践

    1. 前言 2. 不需要cgo情况下的最佳实践 3. 依赖cgo情况下的最佳实践 1. 前言 这几天在构建golang编写的web项目中,关于dockerfile编写的一些总结 可能是单纯我比较菜(大 ...

  5. Dockerfile最佳实践(一)

    1.使用缓存  Dockerfile的每条指令都会将结果提交为新的镜像,下一跳指令将会基于上一步指令的镜像的基础上构建,如果一个镜像存在相同的父镜像和指令(除了ADD),Docker将会使用镜像而不是 ...

  6. 编写 Dockerfile 最佳实践

    官方仓库虽然有数十万计的免费镜像,但大多数无法直接满足公司业务需求,这就需要我们自己去定制镜像了. Docker通过Dockerfile自动构建镜像,Dockerfile是一个包含用于组建镜像的文本文 ...

  7. 8、Dockerfile介绍和最佳实践

    一.Dockerfile 概念 1.Dockerfile是什么 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的一些配置参数(如 ...

  8. Dockerfile 命令详解及最佳实践

    Dockerfile 命令详解 FROM 指定基础镜像(必选) 所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制.就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指 ...

  9. 8.云原生之Docker容器镜像构建最佳实践浅析

    转载自:https://www.bilibili.com/read/cv15220861/?from=readlist 本章目录 0x02 Docker 镜像构建最佳实践浅析 1.Dockerfile ...

随机推荐

  1. Linux下mysql的主从复制配置

    1.准备两台数据库环境,或者单台多实例环境,能正常启动和登录. 数据库的安装和多实例配置请参考https://www.cnblogs.com/qiuhom-1874/p/9757061.html. 2 ...

  2. springboot~高并发下耗时操作的实现

    高并发下的耗时操作 高并发下,就是请求在一个时间点比较多时,很多写的请求打过来时,你的服务器承受很大的压力,当你的一个请求处理时间长时,这些请求将会把你的服务器线程耗尽,即你的主线程池里的线程将不会再 ...

  3. X-Admin&ABP框架开发-RBAC

    在业务系统需求规划过程中,通常对于诸如组织机构.用户和角色等这种基础功能,通常是将这部分功能规划到通用子域中,这也说明了,对于这部分功能来讲,是系统的基石,整个业务体系是建立于这部分基石之上的,当然, ...

  4. Linux常用命令复习

    1> 查看文件信息:ls ls是英文单词list的简写,其功能为列出目录的内容,是用户最常用的命令之一,它类似于DOS下的dir命令. Linux文件或者目录名称最长可以有265个字符,“.”代 ...

  5. PHP-PSR 现代PHPer的开发规范

    PSR是PHP Standards Recommendation的简称,意为PHP推荐标准.要想了解PSR,首先得知道制定这一标准的人/组织是谁————PHP-FIG. PHP-FIG PHP-FIG ...

  6. 通过 position:fixed 实现底部导航

    通过 position:fixed 实现底部导航 HTML <div id="footer">页脚</div> CSS #footer { clear: b ...

  7. nyoj 463-九九乘法表

    463-九九乘法表 内存限制:64MB 时间限制:1000ms 特判: No 通过数:16 提交数:41 难度:1 题目描述: 小时候学过的九九乘法表也许将会扎根于我们一生的记忆,现在让我们重温那些温 ...

  8. Docker从入门到实践(1)

    一.Docker简介 1.1.什么是 Docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多 ...

  9. 领扣(LeetCode)字符串相加 个人题解

    给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 注意: num1 和num2 的长度都小于 5100. num1 和num2 都只包含数字 0-9. num1 和num2 都不包 ...

  10. 虚拟机和容器docker

    云计算中最主要的技术就是虚拟机,开源虚拟机已经kvm已经集成到Linux内核!针对虚拟机浪费资源(CPU.内存.存储等)较大的缺陷,google力推Docker容器和容器管理平台Kubernetes. ...