写点什么

【docker 总结】第五篇 - 制作镜像、数据盘

作者:Brave
  • 2021 年 12 月 17 日
  • 本文字数:5709 字

    阅读完需:约 19 分钟

一,制作个性化镜像


根据公司的技术栈和技术选型,项目有个性化偏好,需要定制镜像,如:环境配置、软件版本等;

制作个性化镜像,无需每次都进行重复的配置环境,实现开箱即用;


制作个性化镜像有两种方式:

  • 基于 commit 制作

  • 根据 Dockerfile 构建

1,第一种:基于 commit 制作镜像


根据镜像启动容器,在容器内完成环境安装后,基于新的容器提交成为新的镜像,后续基于新镜像启动容器即可;


1,根据 ubuntu 镜像启动容器,添加新的文件,退出

// 启动容器并进入容器内部BravedeMacBook-Pro:~ brave$ docker run -it ubuntu /bin/bash// 创建文件root@9ae402815828:/# cd /rootroot@9ae402815828:~# touch my.txt// 退出容器root@9ae402815828:~# exitexit
复制代码


2,将新的容器提交成为新的镜像

// 将指定容器提交为镜像BravedeMacBook-Pro:~ brave$ docker container commit -m"my ubuntu" -a"brave" 9ae402815828 brave/myubuntu:v1sha256:23ed9c6a0c37e3648f995dd96c319e37d56631e6be1c7c0c37c97485be54baf5
// 查看本地镜像列表BravedeMacBook-Pro:~ brave$ docker image lsREPOSITORY TAG IMAGE ID CREATED SIZEbrave/myubuntu v1 23ed9c6a0c37 34 seconds ago 72.8MBmyroot latest 45a3985181e6 17 hours ago 72.8MBnginx latest f652ca386ed1 46 hours ago 141MBubuntu latest ba6acccedd29 7 weeks ago 72.8MBbrave/centos v1 feb5d9fea6a5 2 months ago 13.3kBhello-world latest feb5d9fea6a5 2 months ago 13.3kBcentos 6 5bf9684f4720 2 months ago 194MBcentos latest 5d0da3dc9764 2 months ago 231MB
// 根据新镜像,启动容器BravedeMacBook-Pro:~ brave$ docker run -it 23ed9c6a0c37 /bin/bashroot@625496544fa9:/# cd /rootroot@625496544fa9:~# lsmy.txt
// 结论,基于新镜像启动的容器中,包含了新容器中的自定义内容
复制代码


基于 commit 制作镜像,优点是直观,但不好管理;


2,第二种:根据 Dockerfile 构建


通过一个文件描述改变和操作,描述一个镜像的构建过程


  • Docker 的镜像是用一层一层的文件组成的

  • docker inspect 命令可以查看镜像或者容器

  • Layers 就是镜像的层文件,只读不能修改。基于镜像创建的容器会共享这些文件层

docker inspect centos
复制代码


比如,制作一个 express 的镜像文件


// todo 添加详细实例


3,提交、发布镜像


  • 注册账户

  • docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]


// 注册并登录 dockerdocker login// tagdocker image tag [imageName] [username]/[repository]:[tag]// builddocker image build -t [username]/[repository]:[tag] .
// tagdocker tag express-demo zhangrenyang/express-demo:v1// 推送docker push zhangrenyang/express-demo:v1
复制代码



数据盘


介绍


根据镜像创建一个容器,相当于在底层镜像上添加了一个读写层(就是容器),这样就可以改东西了;

如果将容器 rm 删掉了,就意味着整个都没了,即:整个镜像和容器层都没了;


那样的话,容器中存储的内容也就都丢掉了;

实际开发总,服务的日志需要保留;

mysql 容器删除后,数据不能丢失;

那么,可以将日志放到宿主机上;


这里需要使用 docker 的数据盘:

为容器创建数据盘:


三种方式:

  • bind mount 挂载点

  • volume 数据卷

  • tmpfs mount


备注:tmpfs mount 是挂载到内存中,很少用到;

volumes 数据卷


  • volumes 是 Docker 管理宿主机文件系统的一部分(地址在 /var/lib/docker/volumes);

  • 如果没有指定卷,则会自动创建;

  • 建议使用--mount,更通用;


准备工作:删除所有容器

// 停掉所有容器 stop 比较优雅相对慢一些,kill 比较快BravedeMacBook-Pro:~ brave$ docker container stop $(docker container ps -a -q)625496544fa99ae4028158289c68a087624c4e7e482c7938d0f4ff48842786dfeaa9638cf08109d1269d7f87bc954787
// 删除所有容器BravedeMacBook-Pro:~ brave$ docker container rm $(docker container ps -a -q)625496544fa99ae4028158289c68a087624c4e7e482c7938d0f4ff48842786dfeaa9638cf08109d1269d7f87bc954787
// 查看所有容器BravedeMacBook-Pro:~ brave$ docker container ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
复制代码

