Docker——镜像管理

镜像概念

 docker 镜像是一个只读的 docker 容器模板,含有启动 docker 容器所需的文件系统结构及其内容,因此是启动一个 docker 容器的基础。

rootfs(根文件系统)

rootfs 是 docker 容器在启动时内部进程可见的文件系统,即 docker 容器的根目录。rootfs 通常包含一个操作系统运行所需的文件系统,例如可能包含典型的类 Unix 操作系统中的目录系统,如 /dev、/proc、/bin、/etc、/lib、/usr、/tmp 及运行 docker 容器所需的配置文件、工具等.

  • 传统Linux系统

传统Linux操作系统内核启动,首先挂载一个只读的 rootfs,当系统检测其完整性之后,再将其切换为读写模式。

  • docker架构

当 docker daemon 为 docker 容器挂载 rootfs 时,沿用了 Linux 内核启动时的做法,即将 rootfs 设为只读模式。在挂载完毕之后,利用联合挂载(union mount)技术在已有的只读 rootfs 上再挂载一个读写层。

镜像的运行

如上图:

当由 ubuntu:14.04 镜像启动容器时,ubuntu:14.04 镜像的镜像层内容将作为容器的 rootfs;而 ubuntu:14.04 镜像的 json 文件,会由 docker daemon 解析,并提取出其中的容器执行入口 CMD 信息,以及容器进程的环境变量 ENV 信息,最终初始化容器进程。当然,容器进程的执行入口来源于镜像提供的 rootfs。

镜像的存储驱动(storage driver)

对于一个容器的数据新增,修改,都存储在可写层.当你删除一个容器的时候,可写层也将被删除(注意:可写层与数据卷的区别).然而镜像层是保持不变的.

上图展示了,多个容器共享一个镜像.镜像层是只读层,不变的.多个容器层在同一个镜像层之上,并且相互独立,互相不影响.

docker 存储驱动的职责就是将镜像层和可写容器层管理起来.不同的驱动实现管理的方式也不一致。

实现容器与镜像管理的两个关键技术就是可堆叠的镜像层和copy-on-write (CoW,写时复制).

docker目前支持的存储驱动有:OverlayFS,AUFS,Btrfs,Device Mapper,VFS,ZFS.

docker的存储驱动目前并没有一个通用的,完美的,适用于所有环境的存储驱动.所以需要根据自己的环境来有所选择。

存储驱动 特点 优点 缺点 适用场景
AUFS 联合文件系统、未并入内核主线、文件级存储 作为docker的第一个存储驱动,已经有很长的历史,比较稳定,且在大量的生产中实践过,有较强的社区支持 有多层,在做写时复制操作时,如果文件比较大且存在比较低的层,可能会慢一些 大并发但少IO的场景
overlayFS 联合文件系统、并入内核主线、文件级存储 只有两层 不管修改的内容大小都会复制整个文件,对大文件进行修改显示要比小文件消耗更多的时间 大并发但少IO的场景
Devicemapper 并入内核主线、块级存储 块级无论是大文件还是小文件都只复制需要修改的块,并不是整个文件 不支持共享存储,当有多个容器读同一个文件时,需要生成多个复本,在很多容器启停的情况下可能会导致磁盘溢出 适合io密集的场景

Docker镜像制作

多数情况下,我们做镜像是基于别人已存在的某个基础镜像来实现的,我们把它称为base image。比如一个纯净版的最小化的centos、ubuntu或debian。

Docker镜像制作实例一:

  • 选取base image镜像,这里以busybox为例
[root@localhost boot]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox

Digest: sha256:49dae530fd5fee674a6b0d3da89a380fc93746095e7eca0f1b70188a95fd5d71
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest

[root@localhost ~]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED       SIZE
busybox            latest    a77dce18d0ec   6 days ago    1.24MB
httpd              latest    dd85cdbb9987   3 weeks ago   138MB
nginx              stable    05f64a802c26   3 weeks ago   133MB

  • 以busybox镜像为模板,创建test1容器
[root@localhost boot]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

## 运行此容器,并以交互方式进入容器内部
[root@localhost boot]# docker run -it --name 'test1' busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
  • 修改容器内部文件数据(这里以创建新文件为例)
/ # mkdir data
/ # echo 'hello world' > /data/abc
/ # cat /data/abc 
hello world
  • 保持容器运行,另开一个host终端,并将此容器保存为新的镜像
[root@localhost ~]# docker commit -p test1
sha256:c3b1c27be67af7f805b222d1bfd21f9c7752ae955563290dd4930173f17a7720

## 查看目前docker本地的所有镜像
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
<none>       <none>    c3b1c27be67a   6 seconds ago   1.24MB
busybox      latest    a77dce18d0ec   6 days ago      1.24MB
httpd        latest    dd85cdbb9987   3 weeks ago     138MB
nginx        stable    05f64a802c26   3 weeks ago     133MB
  • 重命名新生成的镜像以及定义版本号
