docker 技术原理
目的:
- 资源隔离: 隔离各个服务使用的资源
- 打包环境: 减小部署的难度,一次打包,多次使用
- 资源控制: 控制各个服务的资源,防止相互影响
使用的主要技术有:
- linux namespce 资源隔离
- overlayfs 文件系统
- cgroup 资源控制
- linux bridge,veth,vxlan. 网络虚拟化(overlay)
1. linux namespace
资源的隔离:
c++ namespace , namespace 之间隔离函数的命名空间
1 |
|
linux namespace :
system api:
clone()
setns()
unshare()
#define _GNU_SOURCE #include <sched.h> int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, void *newtls, pid_t *ctid */ );
flag | namespace | 效果 |
---|---|---|
CLONE_NEWNS | mount namespace | 挂载的文件系统互不可见 |
CLONE_NEWIPC | ipc namespace | ipc 队列互不可见 |
CLONE_NEWUTS | 主机名uts namespace | 主机名互互不相同 |
CLONE_NEWPID | pid namespace | 进程互不可见 |
CLONE_NEWNET | network namespace | 网络隔离 |
CLONE_NEWUSER | user namespce | 用户隔离 |
CLONE_NEWCGROUP | cgroup namespace | 资源控制隔离 |
2. overlayfs
分层文件系统
1 | cd /tmp |
3. cgroup (control grop) 控制组
cgroup 挂载为文件系统
查看 cgroup 挂载
mount -l |grep cgroup
ls /sys/fs/cgroup/
blkio 块设备io cpu cpu 使用率、调度 cpuacct cpu 目前使用率 cpuset cpu绑核 devices 限制使用的设备 freezer 恢复或者挂起 cgroup 中的人物 hugetlb 透明大页 memory 内存限制 net_cls 标记流量 net_prio 设置网络优先级
cgroup 中的概念:
task: 系统进程
control group: 控制组
hierarchy: 层级
subsystem: 子系统
1 | mkdir -p /sys/fs/cgroup/cpu/mytask |
4. linux 虚拟网络设备
两个 namespace 之间的网络是隔离的。
4.1 veth pair 设备
veth 设备能够连接两端,就想 linux pipe 一样,向一头 veth 写数据,另一端可以读取数据
1 | 10.10.0.1 10.10.0.2 |
1 | ip netns add ns1 |
4.2 网桥设备(交换机)
1 | +-----------+ +-------------+ |
1 | ip netns add ns1 |
4.3 vxlan 网络
传统的 vlan 网络 vid 支持支持 12 位 2^12=4096,仅支持 4096 个网络,而 vxlan 网络的 vid 支持 24 位,可以支持 1600 万以上的网络。
vxlan 将 IP 层的数据包封装为带有 vxlan 头部的 UDP 数据包,再次发送出去.
vxlan 其实是工作在第三层(udp) 的第二层协议(ip),因为 vxlan 模拟了 ip 层的数据
1 | # 四层网络协议栈 |
5. docker 使用
5.1 docker 打包应用
编写 Dockerfile 文件,然后在 Dockerfile 所在目录使用 docker build . -t mytag
, 注意打包的时候有个点,表示打包的上下文路径。这里的上下文路径表示的是docker打包时会将这个上下文路径里面的所有内容都发送给dockerd,之后再由 Dockerfile 中的指令操作这些文件,生成 docker 镜像。
1 | FROM busybox |
常见的 Dockerfile 指令有:
指令 | 功能 |
---|---|
FROM | 引入基础镜像 |
ADD | 添加文件,可以自动解压,修改权限等,较为复杂,不建议使用 |
COPY | 拷贝文件,保持文件权限 |
ENV | 指定环境变量 |
表示这个dir是卷,如果运行时没有指定挂载的目录,会使用匿名卷 | | RUN | 打包时执行命令 | | CMD | 运行时的命令 | | ENTRYPOINT | 运行时的入口点位置 |
ENTRYPOINT 和 CMD 格式 :
执行命令有两种形式,一种是使用 exec 模式,跟到参数是一个参数列表;另一种使用 shell 方式,直接跟命令字符串。
exec 格式:
1
2CMD ['ls', '-l']
ENTRYPOINT ['ls', '-l']
shell 格式, shell 格式会转换为 /bin/sh -c "command ...",执行可以读取环境变量,exec格式无法默认无法读取环境变量 , 需要使用 sh
, 比如 ['/bin/sh', '-c', 'command']
1 | CMD ls -l |
CMD
为 ENTRYPOINT
添加参数
test.sh 1
2
echo $@
默认向 test.sh 传入 ls
的参数,如果手动指定,则运行手动指定的
1 | ENTRYPINT ["./test.sh"] |
5.2 常见的 docker 命令
1 | docker ps -a # 查看所有的 docker 容器 |
reference
docker 使用的最佳实践
TODO: docker 精简镜像 https://mp.weixin.qq.com/s/S1Ib08SpQbf1SCbCutUoqQ
阅读资料
docker namespace 上 docker namespace 下 docker aufs docker cgroup docker devicemapper k8s/docker 排障 linux namespace api docker control group docker namespace docker 与 git overlayfs 实现 简单的 docker https://itnext.io/breaking-down-containers-part-1-namespaces-9668b86d003d bocker
docker 网络转发过程 https://www.jianshu.com/p/91002d316185
https://unix.stackexchange.com/questions/465669/what-is-the-nsfs-filesystem