dockerfile 最佳实践及示例
Dockerfile 最佳实践已经出现在官方文档中,地址在 Best practices for writing Dockerfiles。如果再写一份最佳实践,倒有点关公门前耍大刀之意。因此本篇文章是对官方文档的翻译,理解,扩展与示例补充
容器应该是短暂的
通过 Dockerfile 构建的镜像所启动的容器应该尽可能短暂 (ephemeral)。短暂意味着可以很快地启动并且终止
使用 .dockerignore 排除构建无关文件
.dockerignore 语法与 .gitignore 语法一致。使用它排除构建无关的文件及目录,如 node_modules
使用多阶段构建
多阶段构建可以有效减小镜像体积,特别是对于需编译语言而言,一个应用的构建过程往往如下
- 安装编译工具
- 安装第三方库依赖
- 编译构建应用
而在前两步会有大量的镜像体积冗余,使用多阶段构建可以避免这一问题
这是构建 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 跳过缓存
ADD和COPY将会计算文件的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 最佳实践及示例的更多相关文章
- 【原创】Docker实战 Dockerfile最佳实践&&容器之间通信
官方最佳实践文档 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#from Docker实战(三十) ...
- 《容器高手实战: Dockerfile最佳实践》
Dockerfile最佳实践一个容器对应一个进程一个Docker容器应该只对应一个进程,也就是一个Docker 镜像一般只包含一个应用的制品包(比如.jar). 在需要组合多个进程的场景,使用容器组( ...
- Dockerfile 最佳实践
之前 一篇文章介绍 docker 的镜像基本原理和概念 ,主要介绍在编写 docker 镜像的时候一些需要注意的事项和推荐的做法. 虽然 Dockerfile 简化了镜像构建的过程,并且把这个过程可以 ...
- go项目dockerfile最佳实践
1. 前言 2. 不需要cgo情况下的最佳实践 3. 依赖cgo情况下的最佳实践 1. 前言 这几天在构建golang编写的web项目中,关于dockerfile编写的一些总结 可能是单纯我比较菜(大 ...
- Dockerfile最佳实践(一)
1.使用缓存 Dockerfile的每条指令都会将结果提交为新的镜像,下一跳指令将会基于上一步指令的镜像的基础上构建,如果一个镜像存在相同的父镜像和指令(除了ADD),Docker将会使用镜像而不是 ...
- 编写 Dockerfile 最佳实践
官方仓库虽然有数十万计的免费镜像,但大多数无法直接满足公司业务需求,这就需要我们自己去定制镜像了. Docker通过Dockerfile自动构建镜像,Dockerfile是一个包含用于组建镜像的文本文 ...
- 8、Dockerfile介绍和最佳实践
一.Dockerfile 概念 1.Dockerfile是什么 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的一些配置参数(如 ...
- Dockerfile 命令详解及最佳实践
Dockerfile 命令详解 FROM 指定基础镜像(必选) 所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制.就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指 ...
- 8.云原生之Docker容器镜像构建最佳实践浅析
转载自:https://www.bilibili.com/read/cv15220861/?from=readlist 本章目录 0x02 Docker 镜像构建最佳实践浅析 1.Dockerfile ...
随机推荐
- tcpdump抓包工具
tcpdump抓包工具 一:TCPDump介绍 TcpDump可以将网络中传送的数据包的"头"完全截获下来提供分析.它支持针对网络层.协议.主机.网络或端口的过滤,并提供and ...
- 012.Kubernetes二进制部署worker节点Flannel
一 部署flannel 1.1 安装flannel kubernetes 要求集群内各节点(包括 master 节点)能通过 Pod 网段互联互通.flannel 使用 vxlan 技术为各节点创建一 ...
- Python基础之JSON
作用 对Python对象进行序列化,便于存储和传输 Python对象与JSON字符串相互转换 Python对象转JSON字符串 import json data = [ { 'a' : 1, 'b' ...
- 在开发框架中扩展微软企业库,支持使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库
在前面随笔<在代码生成工具Database2Sharp中使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库,实现免安装Oracle客户端,兼容3 ...
- PHP的global和$GLOBALS的区别
global是关键字,通常添加在变量前,可以使变量的作用域为全局. $GLOBALS预定义的超全局变量,把变量扔到里面一样可以变成全局变量. $GLOBALS 是一个关联数组,每一个变量为一个元素,键 ...
- 阿里云ECS服务器部署HADOOP集群(三):ZooKeeper 完全分布式集群搭建
本篇将在阿里云ECS服务器部署HADOOP集群(一):Hadoop完全分布式集群环境搭建的基础上搭建,多添加了一个 datanode 节点 . 1 节点环境介绍: 1.1 环境介绍: 服务器:三台阿里 ...
- 利用Python学习线性代数 -- 1.1 线性方程组
利用Python学习线性代数 -- 1.1 线性方程组 本节实现的主要功能函数,在源码文件linear_system中,后续章节将作为基本功能调用. 线性方程 线性方程组由一个或多个线性方程组成,如 ...
- 学习PHP框架只停留在会用层面,职业生涯肯定走不远!
工作这么多年,也面试过很多PHP工程师,我发现很多PHP工程师只停留在使用框架的层面,然而对框架底层根本没有深入去了解,那么这就会给自己的职业生涯带来一定的瓶颈,当遇到问题的时候你就无从下手,不知道如 ...
- 异步任务AsyncTask使用解析
在Android中实现异步任务机制有两种方式,Handler和AsyncTask. Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更 ...
- 20191010-4 alpha week 1/2 Scrum立会报告+燃尽图 02
此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/8747 一.小组情况 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩昊 刘信鹏 队名 ...