镜像的概念
镜像可以理解为应用程序的集装箱,而docker用来装卸集装箱。
docker镜像含有启动容器所需要的文件系统及其内容,因此,其用于创建并启动容器。
docker镜像采用分层构建机制,最底层为bootfs,其上为rootfs
- bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源
- rootfs:位于bootfs之上,表现为docker容器的根文件系统
传统模式中,系统启动之时,内核挂载rootfs会首先将其挂载为“只读”模式,完整性自检完成后将其重新挂载为读写模式
docker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载”技术额外挂载一个“可写”层
注意:当删除容器时,这个容器自有的“可写”层会一起被删除
docker镜像层
位于下层的镜像称为父镜像(parrent image),最底层的称为基础镜像(base image);
最上层为“可读写”层,其下的均为“只读”层。
镜像的存储驱动
对于一个容器的数据新增,修改,都存储在可写层.当你删除一个容器的时候,可写层也将被删除(注意:可写层与数据卷的区别).然而镜像层是保持不变的.
上图展示了,多个容器共享一个镜像.镜像层是只读层,不变的.多个容器层在同一个镜像层之上,并且相互独立,互相不影响.
docker目前支持的存储驱动有:OverlayFS,AUFS,Btrfs,Device Mapper,VFS,ZFS.
docker的存储驱动目前并没有一个通用的,完美的,适用于所有环境的存储驱动.所以需要根据自己的环境来有所选择。
存储驱动 | 特点 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
AUFS | 联合文件系统、未并入内核主线、文件级存储 | 作为docker的第一个存储驱动,已经有很长的历史,比较稳定,且在大量的生产中实践过,有较强的社区支持 | 有多层,在做写时复制操作时,如果文件比较大且存在比较低的层,可能会慢一些 | 大并发但少IO的场景 |
overlayFS | 联合文件系统、并入内核主线、文件级存储 | 只有两层 | 不管修改的内容大小都会复制整个文件,对大文件进行修改显示要比小文件消耗更多的时间 | 大并发但少IO的场景 |
Devicemapper | 并入内核主线、块级存储 | 块级无论是大文件还是小文件都只复制需要修改的块,并不是整个文件 | 不支持共享存储,当有多个容器读同一个文件时,需要生成多个复本,在很多容器启停的情况下可能会导致磁盘溢出 | 适合io密集的场景 |
Docker镜像制作
多数情况下,我们做镜像是基于别人已存在的某个基础镜像来实现的,我们把它称为base image。比如一个纯净版的最小化的centos、ubuntu或debian。
- 选取base image镜像,这里以busybox为例
[root@localhost ~]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
d60bca25ef07: Pull complete
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
nginx latest ae2feff98a0c 2 weeks ago 133MB
httpd latest dd85cdbb9987 3 weeks ago 138MB
- 以busybox镜像为模板,创建test1容器
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f42dd60d68db httpd "httpd-foreground" 7 hours ago Up 6 hours 80/tcp interesting_moore
644c5aa28e9d nginx "/docker-entrypoint.…" 9 hours ago Created sleepy_hofstadter
[root@localhost ~]# docker run -it --name 'test1' busybox
/ # ls
bin etc proc sys usr
dev home root tmp var
/ #
- 修改容器内部文件数据(这里以创建新文件为例)
/ # mkdir data
/ # echo 'hello tjp' > /data/abc
- 在创建镜像时,我们不能关闭容器,必须使其处于运行状态,所以我们必须要另起一个终端,然后执行
[root@localhost ~]# docker commit -p test1
sha256:55e297c9c78e8f03901e41e46a68f8871de6c767a8762e8c278dadfd4fa3f5d8
#### 查看目前docker本地的所有镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 55e297c9c78e 23 seconds ago 1.24MB
busybox latest a77dce18d0ec 6 days ago 1.24MB
nginx latest ae2feff98a0c 2 weeks ago 133MB
httpd latest dd85cdbb9987 3 weeks ago 138MB
- 重命名新生成的镜像以及定义版本号(要与自己账户一致,否则不能传)
[root@localhost ~]# docker tag 55e297c9c78e TANG/busybox:1.05
Error parsing reference: "TANG/busybox:1.05" is not a valid repository/tag: invalid reference format: repository name must be lowercase
###### 这里新的文件名要与创建的容器名一致,也就是test1
[root@localhost ~]# docker tag 55e297c9c78e tangjunpeng1995/test1:202101.05
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tangjunpeng1995/busybox 202101.05 55e297c9c78e 4 minutes ago 1.24MB
busybox latest a77dce18d0ec 6 days ago 1.24MB
nginx latest ae2feff98a0c 2 weeks ago 133MB
httpd latest dd85cdbb9987 3 weeks ago 138MB
- 将此作为个人镜像push到docker_hub上:
1.在个人主页上创建新的仓库
2.输入仓库名字并创建
3.将本地镜像推送到个人主页上
[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: tangjunpeng1995
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 images
REPOSITORY TAG IMAGE ID CREA
tangjunpeng1995/busybox 202101.05 55e297c9c78e 32 m
busybox latest a77dce18d0ec 6 da
nginx latest ae2feff98a0c 2 we
httpd latest dd85cdbb9987 3 we
#### 注意push为推送镜像的名字
[root@localhost ~]# docker push tangjunpeng1995/test1:202101.05
The push refers to repository [docker.io/tangjunpeng1995/busybox]
fd2649ec67bc: Pushed
1dad141bdb55: Mounted from library/busybox
Head https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/55/55e297c9c78e8f03901e41e46a68f8871de6c767a8762e8c278dadfd4fa3f5d8/data?verify=1609863313-KRbL86v2AKSmQ3XO8BUAV82NYT4%3D: net/http: TLS handshake timeout
[root@localhost ~]# docker push tangjunpeng1995/busybox:202101.05
The push refers to repository [docker.io/tangjunpeng1995/busybox]
fd2649ec67bc: Layer already exists
1dad141bdb55: Layer already exists
202101.05: digest: sha256:58e16445745ae87ed25a6d35b71ff9646a0fb211a74941b877bfdb958f36cea3 size: 734
- 查看个人主页是否push成功
- 验证push的镜像是否为修改过的镜像
删掉此前所有busybox的相关镜像
[root@localhost ~]# docker rmi -f 55e297c9c78e
Untagged: tangjunpeng1995/busybox:202101.05
Untagged: tangjunpeng1995/busybox@sha256:58e16445745ae87ed25a6d35b71ff9646a0fb211a74941b877bfdb958f36cea3
Untagged: tangjunpeng1995/test1:202101.05
Untagged: tangjunpeng1995/test1@sha256:58e16445745ae87ed25a6d35b71ff9646a0fb211a74941b877bfdb958f36cea3
Deleted: sha256:55e297c9c78e8f03901e41e46a68f8871de6c767a8762e8c278dadfd4fa3f5d8
Deleted: sha256:7227e2ae841bf71ec2de5065ba59238ec4ec5d34c91b1c39c7ac69d52fdfdeae
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest a77dce18d0ec 6 days ago 1.24MB
nginx latest ae2feff98a0c 2 weeks ago 133MB
httpd latest dd85cdbb9987 3 weeks ago 138MB
将此前push的镜像pull到本地,创建容器并执行
[root@localhost ~]# docker run --name test2 -it tangjunpeng1995/test1:202101.05
Unable to find image 'tangjunpeng1995/test1:202101.05' locally
202101.05: Pulling from tangjunpeng1995/test1
d60bca25ef07: Already exists
25e6c35a4350: Pull complete
202101.05: Pulling from tangjunpeng1995/test1
d60bca25ef07: Already exists
25e6c35a4350: Already exists
202101.05: Pulling from tangjunpeng1995/test1
d60bca25ef07: Already exists
25e6c35a4350: Already exists
Digest: sha256:58e16445745ae87ed25a6d35b71ff9646a0fb211a74941b877bfdb958f36cea3
Status: Downloaded newer image for tangjunpeng1995/test1:202101.05
/ # cd data/
/data # ls
abc
/data # cat abc
hello tjp