创建数据卷


查看 volume 命令

BravedeMacBook-Pro:~ brave$ docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands: create Create a volume inspect Display detailed information on one or more volumes ls List volumes prune Remove all unused local volumes rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
复制代码


创建数据卷

创建数据卷存放 nginx 日志

BravedeMacBook-Pro:~ brave$ docker volume create nginx-loggernginx-logger
复制代码

在宿主机硬盘上的哪个位置?

/var/lib/docker/volumes/nginx-logger/_data

// 查看数据卷列表BravedeMacBook-Pro:~ brave$ docker volume lsDRIVER    VOLUME NAMElocal     nginx-logger
// 查看指定数据卷的详情BravedeMacBook-Pro:~ brave$ docker volume inspect nginx-logger[ { "CreatedAt": "2021-12-04T12:38:33Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/nginx-logger/_data", "Name": "nginx-logger", "Options": {}, "Scope": "local" }]
复制代码


如何使用数据卷?

挂载数据卷


再创建一个数据卷

BravedeMacBook-Pro:~ brave$ docker volume create nginx-htmlnginx-html
复制代码


将容器中的某个位置挂载到数据卷


根据 nginx 镜像创建一个后台运行的 nginx 容器,命名为 nginx1

将 nginx 的根目录(/usr/share/nginx/html)挂载到数据卷 nginx-html(宿主机的 /var/lib/docker/volumes/nginx-logger/_data)

BravedeMacBook-Pro:~ brave$ docker run -d --name nginx1 --mount src=nginx-html,dst=/usr/share/nginx/html nginx0f4d6a172bc863765f3c0b32605339d87992aea1d9b91ed34eb003a3ed889dca
nginx-html 数据卷/usr/share/nginx/html 是 nginx 的根目录
将 nginx 的根目录挂载到了数据卷 nginx-html 上,即 nginx 的根目录指向宿主机的nginx-html目录:"/var/lib/docker/volumes/nginx-logger/_data"
复制代码


启动后,查看数据卷内的数据


解决 MAC OS 问题

https://blog.csdn.net/qq_45673036/article/details/117901509

https://blog.csdn.net/qq_36457702/article/details/101030793

BravedeMacBook-Pro:~ brave$ docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i shUnable to find image 'debian:latest' locallylatest: Pulling from library/debian5e0b432e8ba9: Pull complete Digest: sha256:45ee40a844048c2f6d0105899c1a17733530b56d481612608aab5e2e4048570bStatus: Downloaded newer image for debian:latest/ # lsbin          dev          home         media        proc         sbin         tmpboot         etc          init         mnt          root         srv          usrcontainers   grpcfuse.ko  lib          opt          run          sys          var
// 进入 docker 目录/ # cd /var/lib/docker//var/lib/docker # lsbuildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
// 查看 docker 卷/var/lib/docker # cd volumes//var/lib/docker/volumes # lsbackingFsBlockDev metadata.db nginx-html nginx-logger
// 进入 nginx-html/_data//var/lib/docker/volumes # cd nginx-html/_data//var/lib/docker/volumes/nginx-html/_data # ls50x.html index.html
复制代码


还可以再进入到容器中的 nginx 根目录(此时容器内 nginx 的根目录与宿主机 nginx-html 数据卷已同步)

BravedeMacBook-Pro:~ brave$ docker container exec -it 0f4d6a172bc863 /bin/bashroot@0f4d6a172bc8:/# cd /usr/share/nginx/htmlroot@0f4d6a172bc8:/usr/share/nginx/html# ls50x.html  index.html
复制代码


在容器内创建一个文件(看数据卷会不会同步)

root@0f4d6a172bc8:/usr/share/nginx/html# touch test.html
复制代码


宿主机看一下,文件已经同步:

/var/lib/docker/volumes/nginx-html/_data # ls50x.html    index.html  test.html
复制代码


在宿主机创建一个文件

/var/lib/docker/volumes/nginx-html/_data # touch test1.html
复制代码


在容器内查看,已同步:

root@0f4d6a172bc8:/usr/share/nginx/html# ls50x.html  index.html  test.html  test1.html
复制代码


挂载有两种方法,上边讲的是第一种,很啰嗦

docker run -d --name nginx1 --mount src=nginx-html,dst=/usr/share/nginx/html nginx
复制代码



第二种,路径的映射可以简写


做 volume 映射 数据卷名称:容器目录

BravedeMacBook-Pro:~ brave$ docker run -d --name nginx2 -v nginx-html:/usr/share/nginx/html nginx2bb332f19311592bea94715f3494bbfc2ddb2e4c1c1ca017d8b4c6d43241dc83
复制代码

没有映射端口,都是 80,会不会冲突?

相当于两台机器,相互独立,与外部的宿主机没有关系;


进去目录看看,内容是一样的:

