Docker镜像

什么是镜像

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称为UnionFS。

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M?

这是因为对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

分层的镜像

以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[dw@dk ~]$ sudo docker pull tomcat
Using default tag: latest

latest: Pulling from library/tomcat
d960726af2be: Pull complete
e8d62473a22d: Pull complete
8962bc0fad55: Pull complete
65d943ee54c1: Pull complete
da20b77f10ac: Pull complete
8669a096f083: Pull complete
e0c0a5e9ce88: Pull complete
f7f46169d747: Pull complete
42d8171e56e6: Pull complete
774078a3f8bb: Pull complete
Digest: sha256:71703331e3e7f8581f2a8206a612dbeedfbc7bb8caeee972eadca1cc4a72e6b1
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest

[dw@dk ~]$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat latest c43a65faae57 2 weeks ago 667MB
hello-world latest d1165f221234 2 months ago 13.3kB

为什么 Docker 镜像要采用这种分层结构呢?

最大的一个好处就是 - 共享资源

比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

镜像的特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

Docker镜像commit操作补充

Docker Commit

docker commit提交容器副本使之成为一个新的镜像。

Docker commit -m="提交的容器描述信息" -a="作者信息" 容器ID 要创建的目标镜像名:[标签名]

案例演示

去容器仓库拉取tomcat镜像,并检查运行,之后删除tomcat的根目录下的DOCS文件夹,commit后访问验证。

1.运行镜像

1
2
# 由于tomcat是位于容器内的,且tomcat默认端口是8080,所以首先得找到docker的对外暴露端口,之后再进入镜像找到tomcat对外暴露的端口才可以进入tomcat的web界面
[dw@dk ~]$ sudo docker run -it -p 8888:8080 tomcat

可能存在tomcat访问不到,详情看下述解释:

  1. 运行docker的tomcat镜像报错docker:IPv4 forwarding is disabled. Networking will not work.

原因:docker:IPv4 forwarding is disabled. Networking will not work.。

解决方法:

网络行不通,是因为IPv4转发被禁用了,只需要开启就可以了。

开启转发配置:

vim /etc/sysctl.conf

配置转发
net.ipv4.ip_forward=1
保存退出就可以了
:wq!
重启服务,让配置生效
systemctl restart network

查看是否成功,如果返回为“net.ipv4.ip_forward = 1”则表示成功

sysctl net.ipv4.ip_forward

然后看一下是否配置成功,看到这句话就是配置成功了。

重启docker
sudo systemctl start docker
查看运行过的容器
sudo docker ps -a
开启mysql容器开机启动
sudo docker update mysql —restart=always

没有异常就是成功了。

参考链接:https://blog.csdn.net/qq_42355392/article/details/110626807

  1. Docker中启动Tomcat后访问报错:”HTTP状态 404 - 未找到”
1
2
#启动tomcat容器
[root@aaa ~]# docker run -it -p 8888:8080 tomcat

访问宿主机端口8888,报错404:

这里是因为新版本的tomcat的webapps文件下并没有放置相应的文件,需要将文件移动出来。

解决方法:

  1. 退出容器
1
2
#不停止退出容器
CTRL+P+Q
  1. 进入容器
1
2
# 查看tomcat容器id
[root@aaa ~]# docker ps

1
2
# 进入容器命令行终端
[root@aaa ~]# docker exec -it ff197cf9b09d /bin/bash

可以看到原本应该放在webapps供外部访问的文件被放在了webapps.dist文件里,需要将它们移动到webapps里。

到此,可能会碰到的问题案例分析完成,如果有其他情况,请自行stackoverflow。

2.访问应用web页面

访问虚拟机docker暴露的端口8888,然后可以访问到tomcat的web页面。

3.删除web应用里的docs文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[dw@dk ~]$ sudo docker exec -it 2a966607e3c3 /bin/bash
root@2a966607e3c3:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps-back
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work

root@2a966607e3c3:/usr/local/tomcat# cd webapps

root@2a966607e3c3:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager

root@2a966607e3c3:/usr/local/tomcat/webapps# rm -rf docs

root@2a966607e3c3:/usr/local/tomcat/webapps# ls
ROOT examples host-manager manager

root@2a966607e3c3:/usr/local/tomcat/webapps#

删除docs文档后,访问tomcat的documentation将无法访问:

4.使用commit命令创建新的tomcat镜像(访问不了docs)

1
2
3
4
5
6
7
8
9
10
[dw@dk ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a966607e3c3 tomcat "catalina.sh run" 17 hours ago Up 17 hours 0.0.0.0:8888->8080/tcp, :::8888->8080/tcp compassionate_leakey
[dw@dk ~]$ sudo docker commit -a="hj" -m="tomcat without docs" 2a966607e3c3 atguigu/mytomcat:1.2
sha256:3195c86b506685864b393d2d3490c98250354ba0d8fbe8af55fe794d0024b020
[dw@dk ~]$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
atguigu/mytomcat 1.2 3195c86b5066 7 seconds ago 669MB
tomcat latest c43a65faae57 3 weeks ago 667MB
centos latest 300e315adb2f 6 months ago 209MB

5.检验commit

删除正在运行的docker容器:

1
2
3
4
5
6
7
8
9
10
[dw@dk ~]$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
atguigu/mytomcat 1.2 3195c86b5066 3 minutes ago 669MB
tomcat latest c43a65faae57 3 weeks ago 667MB
centos latest 300e315adb2f 6 months ago 209MB

[dw@dk ~]$ sudo docker run -it atguigu/mytomcat # 可以发现不加版本号会默认找latest版本
Unable to find image 'atguigu/mytomcat:latest' locally

[dw@dk ~]$ sudo docker run -it -p 7777:8080 atguigu/mytomcat:1.2

访问atguigu/mytomcat:1.2的应用,可以看到:

运行原始镜像tomcat:

1
[dw@dk ~]$ sudo docker run -it -p 7788:8080 tomcat

总结

之前是由镜像生成容器实例,反过来也可以根据当前运行的容器实例状况生成新的镜像,有点像java的反射,类到实例,实例可以反过来得到类的信息。即通过镜像可以得到我们自定义的容器。


上一篇 Docker的常用命令

下一篇预告 Docker容器数据卷