Docker 源码build rpm包

 docker  Docker 源码build rpm包已关闭评论
3月 152018
 

官方文档:

https://github.com/docker/docker-ce-packaging/tree/master/rpm

 

环境搭建:

安装并启动docker就行:

 

命令很简单:

 

打包原理:

从make命令说起,通过docker容器对engine  cli分别进行打包,通过git获取版本号信息,通过docker-ce-packaging/rpm/Dockerfile.x86_64 构建一个基于centos:7 的容器镜像,镜像中安装编译环境(golang),容器挂载外部的一些目录,即,输入来自于外部目录,编译结果输出到外部目录;容器镜像直接启动rpmbuild命令进行构建,构建的详细步骤都在rpm的spec文件中,构建过程中还需要下载有些其他的源码

 

部分细节:

rpmbuild 命令:

 

容器挂载的外部目录:

 

问题记录:

  1. git 版本需要支持 -C 选项
  2. engine 的路径不小心写错了,导致engine的源码文件没有打进去,修改后OK

 

构建优化:

  1. 将github.com 解析到自己的代理服务器,加速下载构建中依赖的代码
  2. 将Dockerfile.x86_64中golang安装包下载地址修改为国内地址,只需将golang.org 修改为golang.google.cn 即可,加速下载golang安装包,当然,更快的办法是改为本地的地址
  3. 更快的办法是,自己build一个自己的环境,用完也不要销毁,每次自己直接执行rpmbuild -ba docker-ce.spec 就行了,不过注意:
    1. 构建过程中需要git clone一些代码,如果目录已经存在,就报错的,所以,可以做一个假的git,使得目录已存在就不再clone,这样还快些

 

 Posted by at 下午 5:25

vsftp in docker

 docker, Linux & Unix  vsftp in docker已关闭评论
3月 052018
 

当vsftpd在容器里面,而且容器IP又是host内部的私有IP的情况,client采用passive模式来下载数据能行得通吗? 可以的

  1. passive模式下,vsftpd需要listen临时端口来传输数据,所以docker创建容器时,不仅要暴露21端口,还要暴露可能listen的临时端口,为了不映射太多端口,可以在vsftpd的配置文件中配置可能的临时端口的范围
  2. passive模式下,vsftpd需要通过协议内容告知client临时端口及IP地址,然而,容器网卡IP地址显然是不能被client直接访问到的,庆幸的是,vsftpd配置文件中有关于可以告知client的ip地址的配置,该ip地址并不要求本机上必须有的,显然该配置是给类似情况准备的

 Posted by at 下午 6:13

docker-init in bash

 docker  docker-init in bash已关闭评论
1月 102018
 

把下面脚本当做容器的init进程:

 

知识点:

  1. while循环中修改外部的环境变量,则 不能使用管道的方式给while提供数据,这样的话,while 就是在新的子shell中执行的,不会影响到当前shell,所以:
    1. 使用了标准输入的重定向
    2. 使用了 <($cmd) 的方式
  2. 为了让字符串中连续的空格被保留,参数传递时多要通过双引号引上,即使是 $(cmd) 产生的字符串也要整个用双引号引上,当然,此时的双引号比较特殊,因为此时的双引号可以套双引号而不需要转义,示例: (注意下面几种双引号中嵌套单引号的的区别)

 

注意:

  1. 这个init进程是bash做的,如果docker attach的话,不管是ctrl-d退出还是ctrl-c退出,都会导致init进程终止,容器退出
  2. 脚本中的while循环最初想到的是通过sleep实现暂停的,但是考虑到sleep会产生一个额外的进程,不好看,于是选择了read
 Posted by at 上午 10:57

docker on openstack

 docker, openstack  docker on openstack已关闭评论
12月 142017
 

场景,用docker做开发用的虚拟机,每个docker都有一个可以公开访问的IP地址。

由于docker和宿主机共享内核,一不小心可能会把整个宿主机搞挂,而且,docker热迁移也是个难题,所以,尽管openstack马上可以支持docker,我也不想让docker直接部署在计算节点;我的思路是,将docker部署在openstack管理的kvm虚拟机上,这样还能通过热迁移kvm的方式将容器迁移到别的计算节点。

 

注意事项:

  1. 关闭openstack的端口安全
  2. 热迁移后容器的IP地址在交换机上的mac地址与端口的映射不能及时更新
    1. 如果容器频繁地和外部通信的话,mac地址与端口的映射会被及时刷新
    2. 如果没能及时刷新的话,可以在与容器IP同网段的机器上,先clear一下arp缓存,在ping 一下容器IP,就可以了;
    3. 如何自动处理呢?在kvm虚拟机上(就是容器的宿主机上),docker exec到容器内部,然后ping一下网关就行。
 Posted by at 下午 2:01

变化的mac地址

 docker, openstack  变化的mac地址已关闭评论
11月 212017
 

 

一个bridge诞生时,会有一个mac地址;当向bridge上addif  veth2时,bridge的mac地址就跟随了veth2的mac地址,难道br0就不能固定一个mac地址吗?

可以的:

默认情况下,bridge总是跟随port中mac地址最小的那个port的mac地址,如果不想让mac地址总是变化,则可以设置bridge的首选mac地址,方法就是显式地给bridge设置mac地址:

参考:

http://blog.csdn.net/fanwenbo/article/details/2131193

 Posted by at 下午 2:58

创建新的名字空间

 docker  创建新的名字空间已关闭评论
10月 202017
 

功能: 创建新的名字空间,并使得进程处于sleep状态,可以随时nsenter进来

测试 mnt 时发现,似乎并没有实现mount的隔离; 测试方法:

./new-namespace -m &

