Docker核心概念
Docker 是一个开源的应用容器引擎,是一种资源虚拟化技术,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上。
Docker 的构成
Docker中有三个核心概念,分别是镜像、容器、仓库。
- 镜像的概念主要就是把运行环境和业务代码进行镜像打包,每个镜像都会存在多个“层”,镜像层都是只读的,不能往里写数据,如果想要写,就需要在其基础之上启动成一个容器, 在容器层,我们是可写的。
- 容器: 进行了资源隔离的镜像运行时环境
https://cloud.tencent.com/developer/article/1672421
在镜像的多个“层”中,有一个busybox的概念,我将它理解为欺骗层。
虚拟化的技术就是来解决宿主机与虚拟机之间的耦合问题(简称“解耦”),传统虚拟化是属于完全解耦的,而docker是属于半解耦的。
Docker 原理
docker容器本质上是宿主机的进程,
Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制,通过写时复制机制(copy-on-write)实现了高效的文件操作。
docker容器技术与传统虚拟化技术比较
Docker容器技术是一个与传统的虚拟化技术有些本质上的差别,传统的虚拟化技术,是站硬件物理资源的基础上,虚拟出多个OS,然后在OS的基础上构建相对独立的程序运行环境,而Docker则是在OS的基础上进行虚拟,所以,Docker轻量很多,因此其资源占用、性能消耗相比传统虚拟化都有很大的优势。
docker容器很快,启动和停止可以在秒级实现,比传统的虚拟化技术要快很多,docker核心解决的问题是利用容器来实现类似VM的功能,从而节省更多的硬件资源,docker容器除了运行其中的应用之外,基本不消耗额外的系统资源,从而在保证性能的同时,减小系统开销,同时,它还可以达到“一次封装,到处运行”的目的。
Namespace
命名空间 (Namespaces) 是 Linux 为我们提供的用于分离进程树、网络接口、挂载点以及进程间通信等资源的方法。Linux 的命名空间机制提供了以下七种不同的命名空间,通过这七个选项我们能在创建新的进程时设置新进程应该在哪些资源上与宿主机器进行隔离。
运行在同一台机器上的不同服务能做到完全隔离,就像运行在多台不同的机器上一样。
当在宿主机运行 Docker,通过docker run或docker start创建新容器进程时,会传入 CLONE_NEWPID 实现进程上的隔离。
Docker资源控制实现 Control Groups(CGroups)
cgroup 是 Linux 内核的一个功能,用来限制、控制与分离一个进程组的资源(如CPU、内存、磁盘输入输出等)。
它是由 Google 的两位工程师进行开发的,自 2008 年 1 月正式发布的 Linux 内核 v2.6.24 开始提供此能力。
Linux Cgroup最主要的作用是为一个进程组设置资源使用的上限,这些资源包括CPU、内存、磁盘、网络等。
在linux中,Cgroup给用户提供的操作接口是文件系统,其以文件和目录的方式组织在/sys/fs/cgroup路径下
cgroups能实现资源的限制,但是不能保证资源的使用,因为有资源竞争的情况存在
cgroup 主要有两个组成部分:
- core - 负责分层组织过程;
- controller - 通常负责沿层次结构分配特定类型的系统资源。每个 cgroup 都有一个 cgroup.controllers 文件,其中列出了所有可供 cgroup 启用的控制器。当在 cgroup.subtree_control 中指定多个控制器时,要么全部成功,要么全部失败。在同一个控制器上指定多项操作,那么只有最后一个生效。每个 cgroup 的控制器销毁是异步的,在引用时同样也有着延迟引用的问题
创建一个容器时:
- docker首先会在
/sys/fs/cgroup/cpu
路径下创建名为docker的目录 - 紧接着会在docker的目录下创建容器id名称的子目录
- 对容器的cpu的使用限制是通过操作容器id子目录下的文件设置,达成的容器内的进程均受容器的资源设置限制
- 其他的资源比如内存、网络等设置与cpu结构相同
Docker容器内存限制
–memory,–memory-swap,–memory-swappiness三个参数
https://www.jianshu.com/p/b02bf3b3f265
镜像原理之联合文件系统 UnionFS
Docker 中的每一个镜像都是由一系列只读的层组成的,Dockerfile 中的每一个命令都会在已有的只读层上创建一个新的层:
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
容器中的每一层都只对当前容器进行了非常小的修改,上述的 Dockerfile 文件会构建一个拥有四层 layer 的镜像:
当镜像被 命令创建时就会在镜像的最上层添加一个可写的层,也就是容器层,所有对于运行时容器的修改其实都是对这个容器读写层的修改。
容器和镜像的区别就在于,所有的镜像都是只读的,而每一个容器其实等于镜像加上一个可读写的层,也就是同一个镜像可以对应多个容器。
镜像原理之分层理解
与传统虚拟机技术的区别
Docker和虚拟机区别的图
这张图应该可以清晰的展示了虚拟机技术和 Docker 技术的区别了,虚拟机技术是完全虚拟出一个单独的系统,有这个系统去处理应用的各种运行请求,所以它实际上对于性能来说是有影响的。而 Docker 技术 完全是依赖 Linux 内核特性 Namespace 和Cgroup 技术来实现的,本质来说:你运行在容器的应用在宿主机来说还是一个普通的进程,还是直接由宿主机来调度的,相对来说,性能的损耗 就很少,这也是 Docker 技术的重要优势。
Docker 技术由于 还是一个普通的进程,所以隔离不是很彻底,还是共用宿主机的内核,在隔离级别和安全性上没有虚拟机高,这也是它的一个劣势。
总的来说 Docker技术由于是一个普通的宿主机进程,所以具有性能优势,而虚拟机由于完全虚拟系统,所以具备了高隔离性和安全性的优势,两者互有优缺点。不过容器化是当下的趋势,相信随着技术的成熟,目前的隔离不彻底的问题也能解决,容器化走天下不是梦。
Docker环境搭建
https://yeasy.gitbook.io/docker_practice/install
https://docs.docker.com/engine/install/centos/
Docker常用命令
11、日志、元数据、进程的查看
查看容器后十条的日志
docker logs -tf --tail 10 id
查看容器内的进程信息
docker top id
查看元数据
docker inspect ContainerId
12、进入容器的命令和拷贝命令
进入当前运行的容器两种方式
-
方式一
docker exec -it ContainerId /bin/bash ps -ef
-
方式二
docker attach ContainerId //进入正在运行的命令行
从容器内往主机cp数据
docker cp 容器id:容器内路径 宿主机路径
作业
Docker安装Ningx
15、作业二:部署Tomcat
17、Portainer可视化面板安装
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
设置完密码,选择local
Dockerfile
FROM centos #指定要生成的镜像的基础镜像,开头第一句话必须也只能是FROM
MAINTAINER why@163.com #指定作者是谁
RUN yum install -y vim #执行 yum install -y vim 命令,安装vim
RUN yum install -y net-tools #执行 yum install -y net-tools, 安装net-tools工具
WORKDIR /dev/ #启动容器后,如果启动交互模式,直接进入到哪个目录
CMD ["/bin/bash"] #启动容器的时候,进入到/bin/bash这种命令行
关键字 | 作用 |
---|---|
FROM | 指定基础镜像 |
MAINTAINER | 作者的信息 |
RUN | 执行什么命令 |
EXPOSE | 容器对外暴露的端口 |
WORKDIR | 进入到容器后进入到哪个目录 |
ENV | 配置环境变量 |
ADD | 将文件拷贝到镜像中并解压 |
COPY | 将文件拷贝到镜像中 |
VOLUME | 配置数据卷 |
CMD | 容器启动时候执行的命令 |
ENTRYPOINT | 容器启动时候执行的命令 |
ENTRYPOINT的两种写法:
docker exec的形式
ENTRYPOINT [“exec”,”param1”,”param2"]
任何docker run设置的命令参数或者CMD指令的命令,都将作为ENTRYPOINT 指令的命令参数,追加到ENTRYPOINT指令之后。
shell的形式
ENTRYPOINT command param1 param2
这种格式禁止追加任何参数,即CMD指令或docker run后面的参数都将被忽略。采用shell格式,在容器中执行时,自动调用shell。
CMD与ENTRYPOINT的关系:
CMD可以为ENTRYPOINT提供参数,ENTRYPOINT本身也可以包含参数,但是可以把需要变动的参数写到CMD里面,而不需要变动的参数写到ENTRYPOINT里面;
ENTRYPOINT使用第二种shell方式会屏蔽掉CMD里面的命令参数和docker run后面加的命令。
在Dockerfile中,ENTRYPOINT指定的参数比运行docker run时指定的参数更靠前。
docker run 的–entrypoint 标志可以覆盖原Dockerfile中的ENTRYPOINT 指令。
关系图
20、commit镜像
-
场景:比如docker 打包tomcat镜像时,webapps下没有文件,需要在webapps.list的所有文件,拷贝到webapps下,十分麻烦。
-
解决办法:commit一个镜像,可以直接使用
docker commit -a "author" -m "change" id mymysql:v1
-
总结:
容器数据卷
21、容器数据卷
- 容器挂载宿主机目录
docker run -it -v /home/ceshi:/home centos /bin/bash
- 查看容器挂载情况
docker inspect id
目录挂载的数据是双向的
22、MySQL同步数据
docker run -d -it -p 3306:3306 --name mysql01 -v /home/mysql/conf.d:/etc/mysql/conf.d -v /home/mysql/logs:/logs -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
23、匿名、具名挂载
-
查看具名挂载的目录
docker volume inspect juming-nginx
24、数据卷之Dockerfile
25、数据卷容器
Docker网络
docker创建的容器之间会通过一张docker0的网卡相互通信
当 Docker 容器完成命名空间的设置,其网络也变成了独立的命名空间,与宿主机的网络互联便产生了限制,这就导致外部很难访问到容器内的应用程序服务。Docker 提供了 4 种网络模式,通过–net指定。
- host
- container
- none
- bridge
34、Docker0网络详解
- 结论
35、容器互联–link
36、自定义网络
自定义网络是容器可以ping通的
37、网络连通
docker network connect mynet tomcat01
网段之间不能打通,容器可以打通网段
- 结论:使用docker network connect 的容器,可以跨网络访问
38、Redis集群部署实战
- 创建网卡,并配置6个redis.conf文件
- docker 启动多个redis容器
- 关闭一个master docker容器来测试 获取存储在该容器的值
总结:可以用docker快速搭建集群,非常方便
39、SpringBoot微服务打包Docker镜像
参考 https://blog.csdn.net/weixin_43746433/article/details/104020667