1.概述
优点:轻量、业务隔离、标准交付
chroot:改变某个进程的根目录,使得该程序不能访问目录之外的其他目录,和容器类似
Docker利用Namespace做主机名、网络、PID等资源的隔离,用Cgroups对进程或者进程组做资源(CPU、内存等)限制,联合文件系统用于镜像构建和容器运行环境
Namespace
功能:对内核资源进行隔离,容器中的进程可以在单独的命名空间中运行,并且只可以访问当前容器命名空间的资源
Docker主要用到5种:
- pid namespace:隔离进程id
- net namespace:隔离网络接口
- mnt namespace:文件系统挂载点隔离
- ipc namespace:信号量、消息队列、共享内存隔离
- uts namespace:主机名和域名隔离
Cgroups
限制容器CPU和内存等资源的使用
联合文件系统
UnionFS,通过创建文件层进程操作的文件系统,非常轻快,Docker使用其为容器提供构建层,使容器可以实现写时复制以及镜像的分层构建和存储
常用的联合文件系统有AUFS、Overlay、Devicemapper
2.核心概念
镜像
容器启动的先决条件
一个只读的文件和文件夹组合,包含容器运行时所需要的所有基础文件和配置信息
使用:
- 自己创建镜像
- 从镜像仓库拉取别人的镜像
容器
容器是镜像的运行实体,镜像是静态的只读文件,容器带有运行时需要的可写文件层,容器运行真正的应用进程
容器有初建、运行、停止、暂停、删除五种状态
容器有自己独立的命名空间隔离和资源限制
仓库
存储和分发Docker镜像
分为公共镜像仓库和私有镜像仓库
3.Docker架构
整体架构采用C/S模式,主要由客户端和服务端两部分组成,客户端负责发送操作指令,服务端负责接收和处理指令
客户端
docker命令、REST API、各种语言的SDK
服务端
所有后台服务的统称
dockerd:负责响应和处理来自客户端的请求,转换为具体操作
containerd:管理容器生命周期,启动并管理runC
runC:运行容器的轻量级工具
containerd-shim:将containered和真正的容器进程解耦,作为容器进程的父进程,containerd重启不影响已经启动的容器进程
4.镜像使用
- 拉取镜像:docker pull
- 查看镜像:docker images或者docker image ls
- 重命名镜像:docker tag
- 删除镜像:docker image rm或者docker rmi
- 构建镜像:docker commit或者docker build
Dockerfile 指令 | 指令简介 |
---|---|
FROM | Dockerfile 除了注释第一行必须是 FROM ,FROM 后面跟镜像名称,代表我们要基于哪个基础镜像构建我们的容器 |
RUN | RUN 后面跟一个具体的命令,类似于 Linux 命令行执行命令 |
ADD | 拷贝本机文件或者远程文件到镜像内 |
COPY | 拷贝本机文件到镜像内 |
USER | 指定容器启动的用户 |
ENTRYPOINT | 容器的启动命令 |
CMD | CMD 为 ENTRYPOINT 指令提供默认参数,也可以单独使用 CMD 指定容器启动参数 |
ENV | 指定容器运行时的环境变量,格式为 key=value |
ARG | 定义外部变量,构建镜像时可以使用 build-arg = 的格式传递参数用于构建 |
EXPOSE | 指定容器监听的端口,格式为 [port]/tcp 或者 [port]/udp |
WORKDIR | 为 Dockerfile 中跟在其后的所有 RUN、CMD、ENTRYPOINT、COPY 和 ADD 命令设置工作目录 |
镜像实现原理
镜像由一系列镜像层(layer)组成,每一层为镜像构建过程中的一次提交,当我们需要修改镜像中的某个文件时,只需要在当前镜像层的基础上新建一个镜像层,只存放修改过的文件内容
5.容器使用
容器定义
容器是基于镜像创建的可运行实例,运行容器时,实际上是在容器内部创建该文件系统的可读写副本,添加一个容器层
容器生命周期
- created:初建状态 docker create
- running:运行状态 docker start
- stopped:停止状态 docker stop
- paused: 暂停状态 docker pause/docker unpause
- deleted:删除状态 任何状态的容器都可以直接删除
容器操作
- 创建:docker create
- 启动:docker start或docker run -it(基于镜像新建一个容器并启动)(-t:分配一个伪终端 -i:将终端的STDIN打开)
- 停止:docker stop
- 进入容器:docker attach(所有终端会同步,一个阻塞会全部阻塞,一般不使用)、docker exec(推荐使用)、nsenter
- 删除容器:docker rm(删除停止状态)、docker rm -f(删除运行中的)
- 导出容器:docker export
- 导入容器:docker import
6.仓库
仓库用来存储和分发Docker镜像,注册服务器是存放仓库的实际服务器,可以包含多个仓库,每个仓库可以包含多个镜像
7.Dockerfile最佳实践
使用Dockerfile构建镜像的优点:
- 易于版本化管理,Dockerfile是一个文件,方便存放在代码仓库做版本管理
- 过程可追溯,Dockerfile每一行指令代表一个镜像层
- 屏蔽构建环境异构
书写原则
- 单一职责:每个容器负责单一业务进程
- 提供注释
- 保持容器最小化:避免安装无用软件
- 合理选择基础镜像
- 使用.dockerignore文件忽略不需要参与构建的文件
规则如下:
规则 | 含义 |
---|---|
# | # 开头的表示注释,# 后面所有内容将会被忽略 |
/tmp | 匹配当前目录下任何以 tmp 开头的文件或者文件夹 |
*.md | 匹配以 .md 为后缀的任意文件 |
tem? | 匹配以 tem 开头并且以任意字符结尾的文件,?代表任意一个字符 |
!README.md | ! 表示排除忽略。 例如 .dockerignore 定义如下: *.md !README.md 表示除了 README.md 文件外所有以 .md 结尾的文件 |
- 尽量使用构建缓存,把不轻易发生改变的指令放到Dockerfile前面,经常发生改变的指令放在Dockerfile末尾,增加缓存命中概率
- 正确设置时区
- 使用国内软件源加快构建速度
- 最小化镜像层数
书写建议
- RUN:RUN指令后面跟的内容比较复杂时,建议使用反斜杠() 结尾并且换行;RUN指令后面的内容尽量按照字母顺序排序,提高可读性
- CMD 和 ENTRYPOINT:Dockerfile 中如果使用了ENTRYPOINT指令,启动 Docker 容器时需要使用 --entrypoint 参数才能覆盖 Dockerfile 中的ENTRYPOINT指令 ,而使用CMD设置的命令则可以被docker run后面的参数直接覆盖;如果希望镜像足够灵活,推荐使用CMD指令。如果镜像只执行单一的具体程序,并且不希望用户在执行docker run时覆盖默认程序,建议使用ENTRYPOINT;无论使用CMD还是ENTRYPOINT,都尽量使用exec模式(即CMD/ENTRYPOINT["command" , "param"])
- ADD 和 COPY:COPY指令只支持基本的文件和文件夹拷贝功能,ADD则支持更多文件来源类型,并且可以支持源文件为 URL 格式;推荐使用COPY指令,因为COPY指令更加透明,仅支持本地文件向容器拷贝,而且使用COPY指令可以更好地利用构建缓存,有效减小镜像体积
- WORKDIR:推荐使用 WORKDIR 来指定容器的工作路径,应该尽量避免使用 RUN cd /work/path && do some work 这样的指令