容器技术:镜像管理、容器管理、容器状态(三)
8. 镜像管理
8.1 了解Docker镜像
- Docker镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需要的所有内容。我们将应用程序、配置打包成一个成型的、可交付、可部署的运行环境,包括代码、运行时所需要的库、环境变量和配置文件等,这个大包好的运行环境就是image镜像文件。
- 只有通过镜像文件才能生成Docker容器实例。
8.1.1 Docker镜像原理
Docker 中一个 Ubuntu 镜像为什么只有几十M,而一个 Ubuntu 操作系统的 iso 文件要好几个G?在开始了解底层原理之前,先来看一下Linux的文件管理系统。Linux文件系统主要由boofts和rootf两部分组成,其中:
- bootfs:包含bootloader(引导加载程序)和 kernel(内核)
- rootfs:root 文件系统,包含的 Linux系统中的 /dev、/proc、/bin、/etc 等标准目录和文件。
不同的Linux发行版,bootfs基本是一样的,只是 rootfs 不同!
8.1.2 UnionFS联合文件系统
Union文件系统(UnionFS)是一种分层的、轻量级的、高性能的文件系统,它是Docker镜像的基础,并且支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂在到同一个虚拟文件系统下。镜像可以通过分层来进行继承,基于基础镜像,可以制作各种具体的应用镜像。
Union文件系统的特性:一次性同时加载多个文件系统,但是从外面来看,只能看到一个文件系统;联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有地层的文件和目录。
8.1.3 Docker镜像分层
Docker镜像是分层构建的,例如在Dockerfile文件中每条指令都会新建一个层。以下面Dockerfile指令为例:
FROM ubuntu:20.04 #基础镜像
COPY . /app#复制文件
RUN make /app #编译文件
CMD python /app/app.py #入口文件
以上四条指令,在每一层上只记录本层所做的更改,而且这些层是只读层。当启动一个容器,Docker只会在最顶部添加读写层,在容器内作的所有更改(写日志、修改、删除文件等,都保存到读写层内),一般称该层为容器层,如下图所示:
容器(container)和镜像(image)的最主要区别就是容器加上了顶层的读写层。所有对容器的修改都发生在此层,镜像并不会被修改(COW copy-on-write技术)。每个容器都有自己的读写层,因此多个容器可以使用同一个镜像。另外,容器被删除时,其对应的读写层也会被删除。
基于同一个base镜像创建多个容器,内存里只需要加载一份base镜像。
验证Dockerfile中的操作对于镜像分层的影响
在镜像构建过程中需要向镜像写入数据的时候会产生分层,一个写操作指令产生一个分层。
查看该镜像的分层结构信息,所有的Docker镜像都起始于一个基础镜像层,因此第一个layer为dockerfile中指定的基础镜像层,然后dockerfile中有多少个写指令,就会有多少个lay。 这里是三个layer,跟dockerfile中刚好对应上。
具体操作的背后流程
8.1.4 Docker镜像加载原理
第一层:在我们输入docker pull centos的时候,第一步先加载宿主机的linux内核。
linux在刚启动的时候会加载bootfs(包含bootloader和kernel,bootloader主要的作用是引导加载kernel)、文件系统。
第二层:当内核加载完成后,docker进行拉取基础镜像也就是linux发行版
Rootfs:在bootfs之上包含的就是典型linux系统中的/dev、/proc、/bin、/etc等标准目录和文件。
第三、四层:使用centos提供的软件管理(yum)这个镜像有什么作用就利用yum安装什么软件。例如安装tomcat。
前四层是只读镜像,不能修改。且技术是通过UnionFS联合文件系统整合成一个文件系统。
第五层:运行容器后可读可写。
docker镜像小的原因是docker镜像只有rootfs和其他镜像层,共用宿主机的linux内核(bootfs),所以很小。
8.2 镜像管理命令
命令 | 说明 |
---|---|
docker images | 查看镜像列表 |
docker search | 搜索镜像,优选官方,stars数量多的 |
docker pull | 拉取镜像(下载) |
docker push | 推送镜像(上传) |
docker save | 导出镜像 |
docker load | 导入镜像 |
docker rmi | 删除镜像 |
docker tag | 给镜像打标签 |
8.3 查看镜像
docker images
- repository:源/软件名
- tag:软件版本
- image id:镜像id
- created:镜像创建时间
- size:镜像大小
8.4 搜索镜像
docker search 镜像名
- NAME: 镜像仓库源的名称
- DESCRIPTION: 镜像的描述
- OFFICIAL: 是否 docker 官方发布
- stars: 类似 Github 里面的 star,表示点赞、喜欢的意思。
- AUTOMATED: 自动构建。
8.5 下载镜像
docker pull 镜像名
docker pull 镜像名:版本
- 下载nginx最新版本 nginx:latest
- 下载nginx最新稳定的版本 nginx:stable
- 下载指定的版本 nginx:1.21.1
- 下载个人制作的镜像 kasmweb/nginx
8.6 上传镜像
以后也自己搭建镜像仓库,把镜像上传到docker hub上
8.7 导出镜像
docker save 镜像id(单个或多个)或镜像名 -o 压缩包名字
Tips:如果上面直接填镜像名nginx,会匹配两个,都会打包在一个文件中。
8.8 导入镜像
docker load -i 镜像压缩包
Tips:如果使用镜像id导出镜像,然后再导入镜像,镜像的名字为none。
8.9 删除镜像
docker rmi 镜像id
Tips:如果被删除的镜像有容器正在使用,无法删除,需先删除容器再进行删除镜像!
8.10 镜像标签
docker tag 标签内容
Tips:可以用于给镜像起名,使用这个新名字的镜像启动容器。把这个镜像通过修改tag可以上传本地镜像仓库中。
9. 容器管理
9.1 容器管理命令
命令 | 说明 |
---|---|
docker ps | 查看容器列表 -a查看所有容器 |
docker run | 创建并运行容器 |
docker create | 创建容器 |
docker start | 启动容器 |
docker stop | 停止容器,本质就是向容器中pid为1的进程发出结束信号,kill命令 |
docker restart | 重启容器 |
docker kill | 强制停止容器,本质就是向容器中pid为1的进程发出强制结束信号,kill -9命令 |
docker rm | 删除容器 |
docker logs | 查看Nginx容器访问日志,加参数-f可持续查看 |
docker port | 查看容器网络映射情况 |
docker cp | 宿主机与容器互传数据 |
docker exec | 在运行的容器中执行命令 |
docker commit | 创建镜像 |
docker rename | 容器重命名 |
9.2 查看容器列表
docker ps(加上-a参数就是包括未运行的容器)
CONTAINER ID: 容器 ID。
IMAGE: 使用的镜像。
COMMAND: 启动容器时运行的命令。
CREATED: 容器的创建时间。
STATUS: 容器状态。
- created(已创建)
- restarting(重启中)
- running(运行中)
- removing(迁移中)
- paused(暂停)
- exited(停止)
- dead(死亡)
PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。
NAMES: 自动分配的容器名称。
Tips:列出所有创建的容器ID:docker ps -a -q
9.3 创建并运行容器
docker run 参数 镜像名(加上--name可指定容器名称)
docker run 参数 镜像名:版本的TAG
上面参数-d是指定容器运行在后台,-p是指定端口映射(主机端口:容器端口)
9.4 创建容器
docker create --name 容器名称 镜像名:镜像TAG(加上--name可指定容器名称)
9.5 启动容器
docker start 容器ID/容器名
9.6 停止容器
docker stop 容器ID/容器名
9.7 重启容器
docker restart 容器ID/容器名
9.8 强制停止容器
docker kill 容器ID/容器名
9.9 删除容器
docker rm 容器ID/容器名
Tips:使用-f参数,即使容正在运行当中,也会被强制删除掉。
9.10 指定端口映射
#方式1:本地端口8999映射到容器80端口
docker run -d -p 8999:80 --name nginx-01 nginx:1.21.1
#方式2:本地IP:本地端口:容器端口
docker run -d -p 172.16.1.81:8080:80 --name nginx-02 nginx:1.21.1
#方式3:本地IP:本地随机端口:容器端口
docker run -d -p 172.16.1.81::80 --name nginx-03 nginx:1.21.1
#方式4: 本地IP:本地端口:容器端口/协议(默认为TCP)
docker run -d -p 172.16.1.81:9000:80/udp --name nginx-04 nginx:1.21.1
#方式5:一次性映射多个端口和协议
docker run -d -p 12306:80/tcp -p 443:443/tcp -p 54:54/udp --name nginx-05 nginx:1.21.1
端口映射的背后会添加iptables规则
9.11 查看容器访问日志
docker logs 容器名/容器ID(加参数-f可持续查看)
9.12 查看容器映射的网络情况
docker port 容器名/容器ID
9.13 宿主机与容器传输数据
宿主机 --> 容器
docker cp 本地目录/文件 容器名称/ID:路径
容器 --> 宿主机
docker cp 容器名称/ID:目录/文件 本地路径
9.14 运行的容器中执行命令
docker exec 选项 命令
比较常用的还是进入到容器里面,-i进入交互模式,一般与-t一起使用,-t是分配一个终端。
9.15 创建镜像
将bird小游戏传到容器里并解压,访问测试,最后将该容器创建镜像。
docker commit 容器名 新镜像名:镜像TAG
使用新镜像创建并运行容器,最后进行访问测试
9.16 容器重命名
docker rename 容器名 新容器名
9.x 常用参数
参数 | 作用 |
---|---|
-d | 容器后台运行 |
-p | 端口映射 |
-v | 挂载数据卷 |
-i | 进入交互模式,一般与-t一起使用 |
-t | 分配一个终端 |
--name | 给容器指定个名字 |
--cpus | 限制 CPU 配额 |
--memory,-m | 限制内存配额 |
--pids-limit | 限制容器的 PID 个数 |
启动一个 1 核 2G 的容器,并且限制在容器内最多只能创建 1000 个 PID
docker run -it --cpus=1 -m=2048m --pids-limit=1000 tengine:latest
10. 容器状态
10.1 容器进程信息
docker top 容器名/容器ID
通过查询信息查找容器在宿主机的进程信息和进程树。
10.2 容器占用资源情况
docker stats 容器名/容器ID
- CONTAINER ID:容器ID
- NAME:容器名称
- MEM USAGE /LIMIT:容器占用的内存大小 /内存限制(默认没有限制)
- NET I/O:网络数据传输 输入/输出
- BLOCK I/O:磁盘读写
- PIDS:容器里的进程和线程总数量
10.3 查看容器各项指标信息
docker inspect 容器名/容器ID
可以通过JQ工具进行取json数据信息,可以配合json解析工具来看json数据的层次关系,方便写JQ语句。
取容器的状态
取容器名称
取容器IP信息
Tips:取其他信息根据语句进行修改,然后测试,不再一 一列举。