标签 docker 下的文章
标签 docker 下的文章
整理自《Docker容器与容器云》一书。
将普通用户加入docker用户组:
$ sudo usermod -aG docker your-user
$ docker run --ulimit nofile=1024:1024 --ulimit nproc=1024:1024 --rm debian ulimit -n
源容器(带volume):
$ docker run -it --name vol_simple -v /data ubuntu /bin/bash
1)备份
备份源容器的volume:(启动一个临时容器)
$ docker run --rm --volumes-from vol_simple -v $(pwd):/backup ubuntu tar cvf /backup/data.tar /data
2)恢复
新容器:
$ docker run -it --name vol_bck -v /data ubuntu /bin/bash
恢复源容器的数据到新容器:(启动一个临时容器)
$ docker run --rm --volumes-from vol_bck -v $(pwd):/backup ubuntu tar xvf /backup/data.tar -C /
容器实际上是一个进程,显然我们不会在进程里再启动一个SSH服务器。
Docker提供了 docker exec 命令,可以在已运行的容器中执行想要的命令,并得到反馈的结果。这个命令实际上可以解决大部分需要ssh进入容器的问题,同样也可以解决诸如定时任务等问题。
对于需要进入容器修改配置文件的需求:
如果需要长期使用这份配置文件,它应该被集成到镜像中
如果需要经常修改这份配置文件,那么应该使用volume共享这份配置
对于某些特殊需求需要进入容器,如程序调试等,则可以使用docker exec 直接在容器中启动一个shell:
$ docker exec -it <containerName> /bin/bash
容器的stdout和stderr 输出存在了 /var/lib/docker/containers/<containerID>/<containerID>-json.log 文件下( /var/lib/docker/ 即 docker graph 目录),docker logs 命令就是从这里读取日志的。
docker logs存在的问题:
JSON消息格式存储,日志文件增长过快
日志文件没有自动切分功能(待验证)
docker logs命令返回的日志记录也过于冗长
主流解决方案,3种:
在容器内收集:
容器内启动一个日志收集进程
需要定制Docker镜像,典型代表为 baseimage-docker 项目
在容器外收集:
宿主机上运行一个单独收集日志的代理,收集所有容器的日志
容器挂载 volume 数据卷,把日志记录在挂载卷中
也可以直接处理 docker graph 目录下的容器日志,开源项目Fluentd
在专用容器中收集:
在宿主机运行日志收集代理的变种方案,该代理运行在一个容器中
且该容器的volume 使用docker run 的 --volumes-from 选项被绑定给其他应用程序容器
参考 Docker and Logstash 一文
环境说明:Centos 7.1 64Bit + Docker 1.9.1,仓库的存储以使用本地磁盘为例。
官方部署指南:Deploying a registry server
由于v1版本的registry要被官方废弃了,所以我们选择安装v2版本。(注:v2版本需要TLS加密连接)
创建一个 certs 目录:
$ mkdir -p certs
然后将仓库域名在权威机构申请的证书 crt 文件放入并命名为certs/domain.crt,将 key 文件放入并命名为 certs/domain.key。
如果使用私有证书,可以这么创建:
$ mkdir -p certs && openssl req \ -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ -x509 -days 365 -out certs/domain.crt
为了让 docker 客户端信任私有证书,需要将证书文件放入使用该仓库的所有 docker 客户端的服务器上:
以仓库所在的 docker 本机为例:
$ sudo mkdir /etc/docker/certs.d/docker-hub.yourdomain.com:5000/ -p $ sudo cp certs/domain.crt /etc/docker/certs.d/docker-hub.yourdomain.com\:5000/ca.crt
使用 htpasswd 命令生成密码文件前,需要先安装 httpd-tools 。另外 htpasswd 授权必须配合TLS一同使用,并且只支持 bcrypt 格式的密码。
创建 htpasswd 密码文件,并添加一个用户user1
$ mkdir auth $ htpasswd -cB auth/htpasswd user1
再添加一个用户user2
$ htpasswd -B htpasswd user2
$ docker pull registry:2 $ docker run -d --net=host --restart=always --name registry \ -v `pwd`/data:/var/lib/registry \ (注:仓库的数据目录) -v `pwd`/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -v `pwd`/certs:/certs \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ registry:2
$ docker pull ubuntu $ docker tag ubuntu docker-hub.yourdomain.com:5000/ubuntu:latest $ docker login -u user1 -p yourpasswd -e "your@email-address.com" docker-hub.yourdomain.com:5000 $ docker push docker-hub.yourdomain.com:5000/ubuntu:latest $ docker pull docker-hub.yourdomain.com:5000/ubuntu:latest
一般来说,我们在自定义Docker与外部网络通信的网络,除了NAT,还有Linux Bridge、Open vSwitch、MacVLAN几种选择。MacVLAN相对于前两者,拥有更好的性能。
macvlan可以看做是物理网卡的子接口,每个macvlan子接口有其自己的MAC地址(跟物理网卡的也不同),而且可以为每个macvlan子接口设置IP地址。
即在同一个物理网卡上设置多个不同的IP+MAC地址的子接口,我们称macvlan子接口所依附的物理网卡为lower device。
MacVLAN有4种模式,参考这里。 VEPA需要接入交换机支持hairpin mode。相对而言,Bridge mode更加常用。
macvlan可以工作在四种模式下:
VEPA(Virtual Ethernet Port Aggregator)mode:default 模式,If the lower device receives data from a macvlan in VEPA mode, this data is always sent "out" to the upstream switch or bridge, even if it's destined for another macvlan in the same lower device.
Brideg mode:this works almost like a traditional bridge, in that data received on a macvlan in bridge mode and destined for another macvlan of the same lower device is sent directly to the target (if the target macvlan is also in bridge mode), rather than being sent outside.
Private mode:this is essentially like VEPA mode, but with the added feature that no macvlans on the same lower device can communicate, regardless of where the packets come from (so even if inter-VM traffic is sent back by a hairpin switch or an IP router, the target macvlan is prevented from receiving it).
Passthru mode:this mode was added later, to work around some limitation of macvlans (more details here ).
MACVLAN工作方式补充:
有时我们可能需要一块物理网卡绑定多个 IP 以及多个 MAC 地址,虽然绑定多个 IP 很容易,但是这些 IP 会共享物理网卡的 MAC 地址,可能无法满足我们的设计需求,所以有了 MACVLAN 设备,其工作方式如下:
MACVLAN 会根据收到包的目的 MAC 地址判断这个包需要交给哪个虚拟网卡。单独使用 MACVLAN 好像毫无意义,但是配合容器的 network namespace 使用,我们可以构建这样的网络:
由于 macvlan 与 eth0 处于不同的 namespace,拥有不同的 network stack,这样使用可以不需要建立 bridge 在 virtual namespace 里面使用网络。
最小安装 + 基本开发包(Minimal Install + Development Tools) 即可。
# wget http://elrepo.org/linux/kernel/el7/x86_64/RPMS/kernel-ml-4.2.5-1.el7.elrepo.x86_64.rpm # rpm -ivh kernel-ml-4.2.5-1.el7.elrepo.x86_64.rpm
查看启动项
# cat /boot/grub2/grub.cfg |grep menuentry menuentry 'CentOS Linux (4.2.5-1.el7.elrepo.x86_64) 7 (Core)' --class centos ... menuentry 'CentOS Linux (3.10.0-229.20.1.el7.x86_64) 7 (Core)' --class centos ... # cat /boot/grub2/grubenv //这里记录了默认启动项 # GRUB Environment Block saved_entry=CentOS Linux (3.10.0-229.20.1.el7.x86_64) 7 (Core)
修改默认启动内核为4.2.5:
# grub2-set-default 'CentOS Linux (4.2.5-1.el7.elrepo.x86_64) 7 (Core)' # grub2-editenv list saved_entry=CentOS Linux (4.2.5-1.el7.elrepo.x86_64) 7 (Core)
3)开启 User namespaces
# grubby --args="user_namespace.enable=1" --update-kernel=/boot/vmlinuz-4.2.5-1.el7.elrepo.x86_64 检查一下,应该已经在 boot command line 上加上启动参数了: # grep user_namespace /boot/grub2/grub.cfg # reboot
# vi /etc/selinux/config SELINUX=disabled # reboot
改用传统的iptables-service 来管理iptables规则
# systemctl stop firewalld # systemctl disable firewalld # yum install iptables-services # systemctl disable iptables.service //不需要启用这个服务,docker会自动启动iptables
# wget -qO- https://get.docker.com/ | sh
# systemctl list-unit-files |grep [d]ocker # systemctl enable docker.service
官网的建议方法如下:(好处是不用修改docker的systemd配置文件,这样在docker升级后不用重新修改该文件)
# mkdir /etc/systemd/system/docker.service.d/ # vi /etc/systemd/system/docker.service.d/docker.conf (注意这个文件名,不能是 docker 或者 docker.service ) [Service] ExecStart= ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay (这段启动命令从 /usr/lib/systemd/system/docker.service 拷贝而来,再加入我们需要的启动参数即可) # systemctl daemon-reload # systemctl start docker
老方法(不建议了):
*************************************************************************************************
# vi /usr/lib/systemd/system/docker.service [Service] EnvironmentFile=-/etc/sysconfig/docker (加入这一行) Type=notify ExecStart=/usr/bin/docker daemon -H fd:// $OPTIONS (加入$OPTIONS) # vi /etc/sysconfig/docker OPTIONS="--storage-driver=overlay" # systemctl daemon-reload # systemctl start docker
*************************************************************************************************
# vi /usr/local/bin/docker-pid #!/bin/sh exec docker inspect --format '{{ .State.Pid }}' "$@" -- # vi /usr/local/bin/docker-ip #!/bin/sh exec docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$@" # chmod 755 /usr/local/bin/docker-*
# docker run hello-world
附:官方提供了内核环境的检查脚本 docker/contrib/check-config.sh ( wget raw_file )