docker — 容器镜像
Linux 操作系统由内核空间和用户空间构成①:Linux系统内核(/boot/vmlinuz-*)②(根文件系统): Linux系统中的用户空间文件系统。rootfs 是一个操作系统所包含的文件、配置和目录,但并不包括操作系统kernel。
目录
1. 运行一个centos 容器中运行 /sbin/init
2. 使用docker commit 命令将该容器保存为镜像“test1”
5. 使用docker history 命令查看镜像构建历史
1. 编辑一个dockerfile 文件,存放于/root/df 目录下
2. 使用docker build 命令用文件 dockerfile 构建一个镜像,并将镜像命名为 tests
一、容器镜像结构
1、Linux 操作系统结构
Linux 操作系统由内核空间和用户空间构成
① kernel:Linux系统内核(/boot/vmlinuz-*)
② rootfs(根文件系统): Linux系统中的用户空间文件系统。
rootfs 是一个操作系统所包含的文件、配置和目录,但并不包括操作系统kernel
2、容器镜像
1. 容器镜像是容器的模板,容器时镜像的运行实例,runtime根据容器镜像创建容器
2. 容器镜像挂载在容器根目录下,是为容器中的应用提供隔离后执行环境的文件系统
① 容器镜像打包了整个操作系统的文件和目录(rootfs),当然也包括应用本身。即, 应用及其运行所需的所有依赖,都在被封装在容器镜像中。
保证了本地环境和云端环境的高度一致
3. 容器镜像采用分层结构:
① 所有容器共享宿主机Kernel,并且不能修改宿主机Kernel。即,容器运行过程中使用 容器镜像里的文件,使用宿主机OS上的Kernel
3、base 镜像
1. scratch 空镜像
① 从 scratch 构建,不依赖其它镜像
- scratch 本身是个空镜像
② 其他镜像可在base 镜像上进行扩展,创建新的镜像
2. 最常用的 base 镜像是各 Linux 发行版的 Docker镜像,如 ubuntu、centos等
4、容器镜像的分层结构
1. Docker 镜像中引入层 layer 的概念。镜像制作过程中的每一步操作,都会生成一个新的镜像层
2. 容器由若干只读镜像层和最上面的一个可写容器层构成
① 分层结构使镜像共享、容器创建、分发非常高效
3. 使用 docker image inspect ubuntu 命令查看 ubuntu 镜像分层结构,回显如下
5、UnionFS 联合文件系统
1. UnionFS 主要功能是将多个不同位置的目录联合挂载(union mount)到同一个目录下
① 每一个镜像层都是Linux 操作系统文件与目录的一部分。在使用镜像时,docker 会 将所有的镜像层联合挂载到一个统一的挂载点上,表现为一个完整的Linux 操作系统 供容器使用
# docker images #查看本地镜像 # docker history alpine:latest #查看镜像制作历史 # docker pull ubuntu #从镜像仓库拉取镜像 ubuntu # docker image inspect ubuntu:latest #查看镜像相关信息 # docker run -itd ubuntu #使用镜像运行容器 # docker ps #查看运行中的容器 # docker exec -it dreamy_carson ls / #查看容器根目录
6、容器 copy-on-write(写时复制) 特性
1. 对容器的增、删、改、查操作:
操作 具体执行 创建文件 新文件只能被添加在容器层中 删除文件 依据容器分层结构由上往下依次查找。找到后,在容器层中记录该删除操作
具体实现是,UnionFS会在容器层创建一个"whiteout 文件",
将被删除的文件"遮挡"起来
修改文件 依据容器分层结构由上往下依次查找。
找到后,将镜像层中的数据复制到容器层进行修改,
修改后的数据保存在容器层中。
(copy-on-write)
读取文件 依据容器分层结构由上往下依次查找
二、构建容器镜像
1、构建容器的两种方法
2、docker commit 构建镜像
1. docker commit 命令:可将一个运行中的容器保存为镜像。其运行过程可总结如下:
① 运行一个容器
② 修改容器内容
③ 将容器保存为镜像
1.docker命令补全
docker命令提供了bash-complete的脚本,在执行该命令时,敲tab可以自动补全参数
/usr/share/bash-completion/completions/docker
# apt-get install bash-completion # source /usr/share/bash-completion/completions/docker #执行后出现如下问题 # docker pbash: _get_comp_words_by_ref: command not found bash: [: : integer expression expected bash: [: : integer expression expected bash: [: : integer expression expected q^C '/usr/share/bash-completion/bash_completion 该文件中有上面缺少的命令' # source /usr/share/bash-completion/bash_completion #此时就可正常进行docker子命令的补全
3、docker commit 示例
1. 运行一个centos 容器中运行 /sbin/init
# docker run -itd --privileged centos /sbin/init #centos不加--privileged没有权限修改 # docker ps #查看状态容器已经运行 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 736eae62b647 centos "/sbin/init" 45 seconds ago Up 44 seconds inspiring_boyd # docker exec -it 736e /bin/bash #进入容器 [root@736eae62b647 /]# yum -y install httpd #安装web服务 Failed to set locale, defaulting to C.UTF-8 CentOS Linux 8 - AppStream 73 B/s | 38 B 00:00 Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist '提示仓库源有问题' [root@736eae62b647 /]# rm -rf /etc/yum.repos.d/CentOS-Linux-* [root@736eae62b647 /]# cat /etc/redhat-release #查看当前版本 CentOS Linux release 8.4.2105 [root@736eae62b647 /]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo #可以去阿里上查找对应版本https://developer.aliyun.com/mirror/ [root@736eae62b647 /]# yum repolist #查看仓库是否架子啊 Failed to set locale, defaulting to C.UTF-8 repo id repo name AppStream CentOS-8.5.2111 - AppStream - mirrors.aliyun.com base CentOS-8.5.2111 - Base - mirrors.aliyun.com extras CentOS-8.5.2111 - Extras - mirrors.aliyun.com [root@736eae62b647 /]# yum -y install httpd #再次安装即可 [root@736eae62b647 /]# echo "hello world" > /var/www/html/index.html [root@736eae62b647 /]# systemctl enable --now httpd [root@736eae62b647 /]# curl localhost #web服务正常开启 hello world [root@736eae62b647 /]# exit #退出容器 # docker ps #查看运行的容器状态 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 736eae62b647 centos "/sbin/init" 27 minutes ago Up 27 minutes inspiring_boyd
2. 使用docker commit 命令将该容器保存为镜像“test1”
# docker commit inspiring_boyd test1 #将运行的容器做成镜像 sha256:18828b81510de014ea66b1ad3b505ba774fbc74ad2b25aa9168c584efced6924
3. 使用docker images 查看新的镜像
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE test1 latest 18828b81510d 41 seconds ago 280MB
4. 以test1 镜像运行一个容器
# docker run -itd --privileged test1 /sbin/init # docker exec -it interesting_vaughan /bin/bash #进入容器 [root@09bf75ca5019 /]# curl localhost #测试服务正常 hello world
5. 使用docker history 命令查看镜像构建历史
对比镜像test1与centos,test1 比 centos 多了一个镜像层
3. Dockerfile
1. 文件指令集,描述如何自动创建 Docker 镜像
① 是包含若干指令的文本文件,可以通过这些指令创建出 docker image
② 文件中的指令执行后,会创建一个个新的镜像层
③ 文件中的注释以 “#” 开始
④ 一般由 4 部分组成
2. build context: 为镜像构建提供所需的文件或目录
4、dockerfile 常用指令
指令 作用 命令格式 FROM 指定base镜像 FROM <image>:<tag> MAINTAINER 注明镜像的作者 MAINTAINER <name> RUN 运行指定的命令 RUN <command> ADD 将文件从build context 复制到镜像中 ADD [--chown=<user>:<group>]<src>...<dest> COPY 将文件从build context复制到镜像中 COPY [--chown=<user>:<group>]<src>...<dest> ENV 设置环境变量 ENV <key><value> EXPOSE 指定容器中的应用监听的端口 EXPOSE <port> [<port>/<protocol>...] USER 设置启动容器的用户 USER <user>[:<group>] CMD 设置在容器启动时运行指定的脚本或命令 CMD command param1 param2 ENTRYPOINT 指定的是一个可执行的脚本或者程序的路径 ENTRYPOINT command param1 param2 VOLUME 将文件或目录声明为volume,挂载到容器中 VOLUME ["/data"] WORKDIR 设置镜像的当前工作目录 WORKDIR /path/to/workdir
参考资料: Dockerfile reference | Docker Documentation
5、Dockerfile 示例
1. 编辑一个dockerfile 文件,存放于/root/df 目录下
~# mkdir df ~# cd /root/df ~/df# echo haha > index.html ~/df# vim vim dockerfile FROM httpd #指定镜像 COPY index.html / #将文件拷贝到镜像的根目录下 RUN echo haha #运行一条命令
2. 使用docker build 命令用文件 dockerfile 构建一个镜像,并将镜像命名为 tests
~/df# docker build -t tests . #-t指定镜像名 .为在当前目录中寻找dockerfile文件 Sending build context to Docker daemon 3.072kB Step 1/3 : FROM httpd ---> a981c8992512 Step 2/3 : COPY index.html / ---> 9f026a199a7d Step 3/3 : RUN echo haha ---> Running in 553668509bac haha Removing intermediate container 553668509bac ---> 3a9e4e5ee1bf Successfully built 3a9e4e5ee1bf Successfully tagged tests:latest
6、容器镜像缓存特性
1. Docker 会缓存已有镜像的镜像层,构建或下载镜像时,如果某镜像层已存在,则直接使用无须重新创建或下载
2. 编译 dockerfile 文件,增加在末尾声明作者的指令
~/df# vim dockerfile FROM httpd COPY index.html / RUN echo haha MAINTAINER *_花非人陌_* #增加作者信息
3. 重新执行 docker build 构建镜像,新镜像命名为 tests2
~/df# docker build -t tests2 . #重新建立镜像 Sending build context to Docker daemon 3.072kB Step 1/4 : FROM httpd ---> a981c8992512 Step 2/4 : COPY index.html / ---> 'Using cache' #使用了缓存 ---> 9f026a199a7d Step 3/4 : RUN echo haha ---> Using cache ---> 3a9e4e5ee1bf Step 4/4 : MAINTAINER *_花非人陌_* ---> Running in 4f9ac93f1eb8 Removing intermediate container 4f9ac93f1eb8 ---> 0bc362ff7331 Successfully built 0bc362ff7331 Successfully tagged tests2:latest
4. 若交换dockerfile 文件中命令执行顺序,虽然在逻辑上这种改动对镜像的内容没有影响,但由于分层的结构特性,Docker 必须重建受影响的镜像层
~/df# vim dockerfile FROM httpd MAINTAINER *_花非人陌_* COPY index.html / RUN echo haha
5. 重新构建镜像test3,每一步均生成新的镜像层,未使用到 cache
~/df# docker build -t tests2 . Sending build context to Docker daemon 3.072kB Step 1/4 : FROM httpd ---> a981c8992512 Step 2/4 : MAINTAINER *_花非人陌_* ---> Running in 2ab77293ccd7 Removing intermediate container 2ab77293ccd7 ---> f1822a01898b Step 3/4 : COPY index.html / ---> 3e7d474f3185 Step 4/4 : RUN echo haha ---> Running in 9dacd7052d95 haha Removing intermediate container 9dacd7052d95 ---> 456098bfd852 Successfully built 456098bfd852 Successfully tagged tests2:latest
7、镜像命名
镜像名称格式
① image name = repository:tag
② tag 一般用于描述镜像版本。若未指定tag,则默认为“latest”
8、Registry
1. Registry 是存放容器镜像的仓库,用户可进行镜像下载和访问,分为公有和私有两类
2. 公有镜像仓库
① Docker Hub 是 Docker 公司为公众提供的托管 Registry Docker Hub
② Quay.io 现为 Red Hat 下的公共托管 Registry Quay
③ https://www.aliyun.com
④ catalog.redhat.com
3. 私有仓库
① 企业可以用 Docker Registry 构建私有的 Registry
- Registry 本身是一个开源项目,可以用于搭建私有 Registry
② Harbor,企业免费
③ quay,收费
9、Docker Hub
1. Docker Hub 是目前世界上最大的容器镜像仓库,由Docker公司维护。
上面有Docker公司提供的镜像,及大量用户上传的镜像
10、搭建私有Registry 示例
1. 使用“registry” 镜像构建本地镜像仓库。registry 是 docker hub 上维护的镜像,其服务端 口是5000。 -v 参数将宿主机的/root/myregistry 目录映射到容器的 /var/lib/registry目录,用于存放镜像数据
root@k8s-master:~# mkdir /root/myregistry root@k8s-master:~# docker pull registry #下载registry镜像 ~# docker inspect registry | grep -A 1 Volume #查看容器数据挂载点 "Volumes": { "/var/lib/registry": {} -- "Volumes": { "/var/lib/registry": {} root@k8s-master:~# docker run -d -p 1000:5000 -v /root/myregistry:/var/lib/registry registry #运行容器 # docker ps #查看容器是否运行 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 45fa5baba5e8 registry "/entrypoint.sh /etc…" About a minute ago Up About a minute 0.0.0.0:1000->5000/tcp, :::1000->5000/tcp epic_heyrovsky
2. 使用docker tag 命令修改镜像名称,使其符合registry上的格式要求。
若要将镜像上传到registry,镜像名称需要符合其命名格式要求:
[Registry-host]:[port]/[username]/[repository:tag]
root@k8s-master:~# docker images #查看镜像 REPOSITORY TAG IMAGE ID CREATED SIZE tests2 latest 456098bfd852 2 hours ago 145MB root@k8s-master:~# docker tag tests2:latest 192.168.5.100:1000/tests2:tests2
3. 上传容器镜像到私有 Registry
# docker push 192.168.5.100:1000/tests2:tests2 #默认无法推送成功 The push refers to repository [192.168.5.100:1000/tests2] Get "https://192.168.5.100:1000/v2/": http: server gave HTTP response to HTTPS client '默认无法推送,因为当前为https'
4. 在Linux下,若使用如“192.168.73.137:1000” 这样的内网地址作为私有仓库地址,则需要 在/etc/docker/daemon.json 中写入如下内容(如果文件不存在需新建该文件),
然后重启Docker服务
root@k8s-master:~# vim /etc/docker/daemon.json #编辑docker配置文件 }, "registry-mirrors": ["https://docker.nju.edu.cn/"], "insecure-registries": ["192.168.5.100:1000"] #意思是不用证书服务地址和端口 } root@k8s-master:~# systemctl daemon-reload #重新加载配置 root@k8s-master:~# systemctl restart docker #重启docker服务 root@k8s-master:~# docker start epic_heyrovsky #启动容器 # ss -tunlp | grep 1000 #查看端口是否被监听,确保可以正常服务 tcp LISTEN 0 4096 0.0.0.0:1000 0.0.0.0:* users:(("docker-proxy",pid=1448928,fd=4)) tcp LISTEN 0 4096 [::]:1000 [::]:* users:(("docker-proxy",pid=1448934,fd=4)) '再次push成功,192.168.5.100:1000就是仓库地址' root@k8s-master:~# docker push 192.168.5.100:1000/tests2:tests2 #上传镜像 The push refers to repository [192.168.5.100:1000/tests2] 462d767129cf: Pushed 01597d537f57: Pushed c7c38e3c39ad: Pushed c672c6903747: Pushed 34e2a1369fc5: Pushed 6485bed63627: Pushed tests2: digest: sha256:6fad1afe9b257abc84994bb30ab12d3b63b44cbd6518c6a8b16a89507387daa0 size: 1573 # curl 192.168.5.100:1000/v2/_catalog #访问后镜像已正常上传 {"repositories":["test2"]} # curl http://192.168.147.102:1000/v2/test2/tags/list #查看镜像标签 # docker-registry-cli
将镜像分成了多层,放置在了不同目录当中
root@k8s-master:~# tree /root/myregistry/ /root/myregistry/ └── docker └── registry └── v2 ├── blobs │ └── sha256 │ ├── 15 │ │ └── 152876b0d24a5561415915c652dceeb3bcd5080dc24c3994e77343a81f64b9f1 │ │ └── data │ ├── 45 │ │ └── 456098bfd852c3b85b0e7756273f8bbc085660225389066c6e9d7e0171ef8928 │ │ └── data │ ├── 6b │ │ └── 6b29c2b62286e254216da297b4066a4bb79b918bc02811ba954bd7b8fd51360b │ │ └── data │ ├── 6c │ │ └── 6cc0f1e2dfdc6eb221cb7ad6e25e84544f19c87767e429a7ea683dfa5cbb257b │ │ └── data │ ├── 6f │ │ └── 6fad1afe9b257abc84994bb30ab12d3b63b44cbd6518c6a8b16a89507387daa0 │ │ └── data │ ├── 7a │ │ └── 7a6db449b51b92eac5c81cdbd82917785343f1664b2be57b22337b0a40c5b29d │ │ └── data │ ├── b4 │ │ └── b4effd428409f1da4dc8c896afb9818ef1ba24be5e7e5e3d86dea650ac3ed8bc │ │ └── data │ └── c2 │ └── c2123effa3fcb96c62bf4d891147aef09029d429321bfb4c6a535fa3ca7e13d6 │ └── data └── repositories └── tests2 ├── _layers │ └── sha256 │ ├── 152876b0d24a5561415915c652dceeb3bcd5080dc24c3994e77343a81f64b9f1 │ │ └── link │ ├── 456098bfd852c3b85b0e7756273f8bbc085660225389066c6e9d7e0171ef8928 │ │ └── link │ ├── 6b29c2b62286e254216da297b4066a4bb79b918bc02811ba954bd7b8fd51360b │ │ └── link │ ├── 6cc0f1e2dfdc6eb221cb7ad6e25e84544f19c87767e429a7ea683dfa5cbb257b │ │ └── link │ ├── 7a6db449b51b92eac5c81cdbd82917785343f1664b2be57b22337b0a40c5b29d │ │ └── link │ ├── b4effd428409f1da4dc8c896afb9818ef1ba24be5e7e5e3d86dea650ac3ed8bc │ │ └── link │ └── c2123effa3fcb96c62bf4d891147aef09029d429321bfb4c6a535fa3ca7e13d6 │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 6fad1afe9b257abc84994bb30ab12d3b63b44cbd6518c6a8b16a89507387daa0 │ │ └── link │ └── tags │ └── tests2 │ ├── current │ │ └── link │ └── index │ └── sha256 │ └── 6fad1afe9b257abc84994bb30ab12d3b63b44cbd6518c6a8b16a89507387daa0 │ └── link └── _uploads
11、搭建Harbor
1. 下载harbor
更多推荐
所有评论(0)