Docker 容器可以秒级启动,只加载每个容器变化的部分
Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker容器。
Docker 容器的运行不需要额外的 hypervisor支持,它是内核级的虚拟化、操作系统级的虚拟化
Docker 容器几乎可以在任意的平台上运行,更轻松的迁移和扩展
Docker 使用客户端-服务器架构模式。客户端会与 Docker 守护进程通过 socket 或者 RESTful API 进行通信。
快速创建容器,直接使用容器部署代码,所有的修改都以增量的方式被分发和更新,更快速的交付和部署
Docker主要针对Paas平台,是以应用为中心。
OpenStack主要针对Iaas平台,以资源为中心。
可以保证线下的开发环境、测试环境和线上的生产环境一致。
开发直接在容器里开发,提测的时候把整个容器给测试,测好了把改动改在容器里再上线就好了。
Docker 的容器利用 LXC(LinuX Containers),
使用 kernel的namespace 来做权限控制和隔离、网络管理,
使用 cgroups 实现对资源的配额和度量(但是从限制用户能使用的磁盘大小和网络带宽上还是非常有限),
通过 aufs 来提高文件系统的资源利用率,以递进的方式创建"VM",就像使用git增量开发一样提供版本控制。
LXC所实现的隔离性主要是来自kernel的namespace,
其中pid, net, ipc, mnt, uts, user等namespace将container的进程、网络、消息、文件系统、UTS、用户隔离,对外展现出一个独立计算机的能力。
虚拟化需要解决的主要是以下4个问题:
隔离性 - 每个用户实例相互隔离互不影响。硬件虚拟化是VM, LXC是container,更细一点是kernel namespace
可配额/可度量 - 每个用户实例可以按需提供其计算资源,所使用的资源可以被计量。硬件虚拟化因为虚拟了CPU, memory可以方便实现, LXC则主要是利用cgroups来控制资源
移动性 - 用户实例可以很方便地复制、移动和重建。硬件虚拟化提供snapshot和image来实现,docker主要利用AUFS实现
安全性 - 这里强调是host主机的角度尽量保护container。硬件虚拟化虚拟化水平高,用户进程都是在KVM等虚拟机中运行, LXC的进程是lxc-start进程的子进程, 只在Kernel的namespace中隔离, 因此需要一些kernel的patch来保证用户运行环境不会受到来自host主机的恶意入侵。
Docker 三个基本概念
镜像(Image)用来创建 Docker 容器,只读模板。
容器(Container)容器是从镜像创建的运行实例。
可以把容器看做是一个简版Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行其中的应用程序。
仓库(Repository)集中存放镜像文件的场所,每个镜像有不同的标签(tag)。
Docker 四种网络模式
host 模式,使用 --net=host 指定,和宿主机共用一个 Network Namespace。
container 模式,使用 --net=container:container1 指定,和指定容器共享IP、端口
none 模式,使用 --net=none 指定,不进行任何网络配置
bridge 模式,使用 --net=bridge 指定,默认设置,分配 Network Namespace,
当 Docker server 启动时,会在主机上创建一个名为 docker0 的虚拟网桥(虚拟网卡),此主机上启动的容器会连接到这个docker0。
Docker 会选择一个和宿主机不同的IP地址和子网分配给 docker0,连接到 docker0 的容器就从这个子网中选择一个未占用的 IP 使用。
如一般 Docker 会使用 172.17.0.0/16 这个网段,并将 172.17.42.1/16 分配给 docker0 网桥。
单主机容器之间的通信可以通过 docker0,
跨主机容器之间通过 pipework 新建容器的网卡桥接 br0,这样跨主机容器之间就可以通信了。
Docker 的基本构成
Docker 三个基本概念
Docker Images 与 Containers 的关联与差异
Dcoker 实现原理总结
Docker Registry(仓库)工作流
Docker Commands(命令行)使用
Docker 容器通信
Docker 集群组网与管理
Docker 安全漏洞与规避
【安装docker】
1、确认linux版本支持
2、区分系统,更新APT镜像源(Ubuntu)、yum软件源(CentOS)
安装 apt-transport-https 包支持https协议的源
添加Docker的官方apt软件源,更新apt软件包缓存
3、区分版本,更新内核或安装软件包
4、安装docker
sudo apt-get install docker-engine
5、创建docker组,检验安装结果
sudo groupadd docker
sudo gpasswd -a user1 docker
sudo service docker restart
docker version
【docker命令】
使用镜像 ID或仓库名:标签名docker.cn/docker/centos:centos6
docker version
docker info
docker ps ------查看最近启动的容器
docker images
docker inspect image1 | container1 ------检查镜像或者容器信息
docker logs -f container1
docker start | stop | restart | pause | unpause | kill container1
docker rm -f container1
docker rm $(docker ps -aq) ------删除所有容器
docker rmi -f image1
docker rmi $(docker images | grep none | awk '{print $3}' | sort -r) ------删除所有镜像
docker run <相关参数> <镜像 ID> <初始命令> ------运行新容器
docker run -it --name container1 image1 ------运行容器
docker run -it -v /data1 image1 ------添加数据卷,可在容器间共享和重用
docker inspect container1 ------查看宿主机对应路径
docker run -it -v /var/image1/data1:/data1 image1 ------挂载宿主机目录为一个数据卷
docker run -d -P --name web1 --link db1:webdb1 image1 ------链接web 容器到db 容器,这样允许 web 容器访问 db 容器的信息
------一个链接允许一个源容器提供信息访问给一个接收容器,Docker 创建了一个安全隧道而不需要对外公开任何端口给外部容器
docker inspect -f "{{ .HostConfig.Links }}" web1 ------查看 web 容器的链接关系
docker run --expose ------提供容器之间的端口访问
docker run -p ------允许外部主机访问容器的端口
docker save image1 > tar1.tar ------镜像保存后加载(不会丢失提交历史和层,可以回滚)
docker save -o xx.tar 192.168.1.2:123/xx:1.0
scp xx.tar ubu@192.168.1.123:~/user1/xx_files/
docker load < tar1.tar
docker export image1 > tar1.tar ------镜像导出后导入(会丢失提交历史和层,不可回滚)
docker import < tar1.tar
docker cp 7bb0e258aefe:/etc/debian_version . ------拷贝容器7bb0e258aefe中的/etc/debian_version到当前目录下
docker build -t image1 /dir1/Dockerfile ------构建镜像
docker build -t image1 . ------当前目录下包含Dockerfile。
docker push 192.168.1.123:123/xx:4.0 ------推送镜像
docker pull image1 repository:tag1 ------拉取镜像
docker tag image1 repository:tag1 ------标记镜像
docker commit container1 [REPOSITORY[:TAG]]
注意:不要直接将修改保存到docker run启动的镜像中去,这样就将之前的启动基底镜像覆盖了,一定要注意备份!!!
推荐方法:可以另外起一个tag,类似于版ifconfig本号。
docker exec -it container1 bash ------在指定容器上运行程序
brctl show ------当前主机网桥
ifconfig docker0 ------当前 docker0 ip
【Dockerfile】
FROM ubuntu ------基于哪个镜像,可出现多次(创建多个镜像)
RUN "executable", "param1", "param2" ------构建镜像时执行
------每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,
------后续的RUN都在之前RUN提交后的镜像为基础,镜像是分层的,可以通过一个镜像的任何一个历史提交点来创建,类似源码的版本控制。
------镜像构建过程中每执行一次指令 Docker 会寻找是否有存在的镜像缓存可复用,指令会对比所有的子镜像寻找是否执行相同的指令,如果没有则创建新的镜像。
------避免使用RUN apt-get update独立成行,否则如果后续包有更新,那么也不会再执行更新(缓存匹配了命令)
------避免使用RUN apt-get upgrade,很多包在一个非privileged权限的容器里是无法升级的。如果知道某个包更新,使用apt-get install -y xxx
------ADD和COPY指令除外,执行ADD和COPY时存放到镜像的文件也是需要检查的
------RUN产生的缓存在下一次构建的时候会被重用,使用--no-cache=true选项不使用缓存
------为了有效地利用缓存,你需要保持你的 Dockerfile 一致,并且尽量在末尾修改。
------为保持可读性把长或者复杂的语句使用\分隔符分成多行
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update \
&& apt-get install -y nginx
RUN rm -v /etc/nginx/nginx.conf
ADD nginx.conf /etc/nginx/
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
EXPOSE 443 ------容器对外映射的本地端口,需要在 docker run 的时候使用-p或者-P选项生效
------docker run -d -p 127.0.0.1:7443:443 image1
CMD service nginx start ------容器启动时执行,但一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条
CMD echo "can be replaced"
ENTRYPOINT echo "can not be replaced" ------容器启动时执行的命令,但一个Dockerfile中只能有一条ENTRYPOINT命令,多条则只执行最后一条
------启动容器时指定了运行命令,则会覆盖掉CMD指定的命令,但ENTRYPOINT不会
ENV name="tom" pass="123"------设置环境变量,会被后续RUN指令使用
ADD /dir1 /dir1------复制本地主机文件或者远程文件URL到容器,比COPY命令支持tar文件自动解包和远程 URL,URL推荐使用 curl 或者 wget 替换
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.gz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
------路径必须是 Dockerfile 所在路径的相对路径,不存在会自动创建目录,如果是目录只会复制目录下的内容,目录本身不会被复制
VOLUME /dir1 ------挂载文件夹到容器,让容器访问宿主机目录
WORKDIR /opt/onframework/ ------指定命令的运行目录,作用于后续的RUN、CMD、ENTRYPOINT指令
USER daemon ------指定运行容器的用户,作用于后续的RUN、CMD、ENTRYPOINT指令
ONBUILD RUN echo "from base image" ------配置该镜像作为其它新镜像的基础镜像时所执行的指令,相当继承到新Dockerfile的构建命令中
拷贝镜像
1 在节点A查看运行nginx镜像的容器Id:docker ps:0bc49f107ff1
2 将镜像打包 docker export 0bc49f107ff1 > nginx.tar
3 将镜像压缩文件传输到其他节点 scp ./nginx.tar root@192.168.1.123:/root/images/
4 在节点B将镜像导入 cat nginx.tar | docker import - nginx
5 重新创建容器
【Murano】
提供应用目录服务,实现服务与应用程序的一键发布、快速部署和生命周期管理,就像app store。
基本流程是通过heat 模板创建虚拟机,再将应用部署在虚拟机内。
1个环境包含多个应用,环境是1个部署单元,不同环境中的应用独立不相关,部署环境使用heat模板。
manifest.yaml #Murano应用的入口点
->/Classes/xx.yaml #在应用中所有的类和文件的映射
->/Resources/xx.template #murano代理部署应用的说明
->/Resources/scripts/xx.sh
->/UI/ui.yaml #murano代理部署应用的创建向导
【Kolla 】
使用Docker容器快速部署升级OpenStack服务。
为OpenStack的每一个服务都创建一个对应的Docker Image,
通过Docker Image将升级的粒度减小到Service级别,从而使升级时,对OpenStack影响能达到最小。
升级只需要三步:Pull新版本的容器镜像,停止老版本的容器服务,然后启动新版本容器。
回滚也不需要重新安装包了,直接启动老版本容器服务就行。
使用Jinja2模板语言,增强Dockerfile语法
【YAML】
在YAML文件中要避免 tab键,包含了 tab键将无法正常的解析。
【puppet/chef】
【Ansible】
是一种配置管理、安装部署的工具。批量的在远程服务器上执行命令 。
在管理节点将 Ansible 模块通过 SSH 协议等推送到被管理端执行,执行完之后自动删除。
【Kubernetes】
简称k8s,容器集群管理和服务编排工具
k8s的节点只有两种角色:master和minion,
对比Docker swarm集群,master相当于docker swarm集群中的manager,而minion则相当于docker swarm集群中的worker。
在master节点的k8s核心组件包括:
# ls /opt/bin|grep kube
kube-apiserver
kube-controller-manager
kubelet
kube-proxy
kube-scheduler
在minion节点的k8s核心组件较少包括:
# ls /opt/bin|grep kube
kubelet
kube-proxy
【Paas】
PaaS上的应用适合快速原型的展现,和短期应用的尝试,不适合深入调优、维护。
dotcloud、heroku以及cloudfoundry都试图通过container来隔离提供给用户的runtime和service,
只不过dotcloud采用docker, heroku采用LXC, cloudfoundry采用 自己开发的基于cgroup的warden。
基于轻量级的隔离机制提供给用户PaaS服务是比较常见的做法。