Docker 镜像结构
Docker 镜像结构
一、镜像与容器之间的关系
- 镜像:是静态的、只读的文件系统,包含运行容器所需的程序、库、资源、配置等
- 容器:是镜像的运行实例,是动态的进程,拥有自己的文件系统、网络、进程空间等资源
- 关系:
- 镜像是容器的基础,容器依赖于镜像。
- 容器启动时,会在镜像之上添加一个可写的“容器层”,所有修改都发生在这一层。
- 镜像通过
json
文件描述运行时的配置(如启动命令、环境变量等),Docker 守护进程解析该文件并启动容器
二、镜像结构
1、基础镜像(base 镜像)
- 不依赖于其他镜像,从
scratch
开始构建 - 以此为基础镜像,进行扩展
- 通常是各种 Linux 发行版(如 CentOS、Ubuntu)的镜像
- 不同发行版的区别在于
rootfs
(用户空间),而内核共享宿主机的 Kernel
2、镜像分层
-
镜像由多个只读层组成,每层代表一个修改(如安装软件、添加文件)
-
层次结构示例
| touch /galaxy/cy | Image |
| mkdir /galaxy | Image |
| CentOS:7 | Base Image |
| Docker Host | Kernel |
3、容器层
- 容器启动时,在镜像顶部添加一个可写层
- 用户看到的是联合文件系统,上层文件覆盖下层同名文件
- 容器层的写入操作使用写时复制机制
三、Docker 镜像构建
1、三种构建方式对比
方式 | 说明 | 优点 | 缺点 |
---|---|---|---|
docker commit | 基于运行中的容器创建镜像 | 简单快捷 | 容易出错,效率低且可重复性弱,不安全 |
基于本地模板导入 | 从模板文件导入镜像 | 快速导入已有系统 | 不灵活、不易定制 |
dockerfile | 通过脚本定义镜像层次 | 透明、可重复、易于维护 | 推荐方式 |
2、docker commit
通过在运行的容器内安装软件、配置环境,再将容器的“当前状态”打包为新镜像,本质是“快照式构建”
在
centos:7
中安装vim-common
先基于centos7运行容器,容器名为cy,并使用-it生成终端进入容器
[root@docker ~]# docker run --name dc -it centos:7 /bin/bash
在容器中安装vim-common
[root@8f3a60b20edb /]# yum -y install vim-common
退出容器后,使用docker commit将v1容器打包为镜像
[root@docker ~]# docker commit dc centosdc:7
[root@docker ~]# docker images | grep centosdc
3、基于本地模板导入
直接从操作系统模板文件(如OpenVZ模板)导入镜像,模板文件通常为压缩包(如
tar.gz
),包含完整的rootfs
和基础配置
导入
ubuntu:12.04
模板
下载模板
从OpenVZ官方地址(http://openvz.org/Download/templates/precreated)下载ubuntu-12.04-x86-minimal.tar.gz
导入为镜像
[root@docker ~]# cat ubuntu-12.04-x86-minimal.tar.gz | docker import - ubuntu:12.04
验证镜像
[root@docker ~]# docker images
4、Dockerfile构建
Dockerfile是一个文本文件,包含一系列“指令(Instruction)”,每一条指令对应镜像的一层——指令描述了该层的构建操作(如安装软件、复制文件、配置环境)。通过docker build命令执行Dockerfile,可自动化、可重复地构建镜像,解决了docker commit的“不透明、不可追溯”问题
编写 Dockerfile
[root@docker ~]# vim Dockerfile
Dockerfile 内容
# 第一行必须指定,基础镜像信息
FROM centos:7
# 维护者信息
MAINTAINER docker@example.com
# 镜像操作指令
RUN yum install -y httpd
EXPOSE 80
# 容器启动执行指令
CMD ["/usr/sbin/httpd"]
执行构建命令
[root@docker ~]# docker build -t httpd:wil /root/
构建过程:
- 下载centos7镜像
- 添加镜像构建者信息
- 基于centos7镜像启动容器,安装httpd软件,安装完毕后将容器打包为镜像
- 基于上一步生成的镜像启动容器,将80端口打开,打开后将容器打包为镜像
- 基于上一步生成的镜像启动容器,添加容器启动后需要执行的指令,再打包为镜像
查看构建历史
[root@docker ~]# docker history httpd:wil
使用DockerFile文件构建完镜像以后,Docker会把构建过程中的每一层临时镜像进行缓存。在构建新镜像时,可以直接使用之前缓存的镜像层,这样能加速镜像的构建
四、Dockerfile 语法详解
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 | FROM centos:7 |
MAINTAINER | 维护者信息(已逐渐被 LABEL 替代) | MAINTAINER cy@example.com |
LABEL | 元数据键值对 | LABEL version="1.0" |
RUN | 构建过程中执行命令 | RUN yum install -y httpd |
COPY | 复制宿主机文件到镜像 | COPY app.py /app/ |
ADD | 类似 COPY ,支持 URL 和自动解压 | ADD app.tar.gz /app/ |
WORKDIR | 设置工作目录 | WORKDIR /app |
VOLUME | 创建挂载点 | VOLUME /data |
EXPOSE | 声明容器端口 | EXPOSE 80 |
ENV | 设置环境变量 | ENV APP_HOME /app |
CMD | 容器启动命令(可被覆盖) | CMD ["/bin/bash"] |
ENTRYPOINT | 容器启动命令(不可被覆盖) | ENTRYPOINT ["/app/start.sh"] |
USER | 指定运行用户 | USER nobody |
五、总结
要点 | 说明 |
---|---|
镜像与容器 | 镜像是静态的模板,容器是运行实例 |
分层结构 | 镜像由多个只读层组成,容器层可写 |
基础镜像 | 从 scratch 构建,提供 rootfs |
构建方式 | 推荐使用 Dockerfile,透明、可重复 |
Dockerfile 指令 | 每条指令对应一层,支持缓存 |
缓存机制 | 加速构建,可通过 --no-cache 禁用 |