基于 Dockerfile 的镜像生成
-
Dockerfile
- 镜像的描述文件,定义了如何基于
base镜像逐层构建出Docker镜像
- 镜像的描述文件,定义了如何基于
-
base镜像
- 不依赖其他镜像,从scratch构建
- 以CentOS镜像为例,仅有三行
FROM scratch ADD centos-7-docker.tar.xz / CMD ["/bin/bash"]- 会添加tar包,并自动解压到
/根目录下,生成/dev,/proc,/bin等目录
- 会添加tar包,并自动解压到
- 以CentOS镜像为例,仅有三行
- 大小只有 几十 或 几百MB
- 为什么这么小?
- 因为打包的只是rootfs,底层直接用Host宿主机的kernel
- 不依赖其他镜像,从scratch构建
-
镜像的生成原理——
逐层构建- 基于base镜像,用一条条命令构造出一个个镜像层,往上堆叠
- 可通过 history指令 查看已有镜像的堆叠层次
docker history <image_id>或镜像名
- 可通过 history指令 查看已有镜像的堆叠层次
- 好处
- 具备缓存特性,可共享资源
- 多个镜像中,由底层到中间某层若内容相同,则硬盘可以只保存一份,直接利用
- 实现机制
- 根据每一层堆上去后的已知所有层的sha值去做记录和比较
- 比如base镜像就可以只存一份
- 但如果中间多了一层不一样,就算上面全部一样,此特性也会失效
- 因为sha值的机制,多了的一层,导致后面计算出的所有层sha值都都是全新的
- 实现机制
- 可以加上
--no-cache禁用此特性
- 多个镜像中,由底层到中间某层若内容相同,则硬盘可以只保存一份,直接利用
- 具备缓存特性,可共享资源
- 注意
镜像层不允许被修改- 镜像启动生成容器后,所有修改都只会发生在更上层的
容器层中 - 两种层次,联合在一起组成统一的文件系统,访问时会从最上层的容器层开始向下找,以最先找到的为准
- 基于base镜像,用一条条命令构造出一个个镜像层,往上堆叠
-
镜像的生成方法——两种
- 【不建议】
docker commit- 步骤+例子
- 1.根据 base镜像 运行容器
docker run -it ubuntu - 2.进入容器内,做修改操作(比如安装软件,添加文件)
apt-get install -y vim - 3.将容器保存为新的镜像
docker commit <container_id>或容器名 新镜像名
- 1.根据 base镜像 运行容器
- 步骤+例子
- 【推荐】
Dockerfile- 步骤+例子
- 1.编写 Dockerfile文件,记录镜像构建要做的修改操作
# 文件内容 FROM ubuntu RUN apt-get install -y vim - 2.用 build命令 执行文件
docker build -t 新镜像名 .- 会出现一系列step,中途会生成临时容器,在里面执行,等待直到出现successfully即可
- 参数
-t指定新镜像的名字.指定 build context 为宿主机的工作目录- 会在这里面搜寻Dockerfile文件
- 指令中的 src相对路径 会根据这个目录 组合扩展成 绝对路径
- 注意
- 这里会把 build context 内的所有文件和子目录,全部发送到 docker 进行处理,所以要确保这个目录的纯净,否则构建会缓慢
- 也可以用
-f指定文件在 build context 下相对的真实位置- 好处
- 允许 Dockerfile 在任意子目录内,且为任意名字
- 好处
- 1.编写 Dockerfile文件,记录镜像构建要做的修改操作
- 步骤+例子
- 【不建议】
-
文件中常用的指令
-
基本
-
FROM- 指定base镜像
-
WORKDIR- 指定后面指令在
容器内的工作目录- 指令中的 dest相对路径 会根据这个目录 组合扩展成 绝对路径
- 好处
- 避免了
RUN cd … && do-something的难看写法 - 【注意!!!】 这里如果分两行写,RUN cd … 和 RUN do-something,是达不到想要的目的的!!,cd在这里会失效,因为两个RUN代表两层,第一层的cd改变,不会被继承到第二层,每一层都会从WORKDIR重新开始!!!
- 避免了
- 指定后面指令在
-
ENV- 设置环境变量,可以被紧跟其后的命令使用
ENV MY_VERSION RUN apt-get install -y mypackage=$MY_VERSION
- 设置环境变量,可以被紧跟其后的命令使用
-
-
文件操作
-
COPY- 将文件从 build context 复制到镜像
- 下面的 src 只能指定 build context 中的文件和目录
- 两种书写方式
- Shell格式
COPY src dest - Exec格式
COPY ["src", "dest"]
- Shell格式
- 将文件从 build context 复制到镜像
-
ADD- 也是将文件从 build context 复制到镜像
- 区别在于,如果 src 是归档文件(tar、zip等),会被自动解压到 dest
-
-
指令运行
RUN- 指定
构建时在容器中要运行的命令 - 常用于安装软件
- 指定
CMD- 指定
等容器启动时运行的命令 - 可以有多个CMD,但只有最后一个生效
- 可以被docker run命令后的参数替换掉
- 指定
ENTRYPOINT- 也是指定
等容器启动时运行的命令 - 也是可以有多个CMD,但只有最后一个生效
- 这里同样也有Shell和Exec格式的区别
- 例子1
- 例子1
- 也是指定
-
-
文件中不常用的指令
EXPOSE- 指定容器中的进程会监听的端口
EXPOSE 3000- 可以顺便学习
ARG,指定构建过程的参数(它与ENV有区别,因为不会出现在容器运行时)ARG port=3000 EXPOSE $port
- 可以顺便学习
- 指定容器中的进程会监听的端口