此部分贴一篇本站博主的博客,个人觉得写的特别好!
docker入门(利用docker部署web应用)_仰望星空-CSDN博客_docker部署前言:本课程是在慕课网上学习 第一个docker化的java应用 课程时所做的笔记,供本人复习之用目录第一章 什么是docker1.1 docker的发展史1.2 docker国内应用史1.3 什么是Docker第二章 了解docker2.1 docker思想2.1.1 集装箱2.1.2 标准化2.1.3 隔离2.2 docker解决的问题2.2.1...https://blog.csdn.net/q610376681/article/details/90483576?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163642958516780264064864%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163642958516780264064864&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-90483576.first_rank_v2_pc_rank_v29&utm_term=docker&spm=1018.2226.3001.4187
docker官网:Container Runtime with Docker Engine | Dockerhttps://www.docker.com/products/container-runtime?spm=a2c6h.13651104.0.0.6d9072ffL2HnED
安装docker
配置docker-ce软件仓库
此时yum install -y docker-ce会报错提示需要安装相关依赖包
配置所需依赖包的软件仓库
安装完成并启用docker
以上所需软件仓库源均可从阿里镜像站获取阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区阿里巴巴开源镜像站,免费提供Linux镜像下载服务,拥有Ubuntu、CentOS、Deepin、MongoDB、Apache、Maven、Composer等多种开源软件镜像源,此外还提供域名解析DNS、网络授时NTP等服务,致力于为互联网用户提供全面,高效和稳定的基础服务。https://developer.aliyun.com/mirror/?spm=5176.21213303.1173276.2.46023edaJVD1rb&scm=20140722.S_card@@%E5%8D%A1%E7%89%87@@1438._.ID_card@@%E5%8D%A1%E7%89%87@@1438-RL_%E9%95%9C%E5%83%8F-OR_ser-V_2-P0_0
docker版本查看及告警解决
查看docker版本
使用docker info查看docker的系统范围信息时出现告警
解决方法
再次执行docker info后可以看到告警解除
docker容器简单运用在官方公共仓库Docker Hub中搜索镜像
拉取镜像
运行容器
##第一个80:容器宿主机的端口;第二个80:容器的映射端口
此时浏览器访问宿主机的效果为:
删除运行中的容器
先终止容器之后删除容器
容器的端口映射
将容器宿主机的8080端口映射至容器的8080端口
浏览器访问:
docker镜像的分层结构
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、环境变量和配置文件
Docker镜像是由文件系统叠加而成;最底端是一个引导文件系统(bootfs),这很像典型的Linu/Unix的引导文件系统;Docker用户几乎永远不会和引导文件系统有什么交互,实际上,当一个容器启动后,它将会被移到内存中,而引导文件系统则会被卸载(umount),以留出更多的内存供initrd磁盘镜像使用
到目前为止,Docker看起来还很像一个典型的Linux虚拟化栈;实际上,Docker镜像的第二层是root文件系统(rootfs),它位于引导文件系统之上;rootfs可以是一种或多种 *** 作系统(如Debian或者Ubuntu文件系统)
在传统的Linux引导过程中,root文件系统会最先以只读的方式加载,当引导结束并完成了完整性检查之后,它才会被切换为读写模式;但是在Docker里,root文件系统永远只能是只读状态,并且Docker利用联合加载(union mount)技术又会在root文件系统层加载更多的只读文件系统;联合加载指的是一次同时加载多个文件系统,但是在外面看起来只能看到一个文件系统,联合加载会将各层文件系统叠加到一起,这样最终的文件系统会包含所有底层的文件和目录
Docker将这样的文件系统称为镜像,一个镜像可以放到另一个镜像的顶部,位于下面的镜像称为父镜像(parent image),可以依次类推,直到镜像栈的最底部,最底部的镜像称为基础镜像(base image);最后,当从一个镜像启动容器时,Docker会在该镜像的最顶层加载一个读写文件系统,我们想在Docker中运行的程序就是在这个读写层中执行的
当Docker第一次启动一个容器时,初始的读写层是空的,当文件系统发生变化时,这些变化都会应用到这一层上;比如,如果想修改一个文件,这个文件首先会从该读写层下面的只读层复制到该读写层,该文件的只读版本依然存在,但是已经被读写层中的该文件副本所隐藏
通常这种机制被称为写时复制(copy on wrte),这也是使Docker如此强大的技术之一;每个只读镜像层都是只读的,并且以后永远不会变化,当创建一个新容器时,Docker会构建出一个镜像栈,并在栈的最顶端添加一个读写层,这个读写层再加上其下面的镜像层以及一些配置数据,就构成了一个容器;容器是可以修改的,它们都有自己的状态,并且是可以启动和停止的;容器的这种特点加上镜像分层框架(image-layering famework),使我们可以快速构建镜像并运行包含我们自己的应用程序和服务的容器
导入本地base镜像并查看其历史
使用base镜像运行容器后可以发现容器共享了宿主机的kernel、dns
base镜像提供的是最小的Linux发行版;同一docker主机支持运行多种Linux发行版本;采用分层结构的最大好处是共享资源
docker构建镜像1、使用busybox构建基础镜像
busybox是一个集成了一百多个最常用linux命令和工具的软件,它甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小;我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍;在嵌入式linux应用中,busybox有非常广的应用,另外,大多数linux发行版的安装程序中都有busybox的身影,安装linux的时候同时按下ctrl+alt+F2就能得到一个控制台,而这个控制台中的所有命令都是指向busybox的链接;busybox的小身材大作用的特性,给制作一张软盘的linux带来了极大便利
拉取busybox镜像,查看所有本地镜像
docker commit方式构建新镜像三部曲:运行容器--->修改容器--->将容器保存为新的镜像
使用新镜像运行容器
镜像的删除
2、Dokerfile构建镜像
创建存放Dockerfile的目录并编写Dockerdile内容
docker build方式构建镜像,测试使用此镜像运行容器
docker commit与docker build两种方式构建镜像的对比
##commit方式所构镜像
##build方式所构镜像
由上可见docker commit方式构建镜像的弊端有:
使用docker commit意味着所有对镜像的 *** 作都是黑箱 *** 作,生成的镜像也被称为黑箱镜像;换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知;而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的 *** 作步骤,虽然或许可以从docker diff得到一些线索,但是远远不到可以确保生成一致镜像的地步,且这种黑箱镜像的后期维护工作是非常痛苦的
此外,镜像所使用的分层存储中,除当前层之外的每一层都是不会发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层;如果使用docker commit制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到,这会让镜像变得臃肿
docker build方式构建镜像的优点:
能够自由灵活的与宿主机联系,比如,某些配置文件在宿主机验证并使用过后很好用,那么,可以将文件copy到镜像中,add远程主机的配置文件到镜像中,定义onbuild动作等等各种灵活的功能;docker commit不能做到这些事情,因为是在一个封闭的在运行中的容器中,无法做复制宿主机文件;dockerfile本身就是一个比较详细的构建文档,有这个文档就可以清楚的知道新构建的镜像经历了怎样的变化,没有黑箱 *** 作的困扰了,后期的维护更为方便
而docker build的每一步构建出来的镜像就是通过docker commit得来的
3、镜像的缓存特性
在构建映像的过程中,docker将按照指定的顺序逐步执行Dockerfile中的指令,随着每条指令的检查,docker将在其缓存中查找可重用的现有映像,而不是创建一个新的(重复)映像,如果用户不想使用缓存,可以在docker build命令中使用--no-cache = true选项
docker将遵循的基本规则如下:
从已经在缓存中的父镜像开始,将下一个指令与从该基本镜像导出的所有子镜像进行比较,以查看其中一个是否使用完全相同的指令构建,如果没有,则缓存无效
在大多数情况下,只需将Dockerfile中的指令与其中一个子镜像进行比较即可(通过比较是否与上一次执行的指令一致);但是,某些指令需要一些额外的检查,对于ADD和COPY指令,将检查镜像中文件的内容,并为每个文件计算校验和,在这些校验和中不考虑文件的最后修改和最后访问的时间;在缓存查找期间,将校验和与现有映像中的校验和进行比较,如果文件(如内容和元数据)中有任何变化,则缓存无效
除了ADD和COPY命令之外,缓存检查将不会查看容器中的文件来确定缓存匹配,例如,当处理RUN yum install -y gcc命令时,不会检查在容器中更新的文件以确定是否存在高速缓存命中,它将只会检查命令字符串是否与之前的一致来判断是否匹配
一旦某一层的缓存无效,所有后续的Dockerfile命令将生成新的镜像,并且高速缓存将不被使用
##可以看到在构建test:lv2镜像时的第2、3步使用了test:lv1镜像的缓存,镜像ID能够一一对应
4、Dockerfile详解
Dockerfile常用指令:
FROM:指定base镜像,如果本地不存在会从远程仓库下载
MAINTAINER:设置镜像的作者,比如用户邮箱等
COPY:把文件从镜像构建环境(构建镜像时的当前路径)复制到镜像,支持两种形式:COPY src dest 和 COPY ["src", "dest"] ;src必须指定镜像构建环境中的文件或目录
ADD:用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像:ADD html.tar /var/www && ADD http://ip/html.tar /var/www
ENV:设置环境变量,变量可以被后续的指令使用:ENV HOSTNAME sevrer1.example.com
EXPOSE:如果容器中运行应用服务,可以把服务端口暴露出去:EXPOSE 80
VOLUME:申明数据卷,通常指定的是应用的数据挂载点:VOLUME ["/var/www/html"]
WORKDIR:为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建
RUN:在容器中运行命令并创建新的镜像层,常用于安装软件包:RUN yum install -y vim
CMD & ENTRYPOINT:这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run命令行后接的内容覆盖,而ENTRYPOINT不会被忽略,一定会被执行;docker run后面的参数可以传递给ENTRYPOINT指令当作参数;Dockerfile中只能指定一个ENTRYPOINT,如果指定了多个,只有最后一个生效
Dockerfile的简单应用:
##编写Dockerfile内容
##构建新镜像
##查看镜像及其分层结构,此时因为镜像层级增加,镜像大小也跟着增加
##在容器中向应用数据挂载点中导入数据
##在容器运行状态下新开shell查看容器中数据在宿主机中的路径
##在容器运行宿主机删除挂载数据
##容器中的数据被删除
Dockerfile的shell和exec书写格式:
##shell格式书写
##shell格式底层会调用/bin/sh -c来执行命令,可以解析变量
##exec格式书写
##exec格式不会调用/bin/sh -c来执行命令,无法解析变量
##在exec格式的Dockerfile中调用/bin/sh -c来解析变量
##变量被成功解析并输出
##exec格式书写Dockerfile
##exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换
##shell格式书写Dockerfile
##在shell格式时,ENTRYPOINT会忽略任何CMD或docker run提供的参数
官方推荐使用exec格式书写
5、镜像的优化
镜像的优化主要指的是镜像大小的优化,优化即对镜像进行瘦身;小镜像的优点有:
+++ 加速构建/部署:虽然存储资源较为廉价,但网络IO是有限的,在带宽有限的情况下,部署一个 1G的镜像和10M的镜像带来的时间差距可能就是分钟级和秒级的差距,特别是在出现故障,服务被调度到其他节点时,这个时间尤为宝贵
+++ 提高安全性,减少攻击面积:越小的镜像表示无用的程序越少,可以大大的减少被攻击的目标
+++ 减少存储开销
镜像的优化主要从以下几个方面出发:
+++ 选择最精简的基础镜像
+++ 减少镜像的层数
+++ 清理镜像构建的中间产物
+++ 注意优化网络请求
+++ 尽量去用构建缓存
+++ 使用多阶段构建镜像
##编写Dockerfile构建一个nginx镜像
##使用此镜像运行容器进行测试
##拉取nginx官方镜像后查看本地所有镜像,发现我们构建的这个镜像比官方大很多;这种情况那就是建了个寂寞,还不如直接从官方镜像仓库进行拉取来的方便
##查看构建的nginx:lv1镜像与官方镜像的分层结构区别
##从减少镜像的层数、清理镜像构建的中间产物方面出发进行优化
##此次优化较lv1版本容量缩小了接近三分之一
##使用多阶段构建镜像进行优化之使用ubuntu基础镜像
##此次优化较lv2(图中标签为none)版本容量缩小了接近80%
##使用多阶段构建镜像进行优化之使用rhel7基础镜像
##此次优化较lv2(图中标签为none)版本容量缩小了接近二分之一
因为ubuntu镜像中缺少nginx命令执行所需的一个动态链接库;会导致使用此版本镜像的容器运行nginx失败;厂家在制作Linux发行版时经常需要判断某条命令需要哪些共享库文件的支持,以确保指定的命令在独立的系统内可以可靠的运行
接下来从使用最精简的base镜像进行对构建镜像的优化
##上传本地精简base镜像
##编写Dockerfile
##构建镜像并查看,此次构建的镜像只有区区32M;所以在实际构建中尽量选择最精简的base镜像
##使用此镜像运行容器并测试,nginx成功运行
Docker仓库docker仓库是用来包含镜像的位置,docker提供一个注册服务器(Register)来保存多个仓库,每个仓库又可以包含多个具备不同tag的镜像;docker运行中使用的默认仓库是Docker Hub公共仓库
Docker Hub是docker公司维护的公共仓库,用户可以免费使用,也可以购买私有仓库;为了区分不同用户的同名镜像,要求镜像的格式是:[username]/xxx:tag],例:yakexi007/busybox:latest
本部分主要介绍私有仓库的搭建及配置,公共仓库搭建可前往
Docker Hubhttps://hub.docker.com/注册账号后即可搭建公共仓库
1、配置镜像加速
从Docker Hub上下载镜像的速度太慢,需要配置镜像加速,这里以阿里云为例:(需要提前注册阿里云帐号)
##将阿里云提供的镜像加速添加至docker daemon文件中,重新加载docker
##docker info中可以查看到此项内容
2、搭建私有仓库
Docker Hub虽然方便,但是还是有限制:需要internet连接,速度慢;所有人都可以访问,不安全;由于安全原因,企业不会允许将镜像放到外网
好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库;所谓私有仓库,也就是在本地(局域网)搭建的一个类似公共仓库的东西,搭建好之后,我们可以将镜像提交到私有仓库中,这样我们既能使用Docker来运行和局域共享我们的项目镜像,也避免了商业项目暴露出去的风险
首先拉取官方的registry镜像,使用此镜像来搭建私有镜像仓库
##此处本人使用了加速进行的下载,效果很好
##使用registry镜像运行容器
##上传镜像到本地仓库,本地镜像在命名时需要加上仓库的IP和端口
##测试:删除本地所有大小为32M的nginx镜像后,重新拉取本地镜像仓库中的资源,还是原来那个,镜像ID没有改变
之前使用registry运行容器时做了端口映射,那么容器宿主机会打开5000端口监听所有
我们还可通过浏览器或者curl命令来测试本地的私有仓库是否搭建成功
v2可能是registry的版本号,可通过以下方式查看
至此,我们的私有仓库就已经搭建完成了;后续会有一些对于此仓库的额外的配置部分,在进行这一部分实验前,先来缕一缕registry的工作原理
3、Registry工作原理
Docker Registry有三个角色:index、registry和registry client
index:负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息;Web UI+元数据存储+认证服务+符号化
registry:是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证
registry client:docker充当registry客户端来维护推送和拉取,以及客户端的授权
一次docker pull或push背后发生的事件:
index服务主要提供镜像索引以及用户认证的功能;当下载一个镜像的时候,首先会去index服务上做认证,然后查找镜像所在的registry的地址并返回给docker客户端,docker客户端再从registry下载镜像,在下载过程中registry会去index校验客户端token的合法性,不同镜像可以保存在不同的registry服务上,其索引信息都放在index服务上
三种情景:
4、私有仓库的安全配置
为Docker仓库添加证书加密功能:
##升级openssl版本
##生成证书
##在主机上解析域名westos.org
##重新创建容器并运行
##推送镜像测试:失败
##拷贝证书至docker主机
##再次推送镜像策测试:成功
为Docker仓库添加用户认证功能:
##生成用户密码文件
##重新创建容器并运行
##推送镜像测试:失败
##docker主机登陆认证后成功推送镜像
Harbor仓库Harbor是一个用于存储Docker镜像的企业级Registry服务;Registry是Dcoker官方的一个私有仓库镜像,可以将本地的镜像打标签进行标记然后push到以Registry起的容器的私有仓库中;企业可以根据自己的需求,使用Dokcerfile生成自己的镜像,并推到私有仓库中,这样可以大大提高拉取镜像的效率
Harbor的所有服务组件都是在Docker中部署的,官方安装使用Docker-compose快速部署,所以需要安装Docker、Docker-compose;由于Harbor是基于Docker Registry V2版本,所以就要求Docker版本不小于1.10.0,Docker-compose版本不小于1.6.0
harboe仓库的搭建:
##安装docker-compose;配置harbor
##安装并启动harbor
至此,harbor仓库即搭建完成,在浏览器中访问配置了harbor的docker主机即可
harbor仓库的使用:
##上传本地镜像至harbor仓库
##将仓库镜像资源指向harbor仓库
##下载镜像,根据镜像ID可知此镜像即为刚才上传至harbor仓库的那一个
##新建项目,访问级别为不公开;当项目设为公开后,任何人都有此项目下镜像的读权限,命令行用户不需要docker login就可以拉取此项目下的镜像
##上传镜像至此新项目
##创建harbor用户
##在westos项目添加成员
##通过此项目成员认证westos项目进行镜像上传,而不能通过此成员往library项目中上传镜像
harbor仓库对于harbor用户及项目成员的权限逻辑是:对于公开项目,项目成员有pull和push的权限,项目成员外的harbor用户以及匿名用户只能pull不能push;对于私有项目,项目成员有pull和push的权限,项目成员外的harbor用户以及匿名用户无任何上传下载权限
对harbor仓库的镜像进行管理:
上个实验中我们是直接安装并启动的harbor,此部分需要在安装和启动harbor时添加参数,故需要将之前安装的harbor停掉并删除相关数据
重新配置、安装并启动harbor
重建harbor仓库成功后,命令行login后,往harbor仓库上传镜像以便后续实验需要
在harbor仓库web页面对上传的镜像进行扫描
在harbor仓库web页面对项目进行配置管理
配置管理应用之后上传的镜像会被自动扫描
此时下载此项目中的镜像时会失败
部署根证书并在docker主机启动内容信任
此时上传镜像时会需要进行签名
此时,已签名的镜像可以被下载而未签名的镜像则不可以
此时再往harbor仓库中上传镜像均需要进行签名 *** 作
删除签名
Docker网络
Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理;然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分
在做本部分实验时要先做以下设置:
##删除docker内容信任,配置镜像加速,安装brctl命令工具
1、docker的原生网络
docker安装时会创建一个名为docker0的Linux bridge,新建的容器会自动桥接到这个接口
docker安装后会自动创建3种网络:bridge、host、none
bridge模式下容器没有一个公有IP,只有宿主机可以直接访问,外部主机是不可见的;容器通过宿主机iptables中的NAT规则后可以访问外网;是容器运行时使用的默认网络模式
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性;host网络模式需要在容器创建时指定:--network=host
none模式是指禁用网络功能,只有lo接口,在容器创建时指定:--network=none
2、docker自定义网络
docker支持自定义网络模式,docker提供了三种自定义网络驱动:bridge overlay macvlan;bridge驱动类似默认的bridge网络模式,但增加了一些新的功能;overlay和macvlan是用于创建跨主机网络;建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址
##自定义网段、网关创建docker网桥
##使用--ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的bridge模式不支持,同一网桥上的容器可以互相通信
##docker容器的IP分配是单调递增的,但在先前容器挂掉后会将其IP分配给新晋容器,挂掉的容器重启后会重新分配IP
##桥接到不同网桥上的容器,彼此是不能通信的;docker在设计上就是要隔离不同network
##为容器hahaha添加想要通信网段的网卡后即可与之网段的容器通信
原理拓扑图:
3、docker容器通信
容器之间除了使用IP通信外,还可以使用容器名称通信;从docker 1.10开始,内嵌了一个DNS server;DNS解析功能必须在自定义网络中使用
Joined容器一种较为特别的网络模式,在容器创建时使用--network=container:test指定(test即运行的容器名称);处于这个模式下的docker容器会共享一个网络栈,这样两个容器之间可以使用localhost实现高效快速通信
在docker命令行使用--link参数可以用来链接2个容器;使用格式为:--link
##将linktest容器链接到test,两者即可进行通信
##此时从linktest容器采集到的信息
##新开shell停掉linktest链接源容器test后,新建容器使之抢占源容器test的IP,之后重新启动源容器test,发现其IP发生变化
##此时在linktest容器中采集到的信息为以上,可以发现link模式会解析源容器的IP,但链接容器的环境变量没有发生变化
容器访问外网是通过iptables的SNAT实现的
外网访问容器需要打开端口映射,通过docker宿主机的docker-proxy和iptables的DNAT功能实现
测试步骤:
##运行容器,打开端口映射
##外部主机和docker宿主机都可以访问得到容器
##清除iptables中的nat策略
此时curl测试访问时,外部主机和宿主机依然可以访问得到,省略此处截图
##杀掉docker-proxy进程
##此时curl测试访问时,外部主机和宿主机均无法访问
##重启docker使docker的iptables策略重新刷新,停掉docker-proxy
##此时宿主机和外部主机都可以访问,由此可见,宿主机访问本机容器使用的是iptables DNAT,外部主机访问容器或容器之间的访问是docker-proxy实现这句话只是说此种方式更加快速,当其中一方不生效时宿主机与外部主机的访问会自动通过另一方式进行
4、跨主机容器网络
跨主机网络解决方案:docker原生的overlay和macvlan;第三方的flannel、weave、calico
众多网络方案是如何与docker集成在一起的:libnetwork ==> docker容器网络库;CNM(Container Network Model) ==> 这个模型对容器网络进行了抽象
CNM分三类组件
Sandbox:容器网络栈,包含容器接口、dns、路由表(namespace)
Endpoint:作用是将sandbox接入network(veth pair)
Network:包含一组endpoint,同一network的endpoint可以通信
macvlan网络方案实现:Linux kernel提供的一种网卡虚拟化技术,无需Linux bridge,直接使用物理接口,性能极好;使用macvlan网络驱动程序可以将MAC地址分配给每个容器的虚拟网络接口,使得看上去是物理网络接口直接连接到物理网络
实验环境:
server101主机 部署docker,网卡eth0 > IP=172.25.100.101,网卡eth1无IP
server102主机 部署docker,网卡eth0 > IP=172.25.100.102,网卡eth1无IP
打开两台主机eth1网卡的混杂模式,以使其可以分配多个mac地址
##实验环境基础配置,两台主机均需 *** 作
##在两台主机上创建同网段的macvlan网络mac1;parent指定流量在docker主机上实际通过的接口
##使用mac1网络运行容器时是没有使用网桥的,容器的接口直接与主机网卡连接,无需NAT或端口映射
##此时这两台主机各自运行的容器可以互相通信
macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络,vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094
##使用vlan子接口创建macvlan网络mac2;如果指定了一个带有点的parent接口名称,如上图中,docker会将其解释为eth1的子接口并自动创建子接口macvlan网络
##在server101主机上运行的nginx容器,可以在server102主机上访问得到
macvlan网络间的隔离和连通:macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的;可以在三层上通过网关将macvlan网络连通起来,docker本身不做任何限制,像传统vlan网络那样管理即可
Docker数据卷管理1、什么是docker数据卷
docker镜像被存储在一系列的只读层,当我们开启一个容器,docker读取只读镜像并在顶部添加一个读写层,如果正在运行的容器修改了现有的文件,该文件将从底层的只读层被拷贝到最顶层的读写层,在读写层中的旧版本文件隐藏于该文件之下,但并没有被破坏,仍然存在于镜像以下;当docker容器被删除后,重新使用该镜像启动容器,将开启一个没有任何更改的全新的容器,之前的更改会丢失,此只读层及在顶部的读写层的组合称为Union File System(联合文件系统);为了能够保存(持久)数据以及共享容器间的数据,docker提出了Volumes(数据卷)的概念;简单来说,volumes就是目录(或者文件),它们是外部默认的联合文件系统或者是存在于宿主机文件系统下的目录和文件
2、docker数据卷存在的意义
volumes是存在一个或多个容器中的特定文件或文件夹,这个目录能够独立于联合文件系统的形式存在于宿主机中,并为数据的共享与持久提供便利
volume在容器创建时初始化,在容器运行时就可以使用其中的文件,其能在不同的容器之间共享和重用;在宿主机中对volume数据的更改会在对应容器中即时生效,但不会影响到镜像本身;volume的生存周期独立于容器的生存周期,即使删除容器,volume也会仍然存在,没有任何容器使用的volume也不会被自动删除
3、docker数据卷的特性
mount到主机中,绕开分层文件系统
和主机磁盘性能相同,容器删除后依然保留
仅限本地磁盘,不能随容器迁移
4、docker数据卷的分类
docker提供了两种卷:bind mount 和 docker managed volume
bind mount:是将主机上的目录或文件mount到容器里,直观高效,易于理解;使用 -v 选项指定路径,格式
docker managed volume:不需要指定mount源,docker自动为容器创建数据卷目录,默认创建的数据卷目录都在 /var/lib/docker/volumes 中;如果挂载时指向容器内已有的目录,容器中原有数据会被复制到volume中
对于以上两类数据卷的测试:
##挂载宿主机的目录至容器并创建测试文件
##宿主机被挂载目录生成测试文件
##退出并回收容器后,测试文件仍然存在
##重新挂载运行容器,测试文件依然存在
##在宿主机中删除测试文件后,容器中的测试文件也被删除;反之亦然
##只读挂载宿主机文件至容器
##手动创建数据卷testdata
##挂载时指向容器内已有的目录,其原有数据被复制到volume中
##宿主机的挂载目录中的文件不符合使用镜像的文件要求会出现报错
5、数据卷插件
卷插件简介:
docker数据卷默认使用的是local类型的驱动,只能存在宿主机,跨主机的volume就需要使用第三方驱动,可以查看官方文档以下部分
Use Docker Engine plugins | Docker documentationHow to add additional functionality to Docker with plugins extensionshttps://docs.docker.com/engine/extend/legacy_plugins/#volume-pluginsdocker官方只提供了卷插件的api,开发者可以根据实际需求定制卷插件驱动
Docker volume plugins | Docker documentationHow to manage data with external volume pluginshttps://docs.docker.com/engine/extend/plugins_volume/#volume-plugin-protocolDocker Plugin是以Web Service的服务运行在每一台Docker Host上的,通过HTTP协议传输RPC风格的JSON数据完成通信,Plugin的启动和停止,并不归Docker管理;Docker Daemon依靠在默认路径下查找Unix Socket文件,自动发现可用的插件;当客户端与Daemon交互,使用插件创建数据卷时,Daemon会在后端找到插件对应的socket文件,建立连接并发起相应的API请求,最终结合Daemon自身的处理完成客户端的请求
convoy卷插件:
convoy卷插件支持三种运行方式:devicemapper、NFS、EBS,本部分采用NFS运行方式进行convoy卷插件的实现
实验环境:
server101主机安装docker IP=172.25.100.101
server102主机安装docker IP=172.25.100.102
##server101主机配置:安装nfs并启动,创建满权限目录,共享其至所有主机
##server102主机配置:安装nfs并启动,挂载server101主机的共享目录至自身的/mnt/nfs目录
##下载convoy软件,解压后配置covoy命令的环境变量
##server101配置:创建docker下的插件目录,声明convoy的socket文件至docker插件目录下的.spec文件,后台运行convoy后生成socket文件
##指定convoy驱动创建数据卷,查看其信息
##创建的数据卷的位置在共享目录下
##server102主机配置:下载convoy并运行
##在server101主机运行nginx容器并测试
##在server101主机将自身的nginx镜像打包发送给server102主机
##在server102主机上传nginx镜像
##在server102主机挂载数据卷运行nginx容器并测试访问
##在server101主机上修改nginx发布内容并测试
##在server102测试访问时数据同步更新
convoy卷插件子命令:
convoy list 列出卷
convoy delete 删除卷
convoy snapshot create 创建快照
convoy snapshot delete 删除快照
convoy backup create 创建备份
convoy create res1 --backup
1、理解docker安全
Docker容器的安全很大程度上依赖于Linux系统自身,评估Docker的安全性时,主要考虑以下几个方面
Linux内核的命名空间机制提供的容器隔离安全:
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间,命名空间提供了最基础也最直接的隔离;与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底;容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的 *** 作系统内核;在Linux内核中,有很多资源和对象是不能被Namespace化的,比如时间
##Linux Namespaces机制提供一种资源隔离方案,PID、IPC、Network等系统资源不再是全局性的,而是属于某个特定的namespace;每个namespace下的资源对于其他namespace下的资源都是透明,不可见的,因此在 *** 作系统层面上看,就会出现多个相同pid的进程;系统中可以同时存在两个进程号为0、1、2的进程,由于属于不同的namespace,所以它们之间并不冲突,而在用户层面上只能看到属于用户自己namespace下的资源,例如使用ps命令只能列出自己namespace下的进程,这样每个namespace看上去就像一个单独的Linux系统
Linux控制组机制对容器资源的控制能力安全:
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合;Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源;确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS)方面必不可少
Linux内核的能力机制所带来的 *** 作权限安全:
能力机制(Capability)是Linux内核一个强大的特性,可以提供细粒度的权限访问控制;大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可;默认情况下,Docker采用“白名单”机制,禁用“必需功能”之外的其他权限
Docker程序(特别是服务端)本身的抗攻击性:
使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问到Docker服务;将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题;允许Docker服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的 *** 作,这些子进程只允许在特定范围内进行 *** 作
其他安全增强机制对容器安全性的影响:
在内核中启用GRSEC和PAX,这将增加更多的编译和运行时的安全检查,并且通过地址随机化机制来避免恶意探测等,启用该特性不需要Docker进行任何配置;使用一些有增强安全特性的容器模板;用户可以自定义更加严格的访问控制机制来定制安全策略;在文件系统挂载到容器内部时,可以通过配置只读模式来避免容器内的应用通过文件系统破坏外部环境,特别是一些系统运行状态相关的目录
2、docker容器资源控制
Linux Cgroups(Linux Control Group)即控制组机制可以限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等;可以对进程进行优先级设置、审计,以及将进程挂起和恢复等 *** 作;Linux Cgroups给用户暴露出来的 *** 作接口是文件系统,其以文件和目录的方式组织在 *** 作系统的 /sys/fs/cgroup 路径下,可执行此命令查看:mount -t cgroup
##此/sys/fs/cgroup下面有很多诸如cpuset、cpu、 memory这样的子目录,也叫子系统;在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),控制组下面的资源文件里填上什么值,就靠用户执行docker run时的参数指定
内存限额:
容器可用内存包括两个部分:物理内存和swap交换分区
##上传压测镜像
##进行压力测试,控制的比较精准;memory设置内存使用限额,memory-swap设置swap交换分区限额
##限额内存但未限额swap交换分区用量,后者大小为前者两倍
##容器的内存限额和进程号都会保存在/sys/fs/cgroup目录下子系统的控制组目录下的相关文件中
##创建memory子系统下的test控制组,设定内存和交换分区限额均为200M
##测试内存占用:通过df可以看到tmpfs是挂载到/dev/shm目录,tmpfs其实是一个临时文件系统,驻留在内存中,所以/dev/shm/这个目录不在硬盘上,而是在内存里;linux中tmpfs默认最大为内存的一半大小,可以使用df -hT查看,查看到的只是挂载内存大小的数值,如果没有使用,是不会真正占用内存的,只有真正在tmpfs存储数据了才会去占用;因为数据是在内存里,所以断电后文件会丢失,内存数据不会和硬盘中数据一样可以永久保存,了解了tmpfs这个特性可以用来提高服务器性能,把一些对读写性能要求较高,但是数据又可以丢失的这样的数据保存在/dev/shm中,来提高访问速度
##安装cgroup管理工具
##指定cgroup中memory子系统下的test控制组执行dd命令,会出现报错且只能写入bigfile中限额大小的数据容量
CPU限制:
##指定一个cpu开启5个进程,此cpu对于这5个进程基本是平均分配状态
##指定两个cpu开启2个进程,每个进程各自独占一个cpu
##不指定cpu数量开启一个进程,此进程独占一个cpu;top界面中可按数字1显示详细cpu号码
##指定特定的cpu开启两个进程,两个进程各占50%额度
##查看cpu控制组的默认控制策略;period=cpu分配周期,单位毫秒;quota=cpu限额是否开启,-1表示没开启
##cpu_period 和 cpu_quota 这两个参数需要组合使用,但以上命令使用的默认cpu_period值,故可省略;此两个参数用来限制进程在长度为cpu_period的一段时间内,只能被分配到总量为cpu_quota的CPU时间,以上设置表示限制为20%的cpu时间
Block IO限制:
##--device-write-bps限制写设备的bps(衡量计算机的性能的bits per second,即比特率、比特/秒、位/秒、每秒传送位数;指的是数据传输速率的指标,同时也是数据传输速率的单位);目前的block IO限制只对direct IO有效,即不使用文件缓存(oflag:使用oflag来控制写入数据时的行为特征)
3、docker安全加固
利用LXCFS增强docker容器隔离性和资源可见性:
LXCFS是一个开源的FUSE(用户态文件系统)实现来支持LXC容器,也可以支持Docker容器;让容器内的应用在读取内存和CPU信息的时候通过lxcfs的映射,转到自己的通过对cgroup中容器相关定义信息读取的虚拟数据上
容器中的top/free/df等命令,展示的状态信息是从/proc目录中的相关文件里读取出来的:
##容器中看到的数据是物理机中的数据
LXCFS(FUSE filesystem for LXC)是一个常驻服务,它启动以后会在指定目录中自行维护与上面列出的/proc目录中的文件同名的文件,容器从lxcfs维护的/proc文件中读取数据时,得到的是容器的状态数据,而不是整个宿主机的数据;LXCFS通过文件挂载的方式,把cgroup中关于系统的相关信息读取出来,通过docker的volume挂载给容器内部的proc系统,然后让docker内的应用读取proc中信息时以为就是读取的宿主机的真实的proc中的内容
##安装lxcfs用户空间文件系统
##挂载使用lxcfs,挂载点下会生成上述两个目录
##挂载/var/lib/lxcfs/proc目录下的文件至容器内,限制内存运行容器可以看到容器内所看到的数据即不再是物理机中数据
设置容器的运行特权:
有的时候我们需要容器具备更多的权限,比如 *** 作内核模块、控制swap交换分区、挂载USB磁盘、修改MAC地址等
##容器运行时的root权限并不完整,虽然容器内的root用户直接是宿主机的root用户,但是Docker可以保证两者在权限方面拥有巨大的差异,这种差异的存在完全是借助于Linux内核的Capabilities机制,正是Capabilities在保障Docker容器的安全性
##运行容器时添加以上参数即相当于对此容器开放所有权限了
设置容器白名单:
上述--privileged=true指定的容器权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限;此种情况可以利用Docker提供的权限白名单的机制对容器权限进行限制
##使用--cap-add=添加必要的权限
更多capabilities见以下链接
capabilities(7) - Linux manual pagehttps://man7.org/linux/man-pages/man7/capabilities.7.html容器的rootless模式:
官方文档参见
Run the Docker daemon as a non-root user (Rootless mode) | Docker documentationRun the Docker daemon as a non-root user (Rootless mode)https://docs.docker.com/engine/security/rootless/Linux需要特权用户来创建namespace,挂载分层文件系统等,所以Docker Daemon一直以来是以root用户来运行的,这也导致了有Docker访问权限的用户可以通过连接Docker Engine获取root权限,而且可以绕开系统的审计能力对系统进行攻击;这阻碍了容器在某些场景的应用:比如在高性能计算领域,由于传统的资源管理和调度系统需要非特权用户来运行容器,社区实现了另外的容器运行时Singularity
##系统普通用户无法使用docker
首先更新shadow-utils工具包以提供newuidmap命令
创建系统普通用户linux并添加认证
配置此普通用户的次级uid和gid,至少包含65536个
##表示uid/gid范围为:100000~165535
##使用ssh连接本地用户,不可使用su切换;设置rootless模式时出现以上报错
##按照报错提示进行设置
##再次ssh连接此用户安装rootless配置工具并按照提示配置环境变量;指定存储驱动为vfs后台运行rootless模式
##rootless模式下,普通用户也可以正常使用docker了
目前rootless容器还在实验阶段,cgroups资源控制、apparmor安全配置、checkpoint/restore等能力还不支持;目前只有Ubuntu提供了在rootless模式下对overlay fs的支持;由于安全顾虑,这个方案尚未得到upstream的支持,其他 *** 作系统需要利用VFS存储驱动,有一定性能影响,并不适合I/O密集型应用
安全加固的思路
保证镜像的安全:使用安全的基础镜像、删除镜像中的setuid和setgid权限、启用Docker的内容信任、最小安装原则、对镜像进行安全漏洞扫描(镜像安全扫描器Clair)、容器使用非root用户运行
保证容器的安全:对docker宿主机进行安全加固、限制容器之间的网络流量、配置Docker守护程序的TLS身份验证、启用用户命名空间支持(userns-remap)、限制容器的内存使用量、适当设置容器CPU优先级
docker安全的遗留问题:主要的内核子系统都没有命名空间,如SELinux、cgroup、在/sys下的文件系统、/proc/sys,/proc/sysrq-trigger,/proc/irq,/proc/bus;设备没有命名空间:/dev/mem、/dev/sd*文件系统设备、内核模块
如果你能沟通或攻击的其中之一作为特权的过程中,你可以拥有自己的系统
虽然docker安全还是有很多没有完善的地方,但不能否认docker依然是当前最安全的容器技术
Docker安全的顶尖开源工具
Docker Bench for Security:对照安全基准审计Docker容器的脚本
Clair:API驱动的静态容器安全分析工具,拥有庞大的CVE数据库
Cilium:内核层可感知API的网络和安全工具
Anchore:使用CVE数据和用户定义的策略检查容器安全的工具
OpenSCAP Workbench:用于为各种平台创建和维护安全策略的环境
Dagda:用于在Docker容器中扫描漏洞、特洛伊木马、病毒和恶意软件的工具
Notary:使用服务器加强容器安全的框架,用于以加密方式委派责任
Sysdig Falco:提供了行为活动监控,可深入了解容器
Docker Machine1、简介
Docker Machine是Docker官方编排(Orchestration)项目之一,负责在多种平台上快速安装Docker环境;Docker Machine支持在常规Linux *** 作系统、虚拟化平台、openstack、公有云等不同环境下安装配置docker host;Docker Machine项目基于Go语言实现,目前在Github上的维护地址:https://github.com/docker/machine/
2、实践
安装:
创建machine:
machine指的是docker daemon主机,其实就是在主机上安装和部署docker;创建流程:ssh免密登陆远程主机--->安装docker软件包--->复制证书--->配置docker daemon--->启动docker
##配置免密,准备在server103主机上部署docker
##在真实主机配置docker软件包仓库和安装脚本
##创建docker主机
##查看server103docker主机变量;登入server103;登出103(只能通过ssh的logout登出,暂未发现更便捷的方式)
##docker-machine主机生成的相关文件
##machine主机上生成的文件,可见docker daemon启用了TLS验证功能,docker-machine已经为其生成好了所需的证书文件
切入machine创建的docker主机时行提示符的优化:
##更新bash
##配置.bash文件并将文件添加至/etc/bash_completion.d/目录下;配置环境变量,重新ssh连接以使变量生效
##配置完成后在切入machine时会显示其hostname
##将server102主机也添加至docker-machine中
##在docker-machine模式下可以随意切换至集群中存在的各个主机,但退出还是依赖ssh的logout
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)