一.概述
1.devops
开发、测试、运维间的矛盾,主要是由于环境的不同而引发的。
如果能将开发人员使用的环境交给测试与运维使用,这些问题就都能解决。
DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。
它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运维工作必须紧密合作。
2.docker
2.1 简介
Docker是一个开源的平台 ,用于开发、交付和运行应用程序。它能够在Windows,macOS,Linux计算机上运行,并将某一应用程序及其依赖项打包至一个容器中,这些容器可以在任何支持Docker的环境中运行。容器彼此隔离,但可以通过特定的通道相互传递信息。
Docker提供了一个轻量级的虚拟化解决方案。由于运行在同一计算机上的所有容器共享同一个操作系统内核,避免了启动与维护虚拟机的开销。因此相比于传统的虚拟机,Docker容器更加轻便、快速、容易部署。使用Docker,开发者可以避免在两台计算机上运行效果不一致的问题,容器提供了一致的行为,进而使得应用程序在不同环境的计算机上有相同的运行效果。
官网:https://www.docker.com/
2.2 作用
-
提供统一的运行环境
在生产环境中,很多时候的开发、测试及上线环境都是不一样的,从而导致项目(war或jar)在不同阶段出现很多其它阶段所不存在的奇怪的问题。Docker 容器除了可以提供相同的应用外,还提供了该应用的统一运行环境,确保在任何宿主机 HOST 上都可以运行出相同的结果。
-
便捷的应用迁移
由于 Docker 确保了统一的运行环境,使得应用的迁移更加便捷。无论是物理机、虚拟机、公有云、私有云,Docker 镜像的运行结果都是相同的。用户可以很方便地将一个平台上运行的应用,迁移到另一个平台上,而无需担心运行环境的变化导致应用无法正常运行。
-
快速的启动
传统的虚拟机技术启动应用一般需要数分钟:首先需要启动虚拟机,然后再加载虚拟机操作系统,最后还需要再手工启动应用。而 Docker 容器应用,由于直接运行于宿主机系统中,无需启动操作系统,因此可以做到秒级、甚至毫秒级的启动。
-
更轻松的维护和扩展
Docker 公司及各个开源项目团队一起维护了一大批高质量的官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。
2.3 虚拟机与容器
传统的应用程序在计算机中的运行原理如下:
Docker 容器的本质就是通过容器虚拟技术虚拟出的一台主机,就像虚拟机一样。可以将应用及其运行环境部署在这台虚拟出的主机上运行。但容器与虚拟机又有着本质的不同。
传统的虚拟技术是在物理机的操作系统之上安装一个虚拟机管理程序,例如 VMware、VirtualBox 等。在其管理下可以创建多个虚拟机,每个虚拟机需要安装自己独立的操作系统,而应用就是安装在虚拟机操作系统之上的程序,应用程序通过调用各种命令或库函数来使用其需要的各种系统资源。
对于完全相同的两个应用,其若需要运行在两个虚拟机中,则就需要两套完全相同的虚拟机操作系统与 bins/libs,存在大量的资源占用冗余,造成资源浪费。
Docker 容器运行在 Docker 引擎之上,所有 Docker 容器共享同一个 Docker 引擎,但它们的运行又是相互隔离、互不干扰的。由于 Docker 容器不需要进行虚拟硬件及操作系统,而是共享的宿主机的硬件与操作系统,所以 Docker 容器对系统资源的占用很少,其仅包含运行时必须的一些资源。所有 Docker 容器对于系统资源的使用都是由 Docker 引擎统一进行管理,所以对系统资源的利用率很高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。
2.4 docker系统架构
https://docs.docker.com/get-started/docker-overview/
-
Docker daemon
即 Dockerd,Docker 守护进程,其监听着 Docker APl 请求并管理 Docker对象,例如镜像、容器、网络和卷工守护进程还可以与其他守护进程通信以管理 Docker 服务。
-
Image 镜像
镜像是用于创建 Docker 容器的模板。
-
Container 容器
容器是镜像运行时的实体,一个镜像可以创建多个容器,每个处于运行状态的容器中都包含着一个或多个相关的应用,且它的运行不会干扰到其它容器,因为它们之间是相互隔离的。
-
Registry 注册中心
注册中心实际上就是镜像仓库,用来储存docker镜像。注册中心是公共的,任何人都搜索、下载、提交镜像。
https://hub.docker.com (翻墙)
https://hubgw.docker.com/
二.Docker安装
1.安装
参考官方:https://docs.docker.com/engine/install/centos/
- 卸载旧版本(如果以前安装过旧版本可以先卸载)
yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
- 安装docker工具
yum install -y yum-utils
- 设置镜像仓库
#官方默认的镜像仓库地址
yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo#改为阿里云的镜像仓库地址
yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 安装docker引擎
yum -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin
- 启动docker服务
#启动服务
systemctl start docker#检查版本
docker version
- 测试helloworld(可选)
docker run hello-world
- 卸载docker引擎
#卸载
yum remove docker-ce docker-ce-cli containerd.io#删除目录
rm -rf /var/lib/docker
2.镜像加速
2.1 阿里云镜像加速器
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
2.2 配置一堆加速地址,大力出奇迹
# vim /etc/docker/daemon.json
# 写入以下内容,再执行命令
# systemctl daemon-reload
# systemctl restart docker
########################################################{"runtimes": {"nvidia": {"args": [],"path": "nvidia-container-runtime"}},"registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn","https://cr.console.aliyun.com","https://mirror.ccs.tencentyun.com","https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn/","https://yxzrazem.mirror.aliyuncs.com","https://docker.kubesre.xyz","https://dc.j8.work","https://docker.registry.cyou","https://docker.hlyun.org","https://docker.chenby.cn","https://docker.jsdelivr.fyi","https://docker-mirrors.mjjman.com","https://docker.kubesre.xyz","https://huecker.io","https://dockerhub.timeweb.cloud","https://docker.registry.cyou","https://docker-cf.registry.cyou","https://dockercf.jsdelivr.fyi","https://dockertest.jsdelivr.fyi","https://2a6bf1988cb6428c877f723ec7530dbc.mirror.swr.myhuaweicloud.com","https://docker.m.daocloud.io","https://hub-mirror.c.163.com","https://mirror.baidubce.com","https://your_preferred_mirror","https://dockerhub.icu","https://docker.registry.cyou","https://docker-cf.registry.cyou","https://dockercf.jsdelivr.fyi","https://docker.jsdelivr.fyi","https://dockertest.jsdelivr.fyi","https://mirror.aliyuncs.com","https://dockerproxy.com","https://mirror.baidubce.com","https://docker.m.daocloud.io","https://docker.nju.edu.cn","https://docker.mirrors.sjtug.sjtu.edu.cn","https://docker.mirrors.ustc.edu.cn","https://mirror.iscas.ac.cn","https://docker.rainbond.cc"],"insecure-registries": [],"debug": false,"experimental": false,"features": {"buildkit": true},"builder": {"gc": {"enabled": true,"defaultKeepStorage": "20GB"}}
}
2.2 切换其他镜像源
如:https://register.librax.org/
{"registry-mirrors": ["https://register.librax.org"]
}
三.镜像
1.镜像相关概念
1.1 镜像
镜像是一种轻量级、可执行的独立软件包,也可以说是一个精简的操作系统。
镜像中包含应用软件及应用软件的运行环境。
具体来说镜像包含运行某个软件所需的所有内容,包括代码、库、环境变量和配置文件等。
几乎所有应用,直接打包为 Docker 镜像后就可以运行。
由于镜像的运行时是容器,容器的设计初衷就是快速和小巧,所以镜像通常都比较小,镜像中不包含内核,其共享宿主机的内核;
镜像中只包含简单的 Shel,或没有 shell。
1.2 仓库地址
https://hub.docker.com (翻墙)
https://hubgw.docker.com/
https://register.librax.org/
1.3.镜像分类
- 官方镜像(Docker Official Image)
- 已验证发布者(Verified Publisher)
- Docker公司赞助开发(Sponsored OSS)
- 无认证
1.4 镜像定位
对于任何镜像,都可通过 : 进行唯一定位。
其中 一般称为镜像的版本号。
中有一个比较特殊的版本:latest,如果不指定,默认即为 latest。
2.镜像相关命令
2.1 docker pull
作用:从镜像仓库拉取镜像
用法:
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
可以用版本号拉取
也可以用 digest 拉取
digest:即摘要 ,是镜像内容的一个 Hash 值,即所谓的 Content Hash(内容散列)。只要镜像内容发生了变更,其内容散列值就一定会发生改变。也就是说,一个镜像一定创建完毕,其 digest 就不会发生改变了,因为镜像是只读的。
Docker 默认采用的 Hash 算法是 SHA256,即 Hash 值是一个长度为 256 位的二进制值。
Docker 使用 16 进制表示,即变为了长度为 64 位的字符串。
摘要的主要作用是区分相同 : 的不同镜像。
例如镜像 xxx:2.8 在生产运行过程中发现存在一个 bug。现对其进行了修复,并使用原标签将其 push 回了仓库,那么原镜像被覆盖。但生产环境中遗留了大量运行中的修复前镜像的容器。此时,通过镜像标签已经无法区分镜像是修复前的还是修复后的了,因为它们的标签是相同的。此时通过査看镜像的 digest 就可以区分出修改前后版本,因为内容发生了变化,digest一定会变。
为了确保再次拉取到的是修复后的镜像,可通过 digest 进行镜像拉取。其用法是:docker pull @
2.2 docker images
查看镜像列表
-q :只显示镜像id
2.3 docker rmi
作用:删除镜像,根据 repository:tag 或者 image id 删除
删除全部镜像:
docker rmi $(docker images -q)
如果镜像已有创建的容器,则用 -f 参数
docker rmi -f hello-world
2.4 docker search
作用:从 DockerHub 搜索镜像
AUTOMATED:该镜像是否为自动化镜像
DockerHub 连接 GitHub或者 Bitbucket平台,并根据其中的Dockerfile 构建的镜像,这种构建镜像的方式也成为Trusted Build。
2.5 docker save
作用:把一个或多个镜像保存到本地tar文件,也可输出到标准输出流
[root@localhost ~]# docker save --helpUsage: docker save [OPTIONS] IMAGE [IMAGE...]Save one or more images to a tar archive (streamed to STDOUT by default)Aliases:docker image save, docker saveOptions:-o, --output string Write to a file, instead of STDOUT
除了用 -o 选项,也可以使用输出重定向 >
2.6 docker load
作用:从tar文件或标准输入流加载镜像
[root@localhost ~]# docker load --helpUsage: docker load [OPTIONS]Load an image from a tar archive or STDINAliases:docker image load, docker loadOptions:-i, --input string Read from tar archive file, instead of STDIN-q, --quiet Suppress the load output
删除掉对应的 image,再测试 load
# 使用 < 输入重定向也可以
docker load < xxx.tar
3.镜像分层
Docker 镜像由一些松耦合的只读镜像层组成,Docker Daemon 负责堆叠这些镜像层,并将它们关联为一个统一的整体,即对外表现出的是一个独立的对象。
通过 docker pull 命令拉取指定的镜像时,每行就代表下载完毕了一个镜像层。
优点:
采用这种分层结构的优势很多:每个分层都是只读的,所有对分层的修改都是以新分层的形式出现,并不会破坏原分层内容,而且,每个分层只记录变更内容,所以有利于节省存储空间等。
分层结构的最大的好处是:在不同镜像间实现资源共享,即不同镜像对相同的下层镜像的复用。对于 docker pul 命令,在拉取镜像前会先获取该镜像的所有 ImagelD,然后在本地查找是否存在这些分层,如果存在,则不再进行拉取,而是共享本地的该分层,这样就节约了存储空间与网络带宽,提升了拉取效率。
镜像FS构成:
一个 docker 镜像的文件系统 FS 由多层只读的镜像层组成,每层都完成了特定的功能而这些只读镜像层根据其位置与功能的不同可分为两类:基础镜像层与扩展镜像层。
一旦镜像运行了起来就形成了容器,而容器就是一个运行中的 Linux 系统,其也是具有文件系统的。容器的这个文件系统是在 docker 镜像最外层之上增加了一个可读写的容器层,对文件的任何更改都只存在于容器层。因此任何对容器的操作都不会影响到镜像本身。容器层如果需要修改某个文件,系统会从容器层开始向下一层层的查找该文件,直到找到为止。任何对于文件的操作都会记录在容器层。
例如,要修改某文件,容器层会首先把在镜像层找到的文件 copy 到容器层,然后再进行修改。删除文件也只会将存在于容器层中的文件副本删除。
可以看出,Docker 容器就是一个叠加后的文件系统,而这个容器层称为 Union File System,联合文件系统。
4.多架构镜像
Multi-architecture lmage,即多架构镜像,是某 中的某 镜像针对不同操作系统系统架构的不同镜像实现。
即多架构镜像中包含的镜像的:都是相同的,但它们针对的操作系统/系统架构是不同的。
无论用户使用的是什么操作系统/系统架构,其通过 dockerpull 命令拉取到的一定是针对该操作系统/系统架构的镜像,无需用户自己考虑操作系统/系统架构问题。Docker Hub 能够根据提交 pu 请求的 Docker 系统的架构自动选择其对应的镜像。
在 Docker Hub 中,镜像的多架构信息保存在 Manifest 文件中。在拉取镜像时,Docker会随着 pull 命令将当前 Docker 系统的 0S 与架构信息一并提交给 Docker Hub。Docker Hub 首先会根据镜像的 : 查找是否存在 Manifest。如果不存在,则直接查找并返回 : 镜像即可;如果存在,则会在 Manifest 中查找是否存在指定系统/架构的镜像。如果存在该系统/架构,则根据 Manifest 中记录的地址找到该镜像的位置。
Docker Hub官网查看某个镜像
使用命令查看
四.容器
1.容器基础
从 docker run 看起
docker run 的流程:
更详细的流程:
查看本机的容器:
Docker 容器存在的意义就是为了运行容器中的应用,对外提供服务,所以启动容器的目的就是启动运行该容器中的应用,而容器中的应用运行完毕后,容器就会自动终止。
如果不想让容器启动后立即终止运行,则就需要使容器应用不能立即结束,通常采用的方式有两种:使应用处于与用户交互的状态或等待状态。
2.容器相关命令
2.1 docker run
作用:从镜像创建并运行一个新的容器。参数较多,用 --help 查看。
对于容器的运行,有两种运行模式:交互模式与后台分离模式,下面通过运行 ubuntu 与 tomcat 来演示这两种运行模式的不同。
2.1.1 以交互模式运行ubuntu
# 先 pull ubuntu
docker pull library/ubuntu:22.04
运行容器,发现状态为 exited
因为 ubuntu容器是一种 linux系统,其中并没有什么应用,所以一旦运行就会结束
以交互模式运行
如果不加 /bin/bash,也可以运行成功,但是有的容器会运行失败,原因在 Dockerfile文件
Dockerfile文件在 github上,打不开,此处截图看看大概意思。
2.1.2 以交互模式运行 tomcat
# 先 pull tomcat
docker pull tomcat:8.5.32
# docker pull register.librax.org/library/tomcat:8.5.32
分别运行以下命令测试
测试1:
docker run --name mytomcat -it tomcat:8.5.32 /bin/bash
# 此时运行了tomcat的容器,并以交互模式进入了容器
# 但是tomcat进程启动了吗?
测试2:
docker run --name mytomcat2 -it tomcat:8.5.32
# 此时运行了tomcat的容器,并以交互模式进入了容器,发现tomcat进程在启动
# 但是可以通过浏览器访问tomcat吗?
查看容器
查看 tomcat 在 github 的 Dockerfile
测试3:
docker run --name mytomcat3 -it -p 8081:8080 tomcat:8.5.32
# -p(小写) : Publish a container's port(s) to the host
# 在宿主机中暴露端口,相当于端口映射
此时按 ctrl + c 退出容器,tomcat 进程会停止。可以按 ctrl + p + q 退出,此时进程还在(停止可用 docker stop)
通过浏览器访问
测试4:
docker run --name mytomcat5 -it -P tomcat:8.5.32
# -P(大写) : Publish all exposed ports to random ports
此时响宿主机暴露的为随机端口
2.1.3 以后台分离模式运行 tomcat
docker run --name mytomcat6 -d -p 8082:8080 tomcat:8.5.32
# -d : Run container in background and print container ID
2.1.4 tomcat版本问题
从 8.5.50 开始,目录结构略有变化,自行测试,此处略…
2.2 docker create
作用:创建新容器。与 dockers run 类似,但是只创建容器并不启动。
2.3 docker ps
作用:列出容器信息
-
-a: 显示所有容器,包括未启动的
-
-q:显示容器id(在全部删除容器时有用)
-
-n:显示最后运行的若干个容器(要指定数字)
-
-l:显示最后一个运行的容器
-
-s:显示容器大小
2.4 docker exec
作用:在已运行的容器中执行一个命令行
- -i: 交互模式
- -t:申请伪终端
- -w:指定进入容器时的工作目录
运行 /bin/bash 或者 /bin/sh 等在容器中运行 shell,相当于进入了容器
注:使用 docker exec 进入容器后,再退出时,并不会结束容器进程。
也可以在容器中运行其他命令,如查看ip等
2.5 docker attach
作用:附加标准输入流、输出流、错误流到已运行的容器。
测试1:
启动一个ubuntu容器做测试
用 docker attach 附加到该容器,发现退出容器后,容器也会停止
原因分析:查看ubuntu的Dockfile文件,发现其最后执行的是 bash 命令,而 attach是附加到此容器的进程,当按了 ctrl +d 或执行 exit 时会结束该进行,所以容器也会停止。
测试2:
attach 到 tomcat 容器时:
此时按 ctrl + c ,会发现接收到了一堆日志,并且tomcat容器停止了
原因分析:查看tomcat 的Dockerfile,发现最后是运行了 catalina.sh ,而这个脚本的作用是记录tomcat 启停信息到 logs/catalina.xxxx.log 日志中,启动tomcat 容器时,已经记录完毕了启动日志,此时用 attach 附加到容器就会出现只有个光标显示的情形,有点像 tail -f 的作用。然后按 ctrl + c 相当于是结束了tomcat,并且记录停止日志,所以能看到tomcat停止的信息,以及最后tomcat容器会停止。
上述操作就跟执行以下命令,并且按 ctrl + c 是一个作用
docker run --name mytomcat2 -it -p 8081:8080 tomcat:8.5.32
2.6 docker top
作用:显示正在运行的某个容器的进程信息
2.7 docker start 等
start | stop | restart | kill | pause | unpause
# 停止所有容器
docker stop $(docker ps -q)
2.8 docker logs
作用:获取容器的日志(与容器对应的Dockerfile最后运行的命令有关)
- -f:监听日志(与 tail -f 类似)
2.9 docker cp
作用:在容器和宿主机之间拷贝文件或目录(已停止的容器也可以)
# 从宿主机拷贝文件到tomcat容器
docker cp test.html mytomcat:/usr/local/tomcat/webapps/ROOT# 从tomcat容器拷贝文件到宿主机
docker cp mytomcat:/usr/local/tomcat/webapps/ROOT/index.jsp ./
2.10 docker rm
作用:删除一个或多个容器
- -f :强制删除,用于删除正在运行的容器
# 删除所有容器
docker rm -f $(docker ps -qa)
2.11 docker commit
作用:从容器创建新的镜像
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
-
-a : 指定作者
-
-m : 指定提交时的message
测试1:
centos:7 这镜像中只安装了一部分命令,希望创建出带有 net-tools 的 centos7 镜像
注:如果不指定 : 则会变为“玄虚镜像”
docker inspect 查看镜像信息
测试2:
tomcat:8.5.50 这个镜像默认没有欢迎页,希望创建出带有欢迎页的 tomcat 镜像
2.12 docker export / import
docker export 作用:把容器导出成为 tar 文件
- -o : 输出到文件,用以代替标准输出流
docker import 作用:把 tar 文件导入成为镜像
注:如果不指定 : 则会变为“玄虚镜像”
其他:
对比 docker export 与 docker save
- export 作用于容器,save 作用于镜像,但它们导出的结果都为tar 文件。
- export 一次只能对一个容器进行导出,save 一次可以对多个镜像进行导出。
- export 只是对当前容器的文件系统快照进行导出,其会丢弃原镜像的所有历史记录与元数据信息,save 则是保存了原镜像的完整记录。
对比 docker import 与 docker load
- import 导入的是容器包,load 加载的是镜像包,但最终都会恢复为镜像
- import 恢复为的镜像只包含当前镜像一层;load 恢复的镜像与原镜像的分层是完全相同的。
- import 恢复的镜像就是新构建的镜像,与原镜像的 ImagelD 不同;load 恢复的镜像与原镜像是同一个镜像,即 ImagelD 相同。
- import 可以为导入的镜像指定与;load 加载的镜像不能指定与,与原镜像的相同。
通过 docker history 查看镜像的历史信息:
对比 docker export + docker import 与 docker commit
- 相同点: docker export+docker import 会将一个容器变为一个镜像,docker commit 也可以将一个容器变一个镜像。
- 不同点: docker export+docker import 恢复的镜像仅包含原容器生成的一层分层;docker commit 生成的镜像中包含容器的原镜像的所有分层信息。(可用 docker history 查看)
五.docker system 命令集
docker system 属于管理类命令
可使用 docker --help 查看 (docker 命令本身也是命令集)
继续查看 docker system --help
继续查看具体命令,如: docker system df -help
docker system df : 查看磁盘占用情况 (-v :显示更详细的情况)
docker system prune:清除未使用的数据
ImagelD 不同;load 恢复的镜像与原镜像是同一个镜像,即 ImagelD 相同。
- import 可以为导入的镜像指定与;load 加载的镜像不能指定与,与原镜像的相同。
通过 docker history 查看镜像的历史信息:
[外链图片转存中…(img-79LoW7C9-1738833413449)]
对比 docker export + docker import 与 docker commit
- 相同点: docker export+docker import 会将一个容器变为一个镜像,docker commit 也可以将一个容器变一个镜像。
- 不同点: docker export+docker import 恢复的镜像仅包含原容器生成的一层分层;docker commit 生成的镜像中包含容器的原镜像的所有分层信息。(可用 docker history 查看)
五.docker system 命令集
docker system 属于管理类命令
可使用 docker --help 查看 (docker 命令本身也是命令集)
[外链图片转存中…(img-yeXvgm5A-1738833413449)]
继续查看 docker system --help
[外链图片转存中…(img-XIswORa9-1738833413449)]
继续查看具体命令,如: docker system df -help
[外链图片转存中…(img-5K0OLMWu-1738833413449)]
docker system df : 查看磁盘占用情况 (-v :显示更详细的情况)
[外链图片转存中…(img-0zZL7TsT-1738833413449)]
docker system prune:清除未使用的数据