知识点回顾
Docker命令docker run/start/restart/kill/execdocker inspect/top/logsdocker save/export/importdocker build/tag/pushDockerfile写法
FROMMAINTAINERRUNUSERVOLUMEWORKDIRCMD 每个容器只能执行一条CMD命令,多个CMD命令时,只最后一条被执行ENVADD/COPYEXPOSTENTRYPOINT 配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。拆解docker/容器
容器本质来说是chroot+分层文件系统+ 配对
容器镜像通过UnioNFS(联合文件系统)将不同的目录挂载到同一个虚拟文件系统下 ,创建一个新的层叠加上去作为一个可读可写层,然后通过change root(chroot dir/)对根目录进行一个限制,在通过namespace命名空间对内核全局资源进行封装,达到资源隔离的目的。Cgroup技术对一组进程的cpu,内存,磁盘io, 带宽等资源进行限制。
解压镜像
root@ubuntu:~# docker pull busybox root@ubuntu:~# docker image save busybox -o busybox.tar root@ubuntu:~# mkdir -p /var/lib/fmeng/busybox root@ubuntu:~# tar -xf busybox.tar -C /var/lib/fmeng/busybox/ tar xf layer.tar chroot /var/lib/fmeng/busybox/75fae911f860e3d9d6898b7af34a3b96374dcb33ee9d8b7a6230b74d4a1f30d4/ /bin/sh
OverlayFS文件系统
https://zh.***.org/zh-cn/OverlayFSOverlayFS是一个面向Linux的文件系统服务,其实现一个面向其他文件系统的联合挂载。Overlayfs的基本理念
只读底层和可写顶层叠加在一起,看起来像一个单一的文件系统。在这种情况下,目录被叠加,文件从顶部看。如果有冲突,对于文件,顶层将优先考虑,而对于目录,顶层将被合并。如果你编辑一个只在底部的文件(只读),在顶部会有一个副本。实验
为了进行overlayfs,你需要以下四个目录
work:工作目录,与上层文件系统相同,必须为空。lower: 下一级的目录。 它是只读的,可以使用各种文件系统。upper: 上层目录。它必须是可写的,并返回适当的d_type的readdir,所以不能使用NFS。merged:overlayfs被挂载到的目录。准备以下三个文件来测试
both:上面和下面都有的文件only_upper: 只存在于顶部的文件only_lower: 只存在于底部的文件azureuser@build:~$ mkdir -p fmeng/{work,upper,lower,merged} azureuser@build:~$ echo "upper" >> fmeng/upper/both azureuser@build:~$ echo "upper" >> fmeng/upper/only_upper azureuser@build:~$ echo "lower" >> fmeng/lower/both azureuser@build:~$ echo "lower" >> fmeng/lower/only_lower azureuser@build:~$ cd fmeng/ azureuser@build:~/fmeng$ sudo mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged azureuser@build:~/fmeng$ azureuser@build:~/fmeng$ df -h | grep overlay overlay 29G 2.1G 27G 7% /home/azureuser/fmeng/merged azureuser@build:~/fmeng$ ls看到这三个文件。 azureuser@build:~/fmeng/merged$ ls both only_lower only_upper azureuser@build:~/fmeng/merged$ 实际上我们创建了四个文件,其中两个both,我们看看both是什么现在 azureuser@build:~/fmeng/merged$ cat bothupper azureuser@build:~/fmeng/merged$ 如果删除both,出现字符特殊文件 azureuser@build:~/fmeng/merged$ rm both azureuser@build:~/fmeng/upper$ sudo ls -l total 4 c--------- 2 root root 0, 0 Jan 15 14:55 both -rw-rw-r-- 1 azureuser azureuser 0 Jan 15 14:52 mytest -rw-rw-r-- 1 azureuser azureuser 6 Jan 15 14:47 only_upper azureuser@build:~/fmeng/upper$
root@build:~# brctl addbr fmengbr0 root@build:~# ip addr add 172.18.0.1/24 dev fmengbr0 root@build:~# ip link set dev fmengbr0 up root@build:~# ip link add dev veth0_1 type veth peer name veth1_1 ip link set dev veth0_1 up ip link set veth0_1 master fmengbr0 ip netns add netns_test ip link set veth1_1 netns netns_test ip netns exec netns_test ip link set dev lo up ip netns exec netns_test ip link set veth1_1 address 02:42:ac:11:00:01 ip netns exec netns_test ip addr add 172.18.0.2/24 dev veth1_1 ip netns exec netns_test ip link set dev veth1_1 up ip netns exec netns_test ip route add default via 172.18.0.2 root@build:~# ifconfig fmengbr0 fmengbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.1 netmask 255.255.255.0 broadcast 0.0.0.0 inet6 fe80::b88d:ebff:fe19:d95a prefixlen 64 scopeid 0x20<link> ether ba:8d:eb:19:d9:5a txqueuelen 1000 (Ethernet) ... root@build:~# cgcreate -g cpu,cpuacct,memory:/test root@build:~# cgexec -g "cpu,cpuacct,memory:/test" ip netns exec netns_test unshare -fmuip --mount-proc chroot "/var/lib/fmeng/image/busybox/75fae911f860e3d9d6898b7af34a3b96374dcb33ee9d8b7a6230b74d4a1f30d4" /bin/sh / # ls VERSION etc layer.tar root var bin home lib tmp dev json lib64 usr / # ip a 1: lo: <loopback,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo ... 5: veth1_1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue qlen 1000 link/ether 02:42:ac:11:00:01 brd ff:ff:ff:ff:ff:ff inet 172.18.0.2/24 scope global veth1_1 ...
镜像构建技巧
容器历史
chrootSolaris Zone -> 很像一个VMOpenVZLXC - Linux 容器(LXC)是之一个、最完整的 Linux 容器管理器的实现方案DockerRocket - CoreOScontainerd 大一统 (OCI)Dockerfile 语法
ADD和COPY区别
https://www.ctl.io/developers/blog/post/dockerfile-add-vs-copy/
ENTRYPOINT 和 CMD 区别
https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/ http://www.johnzaccone.io/entrypoint-vs-cmd-back-to-basics/至少得定义一个(ENTRYPOINT 或者CMD),以保证运行。否则容器跑不起来容器运行时只定义它们其中一个的话,CMD和ENTRYPOINT的效果是一样的。写法SHELL和exec,推荐execENTRYPOINT和CMD都可以被 docker run -- entrypoint参数 override
如果你不想开发者修改镜像缺省的执行命令,例如PING, 那么用ENTRYPOINT。
以命令(ENTRYPOINT)+ 参数(CMD)的形式,提供用户修改参数的灵活性。
如果甚至希望提供修改镜像缺省命令的能力,那么只用CMD(没有ENTRYPOINT) 这样用户可以完全地自己定义我起镜像用什么命令,灵活性更高。
测试:
cat Dockerfile FROM alpine ENTRYPOINT ["ping"] CMD ["www.google.com"] docker run test www.yahoo.com PING www.yahoo.com (98.139.183.24): 56 data bytes 64 bytes from 98.139.183.24: seq=0 ttl=37 time=0.590 ms root@build:~# docker run -it test sh ping: bad address 'sh' root@build:~#
cat Dockerfile FROM alpine CMD ["ping", "www.google.com"] docker run -it test:0.2 sh / # ls bin dev etc home lib media mnt opt proc root run ***in srv sys tmp usr var / #root@build:~# docker run test:0.2 www.baidu.com docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "www.baidu.com": executable file not found in $PATH: unknown.
OCI镜像
OCI镜像规范的目标是:允许开发者只要对容器打包和签名一次,就可以在所有的容器引擎上运行该容器。这意味着开发团队可以根据自己的需要选择构建工具和扩展语法。
OCI 主要有三个规范:运行时规范 runtime-spec ,镜像规范 image-spec 以及不常见的镜像仓库规范 distribution-spec
镜像规范:
├── annotations.md # 注解规范 ├── config.md # image config 文件规范 ├── considerations.md # 注意事项 ├── conversion.md # 转换为 OCI 运行时 ├── descriptor.md # OCI Content Descriptors 内容描述 ├── image-index.md # manifest list 文件 ├── image-layout.md # 镜像的布局 ├── implementations.md # 使用 OCI 规范的项目 ├── layer.md # 镜像层 layer 规范 ├── manifest.md # manifest 规范 ├── media-types.md # 文件类型 ├── README.md # README 文档 ├── spec.md # OCI 镜像规范的概览
容器镜像仓库的选择
公有云
官方 https://hub.docker.comjfrog artifactory https://www.jfrog.com/confluence/display/JFROG/Docker+Registry各个云厂商的镜像仓库服务私有云
harborjfroghttps://quay.io/基础镜像的选择
静态语言:越小越好动态语言:根据情况测试https://aws.amazon.com/cn/blogs/china/choose-the-best-docker-image-for-your-python-application/
实战课程
https://time.geekbang.org/column/intro/100063801
runtime:
容器运行时kernelkubernetes源码