BravedeMacBook-Pro:~ brave$ docker container exec -it 2bb332f19311 /bin/bashroot@2bb332f19311:/# cd /usr/share/nginx/htmlroot@2bb332f19311:/usr/share/nginx/html# ls50x.html  index.html  test.html  test1.html
复制代码



删除数据卷


BravedeMacBook-Pro:~ brave$ docker volume rm nginx-htmlError response from daemon: remove nginx-html: volume is in use - [0f4d6a172bc863765f3c0b32605339d87992aea1d9b91ed34eb003a3ed889dca, 2bb332f19311592bea94715f3494bbfc2ddb2e4c1c1ca017d8b4c6d43241dc83]
复制代码

有两个容器正在使用,不能删除,想要删除需要先把这两个容器停掉

BravedeMacBook-Pro:~ brave$ docker container ps -aCONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS        PORTS     NAMES2bb332f19311   nginx     "/docker-entrypoint.…"   24 hours ago   Up 24 hours   80/tcp    nginx20f4d6a172bc8   nginx     "/docker-entrypoint.…"   25 hours ago   Up 25 hours   80/tcp    nginx1
BravedeMacBook-Pro:~ brave$ docker container kill 2bb332f19311 0f4d6a172bc82bb332f193110f4d6a172bc8
复制代码

两个容器已经停掉了,再删除发现还是不行

BravedeMacBook-Pro:~ brave$ docker volume rm nginx-htmlError response from daemon: remove nginx-html: volume is in use - [0f4d6a172bc863765f3c0b32605339d87992aea1d9b91ed34eb003a3ed889dca, 2bb332f19311592bea94715f3494bbfc2ddb2e4c1c1ca017d8b4c6d43241dc83]
复制代码

这是因为,两个容器挂载了数据卷


可以把容器删掉

// 查看数据卷列表BravedeMacBook-Pro:~ brave$ docker volume lsDRIVER    VOLUME NAMElocal     nginx-htmllocal     nginx-logger
// -f dangling=true 过滤悬挂的,即查看没有任何容器引用的数据卷BravedeMacBook-Pro:~ brave$ docker volume ls -f dangling=trueDRIVER VOLUME NAMElocal nginx-logger
这种是可以直接通过 docker volume rm 删掉的docker volume rm nginx-logger也可以一次将所有没有引用的数据卷都删掉docker volume prune
复制代码

bind mount 数据卷


如果 var/lib/docker/volumes 空间太小不够,就要放到其他地方,此时就不能用 volume 了

需要使用绑定挂载

docker run -v /mnt:/mnt -it --name logs centos bash将宿主机的/mnt 目录映射为这个容器的 /mnt 目录
复制代码

注意个 volume -v 的区别:

docker run -d --name nginx2 -v nginx-html:/usr/share/nginx/html nginx
这个-v nginx-html:/usr/share/nginx/html冒号左侧是数据卷名
复制代码


BravedeMacBook-Pro:~ brave$ docker run -v /mnt:/mnt -it --name logs centos bashdocker: Error response from daemon: Mounts denied: The path /mnt is not shared from the host and is not known to Docker.You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.See https://docs.docker.com/desktop/mac for more info.
复制代码



创建容器后,在容器的/mnt 目录创建一个 txt 文件,

宿主机的/mnt 会同步出现 txt 文件


这样就不会收到 docker/volumes 的限制,想吧数据放在哪就可以挂载到哪里


可以两个容器用一个数据盘 比如负载情况,日志可以写到一起去


创建容器

BravedeMacBook-Pro:~ brave$ docker create -v /Users/brave/logger:/logger --name logger centosc86fb1eb39ba1b87b84af741818b51d6e65e705934382fd3cc206e2d79f82fc1
BravedeMacBook-Pro:~ brave$ docker container ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES06531bf11e91 centos "/bin/bash" 43 seconds ago Created logger
复制代码

docker create 和 docker run 的区别是创建容器但不启动

我们创建它的作用不是用来启动的,而是数据挂载策略:用宿主机的/logger,挂载容器中的 /logger


继承容器:

--volumes-from:从哪个容器继承数据卷(logger 挂载了数据卷)

// logger_test1 继承 logger 容器的数据卷BravedeMacBook-Pro:~ brave$ docker run --volumes-from logger --name logger_test1 -it centos bash[root@4ce4b9717b5c /]# 
复制代码

在 logger_test1 容器内,即/logger 目录下创建一个文件


同理再创建一个 logger_test2,/logger 目录下存在刚刚 logger_test1 创建的文件

logger_test2 进入/logger 目录创建文件,logger_test1 也能看到

退出后,宿主机也能看到


优势,不需要知道数据卷的配置,只需要知道继承就好了

用户头像

Brave

关注

还未添加个人签名 2018.12.13 加入

还未添加个人简介

评论

发布
暂无评论
【docker 总结】第五篇 - 制作镜像、数据盘