Docker
Docker可以看成一个高性能的虚拟机,并且不会浪费资源,主要用于Linux环境的虚拟化
笔记参考 :大量解释来自下链接–>
获取镜像 | Docker 从入门到实践 (docker-practice.com)
传统的虚拟机和Docker的区别(需要查看)
类比解释
每台宿主机(电脑),他下载好了Docker
后,可以生成多个镜像,每个镜像,可以创建多个容器。发布到仓库时,以镜像为单位。可以理解成:一个容器就是一个独立的虚拟操作系统,互不影响,而镜像就是这个操作系统的安装包。想要生成一个容器,就用安装包(镜像)生成一次
性能
高效的虚拟化:不需要额外的hypervisor 虚拟机监视器(多操作系统并行监督)
三个概念
基础命令
systemctl start 启动进程
–help词典
image镜像
只读的模板
docker pull指令
拉取镜像[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KehQUexs-1650433281199)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302134158893.png)]
镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。下载过程中给出了每一层的 ID 的前 12 位。并且下载结束后,给出该镜像完整的 sha256
的摘要,以确保下载一致性。
docker images
查看本地安装的镜像[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xuBPoO6A-1650433281200)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302134303090.png)]
字段 来源 标记 id 创建事件 大小
TAG一般用于标记版本
列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。
ls结合 -f --fliter实现的过滤器
--filter
配合 -q
产生出指定范围的 ID 列表,然后送给另一个 docker
命令作为参数
创建镜像
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6lJYsmkD-1650433281201)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302134757654.png)]
在容器中装入新应用 然后提交docker commit
-m来指定提交的说明信息,跟我们使用的版本控制工具一样;-a可以指定更新的用户信息;之后是用来创建镜像的容器的ID;最后指定目标镜像的仓库名和tag信息。创建成功后会返回这个镜像的ID信息。
对镜像的依赖和内容进行修改产生新镜像
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-srLHG5gX-1650433281202)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302162518989.png)]
从 rootfs 压缩包导入
gzip导入
docker save <镜像名> | bzip2 | pv | ssh <用户名>@<主机名> 'cat | docker load'
中间层镜像
重复利用资源采用的依赖的中间层镜像
用Dockerfile创建镜像
解决无法重复的问题、镜像构建透明性的问题、体积的问题的显示构建文件
run的安装命令 from指定基础镜像 #参与注释 ADD复制本地文件到镜像
EXPOSE命令来向外部开放端口
使用docker build构建创建项目
一个镜像最多不能超过127层
docker tag命令修改镜像标签
Docker 还存在一个特殊的镜像,名为 scratch
。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉
镜像构建上下文
当构建的时候,用户会指定构建镜像上下文的路径,docker build
命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。
实际上 Dockerfile
的文件名并不要求必须为 Dockerfile
,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockerfile.php
参数指定某个文件作为 Dockerfile
docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world
这行命令指定了构建所需的 Git repo,并且指定分支为 master
,构建目录为 /amd64/hello-world/
,然后 Docker 就会自己去 git clone
这个项目、切换到指定分支、并进入到指定目录后开始构建
docker分为服务端守护进程和客户端工具
从本地的文件系统内导入镜像
cat 加管道||dockerimport-
移除本地镜像
docker rmi
untagged 和deleted两种删除类型
因此当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消
上传镜像
docker push命令可以上传自己创建的镜像
导出镜像
docker save指令
$sudodockersave-oubuntu_14.04.tarubuntu:14.04
system df展现所有镜像/容器/数据卷等
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BPD6KHXR-1650433281202)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302195237516.png)]
rmi -f 镜像 or $(-qa)
docker虚悬镜像问题
仓库名和标签都是none
docker image prune
run命令的实现过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZdhfzBZ-1650433281203)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302193804026.png)]
镜像的实现原理
是轻量级的 可执行的独立软件包 程序和依赖环境
镜像是分层的**---->联合二五年间系统 对文件系统的修改层级叠加
将不同的目录挂载到同一个虚拟文件系统下UNIONFS
docker镜像加载原理
镜像是由多层文件系统组成
boot file system 加载一个boots和内核底层 往上搭建rootfs
采用不同的rootfs 和共用host的kernel操作系统内核 实现一致简洁
docker分层的意义
镜像层只读 容器层可写 当容器启动时添加新的可写层
黑箱镜像
使用docker commit产生的镜像 在工作之后导致镜像变得臃肿
container容器
从镜像中创建的运行实例 简易版环境
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间 (opens new window)。因此容器可以拥有自己的 root
文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
容器命令
docker run 【options】 image
options:–name命名
-i(interactive)交互模式运行 -t分配一个伪终端 -it交互终端
(指定shell 接入到了容器实例运行的bash程序 进而转控容器实例)
-P随机端口映射 -p固定端口映射(访问docker程序 到 访问容器实例)
–rm在退出容器后将其删除
docker ps查看当前开启容器 注意相应options
根据相应的容器ID对容器多操作
Docker容器本质上是宿主机上的进程。容器进程ID就是宿主机进程ID**
容器中进退
exit关闭容器进程停止 ctrl +p+q是暂时退出
后台进程
docker run -d后台运行(守护式容器)
查看容器的运行日志logs 加容器pid
查看容器内的运行进程top 加容器pid 可查看容器内的uid
查看容器内部细节 inspect
重新进入运行的容器并进行交互 exec(新终端) attach(老终端)
利用 docker run
来创建容器
Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从 registry 下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
导入导出容器
docker export命令 | docker import命令 让容器从快照文件重新变为镜像
清除容器以及查看所有容器
查看 docker container ls -a
清除 docker container prune
repository仓库
开源和私有 可以看作是服务器上运行的进程 方便进行文件的存取
阿里云开设个人仓库
- 登录阿里云Docker Registry
$ docker login --username=kk**** registry.cn-hangzhou.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码。
- 从Registry中拉取镜像
$ docker pull registry.cn-hangzhou.aliyuncs.com/yxkshiyan/yxksy1:[镜像版本号]
- 将镜像推送到Registry
$ docker login --username=kk**** registry.cn-hangzhou.aliyuncs.com$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/yxkshiyan/yxksy1:[镜像版本号]$ docker push registry.cn-hangzhou.aliyuncs.com/yxkshiyan/yxksy1:[镜像版本号]
请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。
- 选择合适的镜像仓库地址
从ECS推送镜像时,可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。
如果您使用的机器位于VPC网络,请使用 registry-vpc.cn-hangzhou.aliyuncs.com 作为Registry的域名登录。
- 示例
使用"docker tag"命令重命名镜像,并将它通过专有网络地址推送至Registry。
$ docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEregistry.aliyuncs.com/acs/agent 0.7-dfb6816 37bb9c63c8b2 7 days ago 37.89 MB$ docker tag 37bb9c63c8b2 registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816
使用 “docker push” 命令将该镜像推送至远程。
$ docker push registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816
docker register私有搭建个人仓库
拉取registry私服镜像 启动容器
官方的registry镜像 :从这里看出它也是一个进程只是适配了命令
docker run -d -p 5000:5000 --restart=always --name registry registry
私有仓库高级配置
使用 Docker Compose
搭建一个拥有权限认证、TLS 的私有仓库
私有仓库高级配置 | Docker 从入门到实践 (docker-practice.com)
有域名学了ssl后自己实践
使用Nexu的私有仓库
Nexus3.x 的私有仓库 | Docker 从入门到实践 (docker-practice.com)
自己实现新镜像
在原始官网的bash中迭代 添加新层 形成自我镜像
commit -m -a 容器id 标签 指定一系列的参数
docker run -d -p 5000:5000 -v /yxkkxy/myregistry/:/tmp/registry --privileged=true registry 指定容器卷创建仓库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VHKwhN0S-1650433281204)(https://gitee.com/nwesnn/image/raw/master/笔记/image-20220303142731199.png)]
在/etc/docker/damom.json中修改过docker的镜像源和取消其默认的禁止http请求
curl超时:云服务器端口开放
问题2:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rcSsN1Pt-1650433281204)(https://gitee.com/nwesnn/image/raw/master/笔记/image-20220303150158987.png)]
更改网络筛选配置
注意不要直接去清除rm -rf /var/lib/docker/
容器内文件备份
docker cp 容器id: 容器内路径 目的主机路径(copy重要的文件)
export整个容器的内容留作为备份的.tar包
对应的import 可以恢复备份的文件系统再导入为镜像
Docker是一个Client-Server类型的进程
Dockerfile指令详解
From指定基础镜像
Run 函数运作创建一层docker容器 运行后续的指令
Copy复制文件
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
从构建上下文目录中 <源路径>
的文件/目录复制到新的一层的镜像内的 <目标路径>
位置(用户所指定)
同时build的文件可以自己指定 而不是解析tar包后的首个dockerfile
使用 COPY
指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
在使用该指令的时候还可以加上 --chown=<user>:<group>
选项来改变文件的所属用户及所属组。
COPY --chown=55:mygroup files* /mydir/COPY --chown=bin files* /mydir/COPY --chown=1 files* /mydir/COPY --chown=10:11 files* /mydir/
如果源路径为文件夹,复制的时候不是直接复制该文件夹,而是将文件夹中的内容复制到目标路径。
ADD指令: 与COPY基本类似 但是可以获取url资源(默认权限为600)
CMD容器启动命令:
shell
格式:CMD <命令>
exec
格式:CMD ["可执行文件", "参数1", "参数2"...]
容器启动后执行的命令 改变其默认命令(容器为其主进程的运行而存在,不应该将想要运行的主进程作为辅助进程写入 也就是采用默认的shell形式)
ENTRYPOINT:与CMD类似 但是可以将镜像当做命令使用 在已有的命令后run后添加的参数会追加在命令的后方
可以看到,这次成功了。这是因为当存在 ENTRYPOINT
后,CMD
的内容将会作为参数传给 ENTRYPOINT
,而这里 -i
就是新的 CMD
,因此会作为参数传给 curl
,从而达到了我们预期的效果
给运行中的容器设定可执行脚本 通过传入参数实现其中具体的命令
ENV设置环境变量:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
使用环境变量实现操作定制
ARG构建参数:和ENV效果一致 容器运行时不存在这些环境变量
Dockerfile
中的 ARG
指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build
中用 --build-arg <参数名>=<值>
来覆盖。
灵活的使用 ARG
指令,能够在不修改 Dockerfile 的情况下,构建出不同的镜像。
ARG 指令有生效范围,如果在 FROM
指令之前指定,那么只能用于 FROM
指令中。
VOLUME指令:在原先容器的存储层内的需要动态修改的一些存储数据 采用虚拟卷的形式挂载 后续在运行中进行替换
EXPOSE指令:
EXPOSE <端口1> [<端口2>...]
在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P
时,会自动随机映射 EXPOSE
的端口。
WORKDIR:工作目录 指定工作目录 每一层dockerfile的执行环境不同 是不同的两个容器 shell脚本一些基本的内存工作状态的变化不会被继承
USER:指定当前的用户 改变运行环境层次的身份
HEALTHCHECK:
HEALTHCHECK [选项] CMD <命令>
:设置检查容器健康状况的命令HEALTHCHECK NONE
:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
在没有 HEALTHCHECK
指令前,Docker 引擎只可以通过容器内主进程是否退出来判断容器是否状态异常。很多情况下这没问题,但是如果程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了。在 1.12 以前,Docker 不会检测到容器的这种状态,从而不会重新调度,导致可能会有部分容器已经无法提供服务了却还在接受用户请求。
HEALTHCHECK --interval=5s --timeout=3s
LABEL <key>=<value> <key>=<value> <key>=<value> ...
SHELL指令:SHELL指令可以指定
RUNENTRYPOINT
CMD
指令的 shell,Linux 中默认为
["/bin/sh", “-c”]
ONBUILD:没搞懂
多阶段构建
将构建流程全部包含在一个Dockerfile中的传统模式
- 镜像层次多,镜像体积较大,部署时间变长
- 源代码存在泄露的风险
可能会导致以上的问题
分散到多个dockerfile中 :虽然体积减小 但实现过程较为复杂(需要sh执行两个df的构建)
使用多阶段构建:multistage builds |as ****分离过程 给镜像瘦身
只构建某一阶段的镜像
例如当我们只想构建 builder
阶段的镜像时,增加 --target=builder
参数即可
$ docker build --target builder -t username/imagename:tag .
构建时可以从其他镜像中复制文件:
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
多阶段构建镜像实战
容器数据卷
在主机里使用以下命令可以查看指定 数据卷
的信息
$ docker volume inspect my-vol
坑 :–privileged=true 挂载主机目录访问无法访问
container内的root拥有真正的root权限 扩大容器的权限
解决无法挂载目录的低权限问题
将容器内的数据备份+持久化到宿主机的目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eD58cGrF-1650433281205)(https://gitee.com/nwesnn/image/raw/master/笔记/image-20220303155800591.png)]
备份数据卷的文件会被同步更新在检测该容器的主机数据卷中
:rw可读可写的形式|
:ro只读的模式|容器只读
挂载的理解(可以多个挂载)
docker inspect 暴露容器的所有信息(查看其挂载的具体信息)

在docker容器停止后 (重启) 会默认读取所有备份信息(快照?)
容器卷的继承
继承卷规则 --volumes-from
Docker中的网络功能
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。
外部访问容器
-p 或者 -P指定实现端口映射
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务
访问外部端口即可访问容器实例内运行的网络环境
可以通过docker logs查看访问记录
容器互联
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。
下面先创建一个新的 Docker 网络。
$ docker network create -d bridge my-net
其他
阿里云镜像加速等
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BhDkfsOy-1650433281205)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20220302193548838.png)]
重启镜像配置 采用加速器
为什么docker会比虚拟机快
1.比虚拟机更少的抽象层
直接使用实际物理机的资源 不需要硬件资源的虚拟化
2.docker直接使用的宿主机内核
屏蔽了不同虚拟机之间的不同操作系统的差异