一、Docker的优点
docker 主要解决的问题就是程序开发过程中编译和部署中遇到的环境配置的问题。
1.1 Docker与其他虚拟机层次结构的区别**
运行程序重点关注点在于环境。
VM虚拟机是基于Hypervisor虚拟化服务运行的。
Docker是基于内核的虚拟化技术实现的。
1.2 Docker的技术优势
-
隔离性 Linux namespace
与c++中namespace作用差不多,但这里是指kernel namespace。使用pid、net、ipc、user等namespace将container的进程、网络、消息、文件系统和用户空间隔离开。
-
控制组 - Control Groups (cgroups) 可配额、可度量
cgroups可以限制blkio、cpu、cpuset、devices、memory、net_cls子系统的资源。
-
便携性:
在Docker中,初始化时也是将 rootfs 以readonly方式加载并检查,然而接下来利用 union mount 的方式将一个 readwrite 文件系统挂载在 readonly 的rootfs之上, 这样一组readonly和一个writeable的结构构成一个container的运行时态, 每一个FS被称作一个FS层。如下图:
二、Docker 架构
Docker 结构框图如下
Docker对使用者来讲是一个C/S模式的架构,而Docker的后端是一个非常松耦合的架构,模块各司其职,并有机组合,支撑Docker的运行,如下图所示:
用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者。
而Docker Daemon作为Docker架构中的主体部分,首先提供Server的功能使其可以接受Docker Client的请求;而后Engine执行Docker内部的一系列工作,每一项工作都是以一个Job的形式的存在。
Job的运行过程中,当需要容器镜像时,则从Docker Registry中下载镜像,并通过镜像管理驱动graphdriver将下载镜像以Graph的形式存储;当需要为Docker创建网络环境时,通过网络管理驱动networkdriver创建并配置Docker容器网络环境;当需要限制Docker容器运行资源或执行用户指令等操作时,则通过execdriver来完成。
Docker 客户端和服务器间通讯实例
Docker Client可以通过以下三种方式和Docker Daemon建立通信:tcp://host:port,unix://path_to_socket和fd://socketfd。
Docker Client发送容器管理请求后,由Docker Daemon接受并处理请求,当Docker Client接收到返回的请求相应并简单处理后,Docker Client一次完整的生命周期就结束了。当需要继续发送容器管理请求时,用户必须再次通过docker可执行文件创建Docker Client。
查看docker的client+server架构
tn@itec:~$ docker version
Client:Version: 24.0.5API version: 1.43Go version: go1.20.3Git commit: 24.0.5-0ubuntu1~20.04.1Built: Mon Aug 21 19:50:14 2023OS/Arch: linux/amd64Context: default
Server:Engine:Version: 24.0.5API version: 1.43 (minimum version 1.12)Go version: go1.20.3Git commit: 24.0.5-0ubuntu1~20.04.1Built: Mon Aug 21 19:50:14 2023OS/Arch: linux/amd64Experimental: truecontainerd:Version: 1.7.2GitCommit:runc:Version: 1.1.7-0ubuntu1~20.04.2GitCommit:docker-init:Version: 0.19.0GitCommit:
演示如下:
Linux下“一切皆文件”,这个也不例外,/var/run/docker.sock就是client和server交互的中间文件
我们可以向/var/run/docker.sock发送请求,也能达到docker ps、docker images这样的效果。
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json |jq
curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json |jq
三、Docker的基本操作指令
指令交互流程图如下:
创建一个Dockerfile:
FROM ubuntu:16.04
# 防止在非交互模式下的TZ数据错误
ARG DEBIAN_FRONTEND=noninteractive# 更新并安装基本工具
RUN apt-get update && apt-get install -y \lsb-release \gnupg2 \curl \&& rm -rf /var/lib/apt/lists/*# 设置默认工作目录
WORKDIR /root# 运行bash
CMD ["bash"]
创建一个镜像:
docker build -t i/ubuntu16.04:v1 .
创建一个容器并运行:
#!/bin/bash
docker run -it \--rm \-v $(pwd)/:/opt/ws/ \-v /home:/home \-v /etc/localtime:/etc/localtime:ro \-v /tmp/.X11-unix:/tmp/.X11-unix \-e DISPLAY=unix$DISPLAY \-w /opt/ws/ \--hostname ubuntu16 \
i/ubuntu16.04:v1
停止容器:
docker stop $(NAME)
运行容器:
docker start $(NAME)
提交当前容器至镜像:
docker commit -a "i" -m "first commmit" upbeat_babbage i_ubuntu16.04:v1
给提交的docker镜像打tag:
docker tag i/ubuntu16.04:v1 hub.itec.com/embedded/release_test:v1
将打完的docker镜像提交到docker镜像仓库:
登录: docker login https://hub.itec.com/
docker push hub.itec.com/embedded/release_test:v1
从docker镜像仓库拉去镜像:
docker pull hub.itec.com/embedded/release_test:v1
将一个镜像导出为tar包:
docker save hub.itec.com/embedded/release_test:v1 -o release_test.tar
将tar包导入至docker镜像
docker load -i release_test.tar
tips:
docker run :根据镜像创建一个容器并运行一个命令,操作的对象是 镜像;
docker exec :在运行的容器中执行命令,操作的对象是 容器。
四、 Docker镜像跨平台使用
为什么在ARM64架构上打包的docker镜像能在X86上面能加载并运行。
1) 通过查看/proc/sys/fs/binfmt_misc/注册表,查询内核是否支持arm64架构。
2) 进一步确认使用的虚拟机解释器
tn@itec:~$ cat /proc/sys/fs/binfmt_misc/qemu-m68k
enabled
interpreter /usr/bin/qemu-m68k-static
flags: OCF
offset 0
magic 7f454c4601020100000000000000000000020004
mask ffffffffffffff00fffffffffffffffffffeffff
tn@itec:~$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags: OCF
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff
从 Docker 19.03 开始,Docker 引入了对 QEMU 的支持,用于在容器中模拟其他架构的 CPU。
在之前的版本需要运行模拟镜像:
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
在docker build和pull 中指定platform有什么意义?
1) 在build时指定平台的意义完全是构建什么架构的镜像。如果同时指定多个架构,那么将构建多个镜像。
2) 在pull中指定架构,是指在仓库中找到对应架构的镜像,pull到本地docker。
如果在arm64平台上还是不能运行X86的镜像,怎么办?
1) 加载驱动
insmod /usr/lib/modules/5.10.110-rockchip-rk3588/kernel/fs/binfmt_misc.ko
2)添加注册
echo ':qemu-x86:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-x86_64-static:OCF' > register