[root@localhost ~]# docker tag c3b1c27be67a sawyer1995/test1:l0.1
[root@localhost ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
sawyer1995/busybox   l0.1      c3b1c27be67a   2 minutes ago   1.24MB
busybox              latest    a77dce18d0ec   6 days ago      1.24MB
httpd                latest    dd85cdbb9987   3 weeks ago     138MB
nginx                stable    05f64a802c26   3 weeks ago     133MB
  • 将此作为个人镜像push到docker_hub上

    • 在个人主页上创建新的仓库
    • 输入仓库名字并创建
    • 将本地镜像推送到个人主页上
    ### 登录个人主页
    [root@localhost ~]# docker login
    Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
    Username: sawyer1995
    Password: 
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
    
    [root@localhost ~]# docker push sawyer1995/test1:l01
    The push refers to repository [docker.io/sawyer1995/test1]
    
    
    l01: digest: sha256:fe03120da795790cc0058077c8a3ff375756c553e9e8be5ae4d2b76eaa5f7726 size: 734
    
    • 查看个人主页是否push成功
  • 验证push的镜像是否为修改过的镜像

## 删掉此前所有busybox的相关镜像
docker rmi 63c827625ddc
Untagged: sawyer1995/test1:l01
Untagged: sawyer1995/test1@sha256:fe03120da795790cc0058077c8a3ff375756c553e9e8be5ae4d2b76eaa5f7726
Deleted: sha256:63c827625ddc3b50c9e874dd040a0af6a7eead34847ce2521d41592e220c57ef
Deleted: sha256:f80271bcb88be88ba27c2f1c7e7bdc109ebaa8aeda8dc7fb128d4f5218b304d0
......

[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
httpd        latest    dd85cdbb9987   3 weeks ago   138MB
nginx        stable    05f64a802c26   3 weeks ago   133MB

## 将此前push的镜像pull到本地,创建容器并执行
[root@localhost ~]# docker run --name 'ver1' -it sawyer1995/test1:l01
Unable to find image 'sawyer1995/test1:l01' locally
l01: Pulling from sawyer1995/test1
d60bca25ef07: Already exists 
ca88adcce56d: Pull complete 
Digest: sha256:fe03120da795790cc0058077c8a3ff375756c553e9e8be5ae4d2b76eaa5f7726
Status: Downloaded newer image for sawyer1995/test1:l01
/ # 

## 成功进入到容器内,查看此前新建的文件,看是否存在
/ # cd data/
/data # ls
123
/data # cat 123 
hello world
/data # 

Docker镜像制作实例二(修改CMD):

  • 还是以busybox为base images 创建并交互进入test2容器
[root@localhost ~]# docker run --name test2 --rm -it busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var

## 另开终端,查看test2容器的默认CMD
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "sh"               ## 默认进程为sh
            ],
  • 生成index.html文件,作为http的主页文件
/ # mkdir data
/ # cd data/
/data # echo 'Test Web' > index.html
/data # cat index.html 
Test Web
  • 提交为新镜像

注意:这里要修改CMD,也就是默认进程,使得此容器启动时,以httpd的进程来访问index.html文件,从而实现web服务的效果

[root@localhost ~]# docker commit -c 'CMD ["/bin/httpd","-f","-h","/data"]' test2 sawyer1995/test1:l02
sha256:256055b555089b665850ac032f6da3d1295bbbbc0ba07e7533b161feb8bf0001

参数说明:
-f : httpd 命令已前台执行不退出
-h :指定家目录,默认当前目录


## 查看新的image
[root@localhost ~]# docker images sawyer1995/test2
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
sawyer1995/test2   l02       256055b55508   8 minutes ago   1.24MB

  • 查看此image的默认CMD
[root@localhost ~]# docker inspect 256055b55508
......
           "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/httpd",
                "-f",
                "-h",
                "/data"
            ],
  • 将此image push到个人主页仓库中
[root@localhost ~]# docker push sawyer1995/test1:l02
[root@localhost ~]# docker push sawyer1995/test1:l02
The push refers to repository [docker.io/sawyer1995/test1]
387feb2e9433: Layer already exists 
1dad141bdb55: Layer already exists 
l02: digest: sha256:948a1d0b8558e0e815d4f1bc883142feb839beb704d38e9df5a25998fad8f68e size: 734

  • 测试将此镜像Pull本地,并访问
[root@localhost ~]# docker run --rm -d sawyer1995/test1:l02
Unable to find image 'sawyer1995/test1:l02' locally
l02: Pulling from sawyer1995/test1
d60bca25ef07: Already exists 
f91f934e1579: Pull complete 
Digest: sha256:948a1d0b8558e0e815d4f1bc883142feb839beb704d38e9df5a25998fad8f68e
Status: Downloaded newer image for sawyer1995/test1:l02
e8aee14c4fd03286734001eaf50f791a9d6f722bc78eeb8fd8f13ad0cc874e26


[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS     NAMES
e8aee14c4fd0   sawyer1995/test1:l02   "/bin/httpd -f -h /d…"   13 seconds ago   Up 12 seconds             pensive_diffie

## curl测试访问网页
[root@localhost ~]# curl 172.17.0.2
Test Web
posted @ 2021-01-05 17:02  阿不思布丁  阅读(299)  评论(0编辑  收藏  举报