code v中len与seq文件国iv和国v有什么区别别?

Docker基础与高级 | 17173系统部
tag: cloud, virtual, docker, lxc
1. Docker安装
按照官方说明:红帽6、centos均通过epel源,执行yum install docker-io进行docker安装,启动服务是service docker start
经测试,红帽6、centos也可以通过在官网上下载编译好的二进制文件到本地也可以使用,但需要提前手动执行service cgconfig start来挂载cgroup,然后./docker-latest -d来启动服务。
下载地址:https://get.docker.io/builds/Linux/x86_64/docker-latest
https://get.docker.io/builds/Linux/x86_64/docker-1.0.1
但是官方提示需要内核大于3.8版本,否则可能会有问题。el&3.8
2. devicemapper
扩容存储池大小、扩容容器文件系统大小
https://www.dockboard.org/resizing-docker-containers-with-the-device-mapper-plugin/
实验成功,但是一旦容器关闭再启动,就会报错,还得根据文档再做一次 dmsetup resume才能成功启动容器(但是如果不先启动容器,就无法使用dmsetup命令来resume),因此能否用于生产环境有待继续探索
3. 玩转net namespace
首先要支持ip netns指令。而红帽6及epel均不支持,解决方法:
yum install -y http://rdo.fedorapeople.org/rdo-release.rpm
yum update -y iproute
直接执行这个命令(或ip netns list)读取的是/var/run/netns下的文件名,因此若不存在/var/run/netns,需要mkdir -p /var/run/netns
配置像LXC一样的网络
I. 宿主配置
1. 宿主上升级iproute包,以便支持ip netns指令:
yum install -y http://rdo.fedorapeople.org/rdo-release.rpm
yum update -y iproute
2. 在宿主上配置好桥接:
一. 方法1(不推荐): 敲命令配置桥接(很容易导致网络中断,需要ILO连上操作)
1) 创建桥接网卡br1并激活:brctl addbr br1; ip link set br1 up
2) 配置br1的mac地址,和宿主准备桥接的网卡mac相同,通常为内网网卡eth1:ip link set br1 address xx:xx:xx:xx:xx:xx
3) 给br1配置一个ip地址,或者将eth1的ip地址配置在br1上,2种方法任选其一都可行:
ifconfig br1 192.168.2.1 netmask 255.255.255.0
ifconfig eth1 0.0.0.0; ifconfig br1 192.168.2.2 netmask 255.255.255.0
4) 配置宿主网关,从br1出
ip ro del default
ip ro add default via 192.168.2.254 dev br1
5) 将eth1桥接至br1:
brctl addif br1 eth1
二. 方法2(推荐):写网卡配置文件
ifcfg-br1:
DEVICE="br1"
TYPE="Bridge"
NM_CONTROLLED="no"
ONBOOT="yes"
BOOTPROTO="static"
IPADDR=192.168.2.2
NETMASK=255.255.255.0
ifcfg-eth1:
DEVICE="eth1"
BRIDGE="br1"
BOOTPROTO="none"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
注意:要在/etc/sysconfig/network-scripts/ifup-eth里if [ "${TYPE}" = "Bridge" ]; then -& fi段落最后(fi前)加个ip link set br1 address $(get_hwaddr eth1),防止桥接网卡mac地址随机生成导致网络暂时中断
service network restart
# 重启网络生效
II. 容器配置:
1. 启动docker容器:
docker run -t -i -d --name="net_test" --net=none centos:latest /bin/bash
记录下输出(即CONTAINER ID),然后通过docker inspect -f '{{.State.Pid}}' CONTAINER ID获得该容器的pid(也即容器首进程在宿主上的pid),假设为1000
2. 为容器创建网卡命名空间,建立点对点连接(容器命名空间网卡和宿主上生成的网卡点对点)
mkdir -p /var/run/netns
#创建网络命名空间目录,ip netns会读取该目录下的文件名
ln -s /proc/1000/ns/net /var/run/netns/1000
#将网络命名空间文件软链接到/var/run/netns,以便ip netns能够读取
ip link add vethA type veth peer name vethB
#在宿主上创建2张直连网卡(vethA与vethB直连),将vethA作为容器里的网卡,vethB作为宿主上能看到的网卡
ip link set vethB up
# 激活网卡vethB
ip link set vethA netns 1000
# 将刚才创建的网卡归位网络命名空间
配置vethA网卡参数:
ip netns exec 1000 ip link set vethA name eth1
ip netns exec 1000 ip addr add 192.168.2.3/24 dev eth1
ip netns exec 1000 ip link set eth1 up
ip netns exec 1000 ip route add default via 192.168.2.254 dev eth1
brctl addif br1 vethB
# 将eth1桥接至br1
docker attach登录容器,查看是否能ping通网关及其他子网或公网
3.1. ENV(环境变量)
Dockerfile支持ENV参数,表示启动容器时候设置变量。
只在CMD启动的进程export设置变量,而不是将变量赋值命令写入/etc/profile等脚本里,因此通过ssh方式登录容器获得的shell是没有这个变量的
4. port map
docker支持端口映射,通过iptables DNAT将宿主上的端口转发至容器ip对应端口。
虽然配置了端口映射后,在宿主上通过netstat -lntpu可以看到docker进程会监听这个端口,但是还没发现其作用,因为流量直接从iptables就进入容器里。
docker run -p、docker run -P、docker port作用:
docker run -P 就是将image定好的port给做个端口映射(若没指定-p,则外部端口随机)
docker run -p "8080:80" 启动容器时候做端口映射:宿主的0.0.0.0:8080 -& 容器80
docker run -P -p "8080:80" 假如image已经有一个port 22的配置,那么就会做2个端口映射:宿主0.0.0.0:xxxxx -& 容器22、宿主0.0.0.0:8080 -& 容器80
docker port 是查看容器已经做了端口映射的端口被映射到了哪个端口上,其实直接用docker ps就能看到,使用docker port可能是为了方便二次开发
5. 直接使用docker默认分配的IP对外提供服务(测试中)
5.1. 使用参数以及将docker0的ip配为机房内网网段
将宿主eth1桥接到docker0上,将docker0的ip更改为原来eth1的ip(机房内网网段)
存在一个问题:docker run时候分配的ip是从1开始,到254。因此存在和网关或者其他机器ip冲突的可能,无法避免。因此docker分配ip不会做ping检查是否存活
docker run分配出去的ip,docker kill并且docker rm都不会收回并重新使用,而是重启docker daemon才会将ip收回
–iptables=false
使用这个参数后,就不会再往iptables里生成nat、forward等信息了。
这样启动的容器,登录容器能看到网关是宿主docker0的ip,这样网络是通的,是可以访问外网,但路是这么走的:
1. 容器里的数据包将数据经过point-to-point网卡传送到宿主的对应veth网卡上
2. 宿主veth网卡接收到数据包后发现网关是254,于是通过icmp数据包告知网关是254,然后容器发送数据包时自动将网关更改为254,可以从ping的输出看到:
[ 17:37:23-root@21e77bf38fc0:~ ]#ping
PING www. (115.239.210.27) 56(84) bytes of data.
64 bytes from 115.239.210.27: icmp_seq=1 ttl=55 time=13.9 ms
From 192.168.3.1: icmp_seq=2 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=2 ttl=55 time=13.6 ms
From 192.168.3.1: icmp_seq=3 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=3 ttl=55 time=13.6 ms
From 192.168.3.1: icmp_seq=4 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=4 ttl=55 time=14.0 ms
From 192.168.3.1: icmp_seq=5 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=5 ttl=55 time=14.7 ms
From 192.168.3.1: icmp_seq=6 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=6 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=7 ttl=55 time=13.7 ms
From192.168.3.1: icmp_seq=8 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=8 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=9 ttl=55 time=13.6 ms
64 bytes from 115.239.210.27: icmp_seq=10 ttl=55 time=13.5 ms
From 192.168.3.1: icmp_seq=11 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=11 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=12 ttl=55 time=14.1 ms
64 bytes from 115.239.210.27: icmp_seq=13 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=14 ttl=55 time=13.6 ms
64 bytes from 115.239.210.27: icmp_seq=15 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=16 ttl=55 time=13.8 ms
From 192.168.3.1: icmp_seq=17 Redirect Host(New nexthop: 192.168.3.254)
64 bytes from 115.239.210.27: icmp_seq=17 ttl=55 time=13.6 ms
64 bytes from 115.239.210.27: icmp_seq=18 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=19 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=20 ttl=55 time=14.1 ms
64 bytes from 115.239.210.27: icmp_seq=21 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=22 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=23 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=24 ttl=55 time=13.9 ms
64 bytes from 115.239.210.27: icmp_seq=25 ttl=55 time=14.2 ms
64 bytes from 115.239.210.27: icmp_seq=26 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=27 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=28 ttl=55 time=13.8 ms
64 bytes from 115.239.210.27: icmp_seq=29 ttl=55 time=13.9 ms
64 bytes from 115.239.210.27: icmp_seq=30 ttl=55 time=14.1 ms
64 bytes from 115.239.210.27: icmp_seq=31 ttl=55 time=13.9 ms
64 bytes from 115.239.210.27: icmp_seq=32 ttl=55 time=13.9 ms
64 bytes from 115.239.210.27: icmp_seq=33 ttl=55 time=14.0 ms
64 bytes from 115.239.210.27: icmp_seq=34 ttl=55 time=13.7 ms
64 bytes from 115.239.210.27: icmp_seq=35 ttl=55 time=14.0 ms
64 bytes from 115.239.210.27: icmp_seq=36 ttl=55 time=14.4 ms
64 bytes from 115.239.210.27: icmp_seq=37 ttl=55 time=13.9 ms
docker服务启动时候会把内核参数ip.forward给打开(数据包转发)
6. Docker COMMAND
6.1. docker参数
–api-enable-cors
开启cors,以便浏览器能够通过ajax调用。但是若开启了tls,使用cors就变得困难了,目前网络上还未找到解决方案
–link:2个容器互通
其实就做3件事:
1. 若有端口映射,则在iptables的FORWARD链里将端口ACCEPT
2. /etc/hosts:做link的容器的/etc/hosts能看到被link的容器的hosts条目
3. 环境变量:做link的容器可以看到被link的容器的环境变量(仅为--env变量),如:ALIAS_ENV_变量名、ALIAS_NAME=xxx
–volume: 目录共享
支持2种模式:
1. 从宿主挂载:-v /tmp:/tmp/foo 表示将宿主的/tmp目录挂载至容器的/tmp/foo目录,可读可写,和mount --bind的效果类似
2. 容器之间共享:
启动第一个容器时带参数-v /tmp/foo表示在宿主上创建/var/lib/docker/vfs/dir/xxxxx(id,但不是容器id),然后挂进容器的/tmp/foo目录;
启动第二个容器时带参数--volumes-from=b5f(*第一个容器id)表示和第一个容器共享挂载,因此第二个容器启动后也能从df -h看到/tmp/foo目录被挂载。从inspect也可以很容易看出来(2个容器的inspect以下内容相同):
"Volumes": {
"/opt": "/var/lib/docker/vfs/dir/a7b1b8b1bb877eb6df2415"
"VolumesRW": {
"/opt": true
7. 搭建私有Registry注册中心
7.1. 下载软件
yum install python-devel libevent-devel python-pip gcc xz-devel
安装registry:
pip install docker-registry
pip install docker-registry[BUGSNAG]
pip install -i /simple/ backports.lzma
pip install --upgrade -i /simple/ backports.lzma
7.2. 启动服务
使用默认配置文件启动服务:
cd /usr/lib/python2.6/site-packages/config
cp config_sample.yml config.yml
mkdir /tmp/registry
# config_sample.yml的默认配置
gunicorn --access-logfile - --debug -k gevent -b 0.0.0.0:5000 -w 1 docker_registry.wsgi:application
加入开机启动
可以将以下内容写入/etc/rc.local,或者放在一个脚本里,/etc/rc.local调用这个脚本
pkill gunicorn
rm -f /data/docker-registry.db
/usr/bin/gunicorn --access-logfile /opt/logs/docker-registry/access.log --error-logfile /opt/logs/docker-registry/error.log --daemon --debug -k gevent -b 0.0.0.0:5000 -w 8 docker_registry.wsgi:application
pkill gunicorn
/usr/bin/gunicorn --access-logfile /opt/logs/docker-registry/access.log --error-logfile /opt/logs/docker-registry/error.log --daemon --debug -k gevent -b 0.0.0.0:5000 -w 8 docker_registry.wsgi:application
启动不成功FAQ
1. 日志目录没有创建
2. .db文件已存在,启动前删掉就行
排错可通过error.log分析
docker tag busybox localhost:5000/busybox
docker push localhost:5000/busybox
上传成功后在/tmp/registry上应该能看到2个目录:images和repositories
docker pull localhost:5000/busybox
若想给下载的镜像取个别名:
docker tag localhost:5000/busybox aliasname 或 docker tag id aliasname
#id为localhost:5000/busybox的image id
删除别名:
docker rmi aliasname
当然也可以选择把原始名字删掉:
docker rmi localhost:5000/busybox
若一个镜像有至少2个tag,那么通过docker rmi删除的只是别名,若只有1个名字(没有别名),那么删除的是真正的镜像。
已测试:当镜像还在上传过程中时,其他机器是无法pull下来的。因此不会生成不完整的镜像
curl --silent "http://192.168.1.1:5000/v1/search?q="
| json_reformat
7.4. 套一层透明代理(不推荐,有bug)
配置nginx,vhost内容如下
upstream docker-registry {
server 127.0.0.1:5000;
listen 192.168.1.1:80;
proxy_set_header Host
proxy_set_header X-Real-IP
client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads
# required to avoid HTTP 411: see Issue #1486 (/dotcloud/docker/issues/1486)
chunked_transfer_
location / {
proxy_pass http://docker-
注意:只有以下2种情况,套一层透明代理是行的通的:
1. nginx监听80端口,gunicorn监听0.0.0.0
2. nginx监听非80端口,且gunicorn监听在网络可通的ip,如192.168.1.1这样的内网ip,而不能监听在127.0.0.1
测试发现,当端口不为80时,在docker push时候,会首先连接image name中的ip、端口,如:80,然后连接实际的gunicorn端口。因此当gunicorn端口无法访问时,就会报错。
而端口为80时候就不会这样,原因未知,应该是代码逻辑。
&=1.1.2版本都有如上共性,&1.1.2的尚未测试。
7.5. Web UI
docker pull atcol/docker-registry-ui
docker run --name "registry_UI" -tid -p 127.0.0.1: -e REG1=/v1/ atcol/docker-registry-ui:latest
开机启动:
echo 'docker start registry_UI' && /etc/rc.local
套一层透明代理
配置nginx,vhost内容如下
upstream docker-registry-web {
server 127.0.0.1:5001;
listen 192.168.1.1:80;
server_name registry-;
location / {
proxy_pass http://docker-registry-
http://registry-/
注意:页面上的删除镜像只是删除tag标签,实际id和image不会删除
docker镜像的元数据里记录着FROM哪个镜像,如果真的删除镜像所有数据,正常逻辑应该是A-&B B-&C -C-&D D-&E,这样一连串都给删除了,但是其中的某个镜像可能又被其他镜像给依赖了,猜测正是基于这种逻辑,才只删除了tag
8. docker with HTTPS
Docker HTTPS原理:双向验证。官方说明():
In daemon mode, it will only allow connections from clients authenticated by a certificate signed by that CA.
In client mode, it will only connect to servers with a certificate signed by that CA.
核心:服务端和客户端的数字证书都由同一个CA签发,因此双方在认证通讯时使用和签发时的同一个CA就能互相认证。
8.2.1. 创建CA(证书颁发中心)
echo 01 & ca.srl
openssl genrsa -des3 -out ca-key.pem 2048
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca.pem
8.2.2. 创建服务端公钥和私钥
生成私钥:
openssl genrsa -des3 -out server-key.pem 2048
生成公钥(数字签名证书):
1. 生成CSR文件(Certificate Signing Request 证书签名请求):openssl req -subj '/CN=' -new -key server-key.pem -out server.csr
2. 编写openssl.conf文件,内容如下:
------------- BEGIN ---------------------------------
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[ v3_req ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.
DNS.2 = *.
------------- END ------------------------------------
生成公钥(数字签名证书):
openssl x509 -req -days 3650 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem -extensions v3_req -extfile openssl.conf
8.2.3. 创建客户端公钥和私钥
生成私钥:
openssl genrsa -des3 -out client-key.pem 2048
生成公钥(数字签名证书):
1. 生成CSR文件(Certificate Signing Request 证书签名请求):openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr
2. echo extendedKeyUsage = clientAuth & f
3. 生成公钥(数字签名证书):openssl x509 -req -days 3650 -in client.csr -CA ca.pem -CAkey ca-key.pem -out client-cert.pem -f
8.2.4. 移除服务端私钥、客户端私钥密码
openssl rsa -in server-key.pem -out server-key.pem
openssl rsa -in client-key.pem -out client-key.pem
8.2.5. 使用
将服务端3个文件拷贝到docker daemon(假设为192.168.1.2)的/root/.docker/下:
1. scp ca.pem server-cert.pem server-key.pem 192.168.1.2:/root/.docker/
2. 登录192.168.1.2
cd /root/.docker/
chmod 0600 *
3. 添加启动参数:
修改/etc/sysconfig/docker中的other_args值,添加以下内容,如:other_args="--graph /opt/docker --tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/server-cert.pem --tlskey=/root/.docker/server-key.pem -H unix:///var/run/docker.sock -H tcp://192.168.1.2:2376 -H tcp://127.0.0.1:2376"
将客户端3个文件拷贝至”中控机”,然后就可以通过HTTPS远程对docker daemon进行操作:
docker --tlsverify --tlscacert=/opt/docker_tls/ca.pem --tlscert=/opt/docker_tls/client-cert.pem --tlskey=/opt/docker_tls/client-key.pem -H localhost:2376 images
8.2.6. 管理
查看CSR文件:
openssl req -noout -text -in server.csr
查看签名证书(server-cert.pem、client-cert.pem):
openssl x509 -noout -text -in server-cert.pem
9. Docker Web-UI(shipyard)
9.1. 工作原理
在每台docker宿主机上启动一个容器(shipyard/agent),这个容器通过挂载宿主的/var/run/docker.sock文件来获取该宿主上容器、镜像的信息,同时在容器启动时将agent注册到管理中心(shipyard/deploy)上,实现从Web查看和操作docker容器与镜像
每个docker宿主启动一个agent(shipyard/agent),管理中心启动一个server(shipyard/deploy)
9.2. server配置
9.2.1. 下载镜像
docker pull shipyard/deploy
9.2.2. 启动容器(自动完成部署)
docker run -i -t -v /var/run/docker.sock:/docker.sock shipyard/deploy setup
执行该命令时,实际做了如下操作:
在本地宿主上依次下载并启动
1. shipyard/redis
2. shipyard/router
3. shipyard/lb(Load Balance的意思)
4. shipyard/db
5. shipyard/shipyard(Web-UI)
如何做到上述的:docker run -i -t -v /var/run/docker.sock:/docker.sock shipyard/deploy setup会将socket文件挂载进容器里,这样在容器里就能对宿主的镜像和容器进行管理,而shipyard/deploy的CMD是一个脚本,这个脚本就是进行上述操作
9.2.3. 验证
docker ps查看是否都已启动
注意docker logs shipyard_router可能会看到大量报错,并且占用大量CPU,负载也会升高。暂时不知原因,已提交至,等待答复,详见
9.3. agent配置
9.3.1. 下载镜像
docker pull shipyard/agent
9.3.2. 启动容器(自动注册到server)
docker run -i -t -v /var/run/docker.sock:/docker.sock -e IP=`ip -4 address show br1 | grep ‘inet ‘ | sed ‘s/.*inet \([0-9\.]\+\).*/\1/’` -e URL= -p
shipyard/agent
如果看不懂,可以这么写:
docker run -i -t -v /var/run/docker.sock:/docker.sock -e IP=192.168.1.2 -e URL=http://192.168.1.1:8000 -p
shipyard/agent
(192.168.1.2是docker宿主ip)
注意:要先启动server,才能启动agent,否则agent注册到server可能会失败。
9.4. 页面配置
9.4.1. 登录页面
默认账号:admin
默认密码:shipyard
9.4.2. 接受agent注册
,在打开网页的右部分点击按钮,选择authorize host
9.5.1. 页面上的Images(http://192.168.1.1:8000/images/)进行镜像删除要注意
自动进行了去重(根据image id),因此从页面上删除镜像时会将相同image id的全部删除
9.5.2. server端管理
移除:docker run -i -t -v /var/run/docker.sock:/docker.sock shipyard/deploy cleanup
重启:docker run -i -t -v /var/run/docker.sock:/docker.sock shipyard/deploy restart
升级:docker run -i -t -v /var/run/docker.sock:/docker.sock shipyard/deploy upgrade
9.5.3. 不建议生产使用,可作为学习借鉴
原因1:封装太多,用户无法定制修改()
原因2:一些细节功能方面,例如不同host的容器打印在一张表里,连排序功能都没有()
10. 镜像制作
10.1. 远程编译Dockerfile
docker -H tcp://xxx:2376 build –force-rm –no-cache -t foo/rhel6.5:1.0 /path/to/ 那么这个/path/to/指的是本地文件,而非远程编译机上的文件。
/path/to/Dockerfile文件会在命令执行之初就通过远端2376端口将/path/to/*(Dockerfile所在目录下的所有文件)传送到编译机上
Sending build context to Docker daemon xx MB过程就是将文件发送过去
Dockerfile除了支持文件方式外,还支持URL,即/path/to/可以改为(尚未测试过)
11. 内置bridge(nat)和自建网络桥接使用区别
内置bridge(nat)
1. 需要配套服务注册/发现,否则宿主上端口分配困难,容易冲突。
2. 由于每个容器暴露的端口都不一致,造成前端路由层nginx配置(proxy_pass)里无法使用dns的方式。
3. 端口映射要在容器启动时就指定好,后期无法变更。
4. 测试发现nat不支持websocket。
自建桥接网络
1. 每个容器都有独立ip,对外提供服务,如nginx+php,nginx+resin,都可以使用默认的80端口
2. 由于容器暴露端口都可以使用80端口,因此前端路由层nginx配置(proxy_pass)里可以使用dns的方式。
3. 无需为了后期端口映射添加而烦恼
4. 桥接支持websocket
1. 每个容器都需要一个IP(内网ip是不需要钱的)
12. Docker Event事件监听
12.1. 方法1:使用remote api
还未找出靠谱的阻塞方式
12.2. 方法2:使用unix socket
测试发现:docker服务关闭时,/var/run/docker.sock文件并不会自动删掉
使用python连接/var/run/docker.sock文件会一直连着,docker daemon停止后,文件仍在,连接也仍在,因此不适用于事件监听。
12.3. 方法3: 使用docker events命令
测试发现:输出内容与api的输出不完全一样,比如docker events输出的时间格式为可读的格式,而api输出的是unix timestamp。
可以通过python的模块os.popen(‘docker events’)来建立监听连接
# -*- coding: utf-8 -*-
handler = os.popen('docker -H 127.0.0.1:2376 events')
while True:
res = handler.readline()
print "Null"
13.1. nsenter(无需sshd、无需attach也可以登录容器)
原理:进入namespace(通过/proc/xxxx/ns/)
安装:docker run -v /usr/local/bin:/target :5000/jpetazzo/nsenter:latest
执行成功后会在宿主的/usr/local/bin下生成1个二进制程序nsenter和1个shell脚本docker-enter
docker-enter是对nsenter用法的封装,让使用更加简单
使用:docker-enter 容器id(或容器名)
docker-enter是一个shell脚本,其实是调用nsenter(二进制文件),因此可以直接使用nsenter:
nsenter --target $PID --mount --uts --ipc --net --pid
# 这个$PID指容器里的任意进程在宿主上的真实PID
14.1. sshd服务起不来
docker在源码里就关掉了audit_control(linux Capabilities),而/etc/pam.d/sshd里有一行session required pam_loginuid.so,把这行删掉就可以了
14.2. ulimit无法更改open-file、max processes
docker容器默认移除sys_resource(Linux能力),因而ulimit -n设置只能改小无法改大,改大会报错:ulimit: open files: cannot modify limit: Operation not permitted。
红帽7下docker run可以使用–privileged选项来不移除Linux能力,但docker默认移除这个Linux能力肯定是有安全方面的考量,因此尽量别用该选项
红帽6下要使用–privileged,docker版本不能&=1.0.1,否则会报错;stat /dev/.udev/db/cpuid:cpu0: no such file or directory。
解决方法:
若启动docker使用sysV服务,则在/etc/init.d/functions最开头添加一行:ulimit -u 204800 -HSn 204800
若启动docker使用命令,如docker -d,那么在启动之前先执行ulimit -u 204800 -HSn 204800即可
14.3. 改变/var/lib/docker路径
使用–graph参数:docker –graph=/opt/docker -d,会自动生成/opt/docker目录(0700),并在该目录下创建docker相关文件
原来的镜像和容器都找不到了,因为路径改了(原来的镜像是在/var/lib/docker/devicemapper/devicemapper/{data,metadata})
14.4. 将指定镜像标识为latest
docker tag 镜像id cyent/rhel6.5:latest
14.5. docker push报错
14.5.1. HTTP code 403 while uploading metadata: invalid character ‘&‘ looking for beginning of value
报错示例:
[ 14:50:44-root@localhost:vhosts ]#docker push :82/crosbymichael/dockerui
The push refers to a repository [:82/crosbymichael/dockerui] (len: 1)
Sending image list
Pushing repository :82/crosbymichael/dockerui (1 tags)
c5a: Pushing
14:50:46 HTTP code 403 while uploading metadata: invalid character '&' looking for beginning of value
解决方法:在nginx配置里注释掉”proxy_set_header Host $”
14.5.2. dial tcp 127.0.0.1:5000: connection refused
报错示例:
[ 18:24:35-root@localhost:~ ]#docker push :81/17173/as6.5-ng1.4:1.4
The push refers to a repository [:81/17173/as6.5-ng1.4] (len: 1)
Sending image list
Pushing repository :81/17173/as6.5-ng1.4 (1 tags)
c5a: Pushing
18:27:27 Failed to upload metadata: Put http://127.0.0.1:5000/v1/images/c5a64f264b78b5433614aecdd4d/json: dial tcp 127.0.0.1:5000: connection refused
解决方法:不要这么用,不要套nginx,gunicorn直接对外使用
14.6. CMD 和 ENTRYPOINT的区别
CMD是可以在docker run时候被覆盖的,而ENTRYPOINT无法被覆盖
CMD通常被用于调试,可以选择不同的CMD,可支持带参数
而ENTRYPOINT通常被用于应用发布,也可支持带参数
举例说明:
假设CMD和ENTRYPOINT都是/bin/run.sh,run.sh的内容是echo "Hello,$1"
那么,若为CMD,则docker run -t -i xxx/yyy /bin/ls /root就会列出/root目录下的内容
若为ENTRYPOINT,则docker run -t -i xxx/yyy /bin/ls /root就会打印出Hello,/bin/ls
最重要的区别:ENTRYPOINT是会被继承下去的
比如做镜像A的时候Dockerfile里写了一行ENTRYPOINT /usr/local/bin/run.sh,那么之后做的镜像(FROM:)的Dockerfile里如果不指定ENTRYPOINT,而是指定CMD,那么这个CMD虽然从inspect里看是存在的,但却是无效的。
本条目发布于。属于分类。作者是。
本站正在使用主机}

我要回帖

更多关于 psv日版和港版区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信