然后使用nsenter,分别在名字空间内外查看 /proc/self/mountinfo 的内容,发现如何操作,内外都是一致的。

注意: 需要和pid名字空间一起使用

 

参考: https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces

 Posted by at 下午 12:08

docker 之 exec失败的问题

 docker  docker 之 exec失败的问题已关闭评论
10月 122017
 

现象:

乍一看, /proc/self/exe 文件找不见?

一般来讲,文件找不见并不奇怪,怪就怪在是 /proc/self/exe 找不见就不太应该了;

因为docker exec 最终是由libcontainerd进程来出来的,strace跟进发现,是chdir到 /root/data1/docker/devicemapper/mnt/4723e8178992b32b7284aa48c1c62f4011a6b785aca0c54e18d7ce5cc23b22dc/rootfs 时,找不到目标目录导致的,于是我就迅速地看了一下,该目录确实不存在,但是对于正常的能够exec的容器来讲,相应的rootfs目录也是不存在的

思考中。。。

docker玩的就是名字空间和cgroup,所以不能不想到这些;libcontainerd也有自己的(mnt)名字空间,我们进入libcontainerd进程的文件系统就可以查看到上面目录的存在了,而且,正常的容器存在相应的目录,异常的容器不存在相应的目录;

通过mount命令可以发现mount的规律,从容器的config.json (/var/run/docker/libcontainerd/c6176f37c4b67b03d4187edef6d1131cd44ab80bd0f0c20b24a7a20056967652/config.json) 中查看到对应的mount的位置,通过nsenter进入libcontainerd的mnt名字空间手动mount上去就好了,如下:

那么该mount点是如何丢掉的呢?重启dockerd能否自动修复该问题呢?稍后再研究

 Posted by at 下午 6:34

cgroup 审计策略

 docker, Linux & Unix  cgroup 审计策略已关闭评论
9月 072017
 

内存子系统

场景:

当你把一个已经占用了1GB内存的进程转移到一个新的cgroup后,新的cgroup看到的该进程使用的内存大小会是多少呢?

memory.max_usage_in_bytes  和 memory.usage_in_bytes 都不会将这1GB计算在内的,只有该进程继续申请内存才会计算新申请的内存。

同样,如果把一个占用内存很多的进程从cgroup中移出来,memory.max_usage_in_bytes  和 memory.usage_in_bytes 应该也不会被更新

Process Number Controller

  1.  pids.current 可以大于 pids.max
    1. 当cgroup中进程数量达到最大时,cgroup并不“阻止”从其它cgroup中移动一个进程到该cgroup中;只是说不允许在该cgroup中fork、clone新的进程或线程
  2. pids.current包含所有子孙cgroup中的进程(和线程)
  3. 当cgroup对进程数量不限制时,pids.max 不是0(零)也不是-1,而是字符串max😓
 Posted by at 下午 6:33

docker 之磁盘限额

 docker, Linux & Unix  docker 之磁盘限额已关闭评论
9月 062017
 

docker-ce-17.07.0 版本开始支持overlay2的磁盘配额,该版本 8月29号release了,现在可以使用edge版本:

https://download.docker.com/linux/centos/7/x86_64/edge/Packages/docker-ce-17.07.0.ce-1.el7.centos.x86_64.rpm

 

overlay2的配额限制是有条件的:

  1. 基于xfs文件系统(如果不开启配额的话,ext4上也能支持,如果内核版本够高的话,btrfs也能支持)
  2. xfs文件系统挂载时使用pquota选项(pquota和gquota 不能同时出现)
  3. xfs 格式化时需要ftype=1,用于enable d_type

 

xfs的pquota是个啥东西: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/xfsquota.html

 

XFS quotas are enabled at mount time, with specific mount options. Each mount option can also be specified as noenforce; this will allow usage reporting without enforcing any limits. Valid quota mount options are:
  • uquota/uqnoenforce – User quotas
  • gquota/gqnoenforce – Group quotas
  • pquota/pqnoenforce – Project quota

注意:

pquota和gquota 不能同时出现

  • uquota: 强制限制,绝对不能超限
  • uqnoenforce:可以超限,但是会贴罚单

 

如果是kickstart 安装的系统,用如下命令:


mkfs.xfs 还有很多选项,专门研究存储的话,还是要了解的

参考: http://foxhound.blog.51cto.com/1167932/1841487

docker-ce-17.07.0 关于xfs上的overlay2存储驱动的磁盘限额,使用效果如下:

注意:

  1. –storage-opt时, 使用的是size,而不是overlay2.size;关键是多处文档描述的都是overlay2.size=1g,而实际上却不识别overlay2.size,识别的却是size
  2. 做磁盘限额的时候,基础镜像的大小显然没有计算在内; 不做磁盘限额的时候,显示的是整个overlay文件系统的使用情况
  3. 据说daemon.json 中也是可以定义存储选项的,但是测试发现不管使用overlay2.size还是size都不报错,也都不生效(但是源码上确实都是overlay2.size呢)
  4. docker info中不显示默认的存储配额
  5. 关于存储选项: overlay2.override_kernel_check, 文档 要求必须设置为true,实际情况是:
    1. 如果设置为true,docker会帮忙检查内核版本够不够高,不够高就直接报错了
    2. 如果设置为false,docker依然会帮忙检查内核版本够不够高,不够包就记录一个警告日志

阿里云提供的centos7镜像的文件系统类型似乎都是ext4的

并非所有的D状态的进程都是kill不掉的:

docker 的磁盘限额是可以通过xfs_quota 查看到的(kernel内核版本要求4.6以上才能查看到,小于4.6的内核版本上不是不支持限额,只是通过xfs_quota 看不到而已)

 

 Posted by at 下午 2:16