一,docker为什么那么火
这要从虚拟机说起,我们都知道很多虚拟机管理工具程序都基于虚拟化硬件仿真机制。这意味着,它们对系统要求很高。但是容器却使用共享的操作系统。这意味着它们在使用系统资源方面比虚拟机管理程序要高效得多。容器不是对硬件进行虚拟化处理,而是驻留在单单一个Linux实例上。这反过来意味着,你可以“丢弃没有用的99.9%的虚拟机垃圾,剩下一个小巧简洁的胶囊式容器,里面含有你的应用程序。因此,借助经过全面调优的容器系统,你就可以在同一硬件上拥有数量比使用虚拟机多出四到六倍的服务器应用实例。
从上图,我们可以看到,容器由于省去了操作系统,整个层级更简化,可以在单台服务器上运行更多的应用,一个虚拟机可能5G右的空间,对你来说不是什么大事,但是如果你需要对外提供成千上万的主机,那就是不得了。
普通虚拟机将整个操作系统运行在虚拟的硬件平台上,进而提供完整的运行环境供应用程序运行,而Docker则直接在宿主平台上加载运行应用程序.本质上他在底层使用LXC启动一个Linux Container,通过cgroup等机制对不同的container内运行的应用程序进行隔离,权限管理和quota分配等每个container拥有自己独立的各种命名空间(亦即资源)包括:PID进程, MNT文件系统, NET网络, IPC, UTS主机名等。
在实际生产开发中我们经常听到的一句话就是“我在我的环境上可以运行,怎么到你那边就不行了呢”,而docker可以完美解决这种问题,docker的镜像提供了除内核外完整的运行时环境,确保环境一致性,从而不会在出现“这段代码在我机器上没问题”这类问题。
对开发和运维人员来说,最希望就是一次创建和部署,可以在任意的地方运行。(定制应用镜像来实现集成、持续支付、部署。开发人员可以通过dockerfile来进行镜像构建,并结合持续集成系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署)。而且使用dockerfile使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
由于docker确保了执行环境的一致性,使得应用的迁移更加的容易。docker可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云、甚至是笔记本、其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
docker使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得十分简单。此外,docker团队同各个开源项目团队一起维护了一大批高质量的官网镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
总结docke深受大众喜爱的原因
1.更高效的利用系统资源
2.更快速的启动时间
3.一致的运行环境
4.持续支付和部署
5.更轻松的迁移
6.更轻松的维护和拓展
二,docker中的名词概念
仓库(Repository)
镜像(Image)
容器(Container)
打个比方:你如果想玩英雄联盟中骚气的亚索,你首先得有这个英雄(Docker的镜像),然后你得花金币去英雄商店(Docker的仓库)买,接着进游戏就会看到一个半蹲的发型飘逸的剑客(Docker的容器),所以:
1,其中Registry是Docker用于存放镜像文件的仓库,Docker 仓库的概念跟Git 类似(就像商店存放所有的英雄,只是更改英雄的权限在某些非程序员手里)。
2,所谓镜像就是构建容器的源代码,是一个只读的模板,由一层一层的文件系统组成的,类似于虚拟机的镜像(英雄也是只读的,有自己的技能被动,你也不能进行操作)。
3,那么容器就是由Docker镜像创建的运行实例,类似于虚拟机,容器之间是相互隔离的,包含特定的应用及其所需的依赖文件(好比每个英雄都是隔离的,都有自己的皮肤,技能以及走的路线)。
注:Docker Hub是Docker公司提供的一个注册服务器(Register)来保存多个仓库,每个仓库又可以包含多个具备不同tag的镜像。
三,安装docker
1,root账户登录,查看内核版本如下
[root@localhost ~]# uname -a
Linux localhost.localdomain 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018
x86_64 x86_64 x86_64 GNU/Linux
2,把yum包更新到最新
yum update
3,安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2
4,设置yum源(选择其中一个)
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo(中央仓库)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo(阿里仓库)
5,可以查看所有仓库中所有docker版本,并选择特定版本安装
yum list docker-ce --showduplicates | sort -r
6,安装Docker,命令:yum install docker-ce-版本号,我选的是docker-ce-18.03.1.ce,如下
yum install docker-ce-18.03.1.ce
7, 启动Docker,命令:systemctl start docker,然后加入开机启动,如下
systemctl start docker
systemctl enable docker
docker version
四,配置阿里云镜像加速
登录阿里云搜索“容器镜像服务”————“镜像加速器”
执行如下命令
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-‘EOF’
{
“registry-mirrors”: [“镜像加速地址”]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
五,run流程和docke原理
以docker run hello-world为例
run流程见下图
docker底层原理
Docker是一个Client - Server结构的系统,Docker的守护进行运行在主机上。通过Socket从客户端访问! DockerServer接收到Docker-Client的指令,就会执行这个命令!
docker为什么比虚拟机快
1、Docker有着比虚拟机更少的抽象层。
2、docker利用的是宿主机的内核,vm需要是Guest os。
所以说,新建一个容器的时候,docker不需要想虚拟机─样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest O5,分钟级别的,而docker是利用宿主机的操作系统吗,省略了这个复杂的过程,秒级!
六,镜像基本命令
docker命令以docker开头
帮助命令
docker version
#显示docker的版本信息
docker info
#显示docker系统信息,包括容器和镜像的数量
d
ocker --help
#帮助命令
容器命令
docker images
#查看本地主机上的所有镜像
解释:
REPOSITORY
#镜像的仓库源
TAG
#镜像的标签
IMAGE ID
#镜像的ID
CREATED
#镜像创建时间
SIZE
#镜像大小
可选参数
-a, --all #查看所有镜像(默认)
-q, --quiet #列出所有镜像id
docker search #搜索镜像
例如搜索MySQL镜像:
docker search mysql
#可选项,通过收藏次数来过滤筛选
docker search mysql --filter=STARS=3000
docker pull
拉取镜像
docker pull 镜像名:tag
例如:
docker pull mysql:5.7
结果分析:
[root@VM-0-11-centos ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
bf5952930446: Pull complete #分层下载,联合文件系统
8254623a9871: Pull complete
938e3e06dac4: Pull complete
ea28ebf28884: Pull complete
f3cef38785c2: Pull complete
894f9792565a: Pull complete
1d8a57523420: Pull complete
5f09bf1d31c1: Pull complete
1591b28581e8: Pull complete
96ef942f7603: Pull complete
2e009731422e: Pull complete
Digest: sha256:1a83136153b238b659b0887ceb4e08275473af1eab2e67de4c22b37c5f4130cd #签名
Status: Downloaded newer image for mysql:5.7
docker rmi 镜像ID
#删除镜像
骚操作,一次删除所有:
docker rmi $(docker images -q)
七,容器命令
docker run [可选参数] images
#参数说明
–name=“Name” 容器名字tomcat01,tomcat02,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p指定容器的端口
-p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-P 随机指定端口
docker run -it centos /bin/bash 启动并进入容器
查看容器
docker ps 查看正在运行的容器
docker ps -a 查看所有容器(包括停止的)
docker ps -aq 查看所以普容器的ID
docker ps -n=1 查看最近创建的一个容器
退出容器
exec 停止并退出容器
快捷键 Ctrl+p+q不停止容器退出
删除容器
docker rm 容器id
docker rm $(docker ps -qa) 删除所有容器
注意:删除容器只能删除已经停止的容器
启动、停止、重启容器
docker start 容器id 启动容器
docker stop 容器id 停止容器
docker restart 容器id 重启容器
查看容器日志
docker logs -tf --tail 10 容器id #查看最近10条日志
查看容器的进程信息
docker top 容器id
查看容器内部详细信息
docker inspect 容器id
进入容器的两种方式
1,docker exec -it 容器id bashshell
例如:
docker exec -it ca1b9901f34f /bin/bash
2,docker attach 容器id
区别:
docker exec 进入容器后开启一个新的终端,可以在里面操作(常用)
docker attach 进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝文件到本地主机
docker cp 容器id:容器内路径 目的的主机路径
例如:
docker cp ca1b9901f34f:/test.txt /
八,portainer可视化面板安装
什么portainer ?
Docker图形化界面管理工具!提供一个后台面板供我们操作!
安装命令:
docker run -d -p 8088:9000
–restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
浏览器访问 IP:8088
九,镜像原理之联合文件系统
1,镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。所有的应用,直接打包docker镜像,就可以直接跑起来!
2,如何得到镜像:
·从远程仓库下载
·朋友拷贝给你
.自己制作一个镜像DockerFile
Docker镜像加载原理
1、UnionFS(联合文件系统)
Union文件系统(UnionFS) 是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来层层的叠加,
同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像
的基础。镜像可以通过分层来进行集成,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统你那个,联合加载会把各层文件系统叠加起来,这样最终的
文件系统会包含所有底层文件和目录。
2、Docker 镜像加载原理
docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system) 主要包含bootloader和kernel,bootloader 主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就存在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
roorfs (root file system),在bootfs之上。包含的就是典型Linux系统中的 /dev ,/proc,/bin ,/etx 等标准的目录和文件。rootfs就是各种不同的操作系统发行版。比如Ubuntu,Centos等等。
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host(宿主机)的kernel,自己只需要提供rootfs就行了,由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
四、Docker 镜像联合文件系统分层,Tomcat镜像示例
采用这种分层结构最大的一个好处就是共享资源,比如有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,
同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作 “容器层” ,“容器层” 之下的都叫镜像层。
十,commit镜像
docker commit提交容器成为一个新的副本
#命令和git原理类似
docker commit -m=“提交的描述信息” -a="作者” 容器id 目标镜像名:[TAG]
测试:
在官方nginx下创建test.txt测试文件
通过commit提交为一个新的镜像
通过我们的新镜像run一个容器查看test.txt存在
成功如下图
十一,容器数据卷以及数据卷容器的使用
docker容器数据卷是什么?
当我们在使用docker容器的时候,会产生一系列的数据文件,这些数据文件在我们关闭docker容器时是会消失的,但是比如我们的数据库文件我们不可能让他随容器消失而消失,Docker将应用与运行环境打包成容器发布,我们希望在运行过程钟产生的部分数据是可以持久化的的,而且容器之间我们希望能够实现数据共享。
通俗地来说,docker容器数据卷可以看成使我们生活中常用的u盘,它存在于一个或多个的容器中,由docker挂载到容器,但不属于联合文件系统,Docker不会在容器删除时删除其挂载的数据卷。
容器数据卷特点:
1:数据卷可以在容器之间共享或重用数据
2:数据卷中的更改可以直接生效
3:数据卷中的更改不会包含在镜像的更新中
4:数据卷的生命周期一直持续到没有容器使用它为止
添加数据卷的方式有两种,第一种是直接通过命令行挂载,第二种是通过dockerFile添加
首先来说第一种通过命令行挂载的方式,命令如下:
docker run -it -v /宿主机绝对路径目录: /容器内目录 镜像名
例如:
将本地test.txt挂载到容器text.txt上
通过docker inspect 容器id
查看挂载情况
我们再挂载的时候还可以给数据卷加上权限,假如我们要宿主机只能读取容器的数据卷内容不能修改,我们可以添加只读权限
docker run -it -v /宿主机绝对路径目录 :/容器内目录 :ro 镜像名
第二种通过dockerfile挂载后面会说到,这里不做多解释
什么是docker数据卷容器?
上面介绍了docker容器数据卷,它的作用相当于生活中的活动硬盘,那么数据卷容器就相当于把多个活动硬盘再挂载到一个活动硬盘上,实现数据的传递依赖。
官网解析:命名的容器挂载数据卷,其他的容器通过挂载这个父容器实现数据共享,挂载数据卷的容器,我们称为数据卷容器。
1,创建父容器
docker run -it - -name 容器名字 镜像名
2,然后建立子容器继承父容器
docker run -it - -name 子容器名字 --volumes -from 父容器名字 镜像名
3,验证成功
十二,具名挂载和匿名挂载
匿名挂载:不指定容器卷名
docker volume ls 查看所有卷情况
具名挂载: 指定数据卷名
通过docker volume inspect 数据卷名查看到挂载目录
-v /宿主机路径:容器内路径 指定路径挂载
-v 数据卷名:容器内路径 具名挂载
-v 容器内路径 指定目录挂载
十三,数据卷之初识Dockerfile
Dockerfile就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!
编写dockerfile如下
通过build构建镜像
docker build -f /root/test_volumes/dockerfile01 -t zhangshaocentos01 .
发现我们容器里有volumes01,volumes02,docker inspect 69b74135de9a
查看是否挂载成功
十四,什么是dockerfile
Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。
docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。
Dockerfile的基本结构
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令.
’#’ 为 Dockerfile 中的注释。
每个保留关键字(指令)都是必须是大写字母
执行从上到下顺序执行
每一个指令都会创建提交一个新的镜像层,并提交!
Dockerfile文件说明
Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。
十五,dockerfile常用指令
FROM
#基础镜镜像,一切从这里开始构建
MAINTAINER
#镜像是谁写的,姓名+邮箱
RUNI
#镜像构建的时候需要运行的命令
ADD
#步骤: tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR
#镜像的工作目录
VOLUME
#挂载的目录
EXPOSE
#保留端口配置
CMD
#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT
#指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD
#当构建一个被继承DockerFile这个时候就会运行ONBUILD的指令。触发指令。
COPY
#类似ADD ,将我们文件拷贝到镜像中
ENV
#构建的时候设置环境变量!
十六,docker发布自己的镜像
发布到docker Hub
到官网注册账号:https://hub.docker.com/
首先登录到docker Hub上命令docker login
发布
docker push 仓库名/镜像名:镜像版本
发布到阿里云
登录阿里云------“容器镜像服务”--------------创建命名空间
发布参考阿里云
https://cr.console.aliyun.com/repository/cnhangzhou/docker20200526/zhangshao/details
十七,理解docker0
首先查看一下本机网卡
三个网卡解释:
lo:本机回环地址
eth0:本机网卡
docker0:docker的地址
测试
首先我们启动一个容器,查看容器IP地址会发现容器ip和docker0网卡在同一网段,那么意味着我们的服务器是可以和我们容器互通的
再次折腾:
1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0(使用的桥接模式),使用的技术是 evth-pair技术!
再次启动一个容器,我们会发现我们服务器上又多了一个网卡,我们观察容器和服务器会发现如下图这种联系(evth-pair技术),我们发现每启动一个容器带来的网卡都是成对的
evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,彼此相连
正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备
下面我们测试tomcat01是否和tomcat02是否可以联通
总结:
docker0我们可以理解为路由器他的ip就相当于我们的网关,而我们创建的容器我们可以理解为是docker0下的网络设备,因为在同一网络下,所以我们的容器可以互通
思考:
我们的容器重启之后IP会发生改变,也就是说我们的连接将不可用,那么我们能不能通过容器名来实现容器连接呢,也就是说我们不管IP怎么改变只要我们的容器名字不变那么我们就可以正常连接呢?请继续往下看我们一起来解决这个问题
十八,容器互联 --link
首先我们进行ping测试,发现无法ping通
下面我们通过–link来再创建一个tomcat03和tomcat02建立连接,我们再使用tomcat03容器名来测试是否可以和tomcat02建立连接
ok没问题,那么我们tomcat02是否可以ping通同tomcat03呢?
显然是不可以的,下面我们来看一下为什么
我们进入tomcat03查看/tec/hosts
我们可以看到之所以tomcat03可以ping通tomcat02是因为我们在hosts里配置了,那么我们在进入tomcat02查看肯定没有tomcat03的配置,这就是tomcat02不能ping通03的关系,见下图
总结
–link实际上是在hosts里增加了映射(真实环境中不建议使用这种方法),真实生产环境建议使用以下方法-----自定义网络
十九,容器互联------自定义网络
查看主机上所有的docker网络
docker network ls
网络模式
bridge:桥接docker(默认,自定义网络建议使用这种)
none:不配置网络
host :和宿主机共享网络
container :容器网络连通!(用的少!)
下面我们来创建一个网络
docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 mynet
解释
–driver bridge 使用的网络模式
–subnet 设置子网
–gateway 设置网关
mynet 网络的名字
查看我们自己配置的网络
docker network inspect mynet
我们在自己的网络下通过--net
创建两个容器tomcat-net-01,tomcat-net-02
docker network inspect mynet
再次查看发现我们这个网络下多了两个容器
再回到第十七章中我们的思考问题,我们自定义网络就可以完美解决这个问题
ok这样我们只要保证容器名不变就可以容器间互通
自定义网络的好处
举个例子,我创建了两个集群(radis,mysql),我分别为这两个集群设置不同的网络,那么这两个集群就是隔离的,互不影响。
思考
我现在有两个网络(docker0,mynet),上面分别有两个容器,那么我怎样才能让docker0上的容器连通mynet呢?请继续往下看网络连通
二十,网络连通
可能有的朋友会想我是不是只要把docker0和mynet连通不就ok了嘛,这样是不对的,如果这样做那岂不是要乱套了吗?继续往下看
大概需求看下图
下面我们通过docker network connect mynet tomcat01
来实现tomcat01和mynet连通
测试
从上图我们可以看到tomcat01和mynet下的两个容器成功实现了联通
tomcat01就是官网所说的一个容器两个IP,我们查看一下见下图
---------------------------------------不要在该奋斗的年纪选择安逸
最后,这篇博客是本人学习之后所写记录,有问题的地方欢迎大家指出,共同进步。