Docker
1、概述
利用docker技术,消除协作编码时,“在我的机器上可正常工作”的问题,将运作应用程序所需要的系统环境,由下而上打包,达到应用程序跨平台间的无缝接轨运作。
Build,Ship and Run Any App,Anywhere;
一次构建,处处运行
- 镜像技术
- 基于go语言实现的云开源项目
- 解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
- 只需要一次配置好环境,换到别的机器上就可以一键部署,大大简化了操作。
虚拟机:
- 带环境安装的一种解决方案
- 缺点:
- 资源占用多
- 冗余步骤多
- 启动慢
Linux容器(Linux Containers, LXC)
- Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离,有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器和虚拟机不同,不需要捆绑一整套操作系统。只需要软件工作所需要的库资源和设置。
比较docker和传统虚拟化方式的不同之处:
- 传统虚拟机技术是虚拟化出一套硬件后,在其上运行完整的操作系统,在该系统上再运行所需应用进程。
- 而容器内的应用进程直接运行于宿主机的内核,容器内没有自己的内核,而且也没有进行硬件虚拟化,因此容器要比传统虚拟机更加轻便。
- 每个容器之间互相隔离,每个自己的文件系统,容器之间进程不会相互影响,能区分计算资源。
开发/运维(DevOps):
- 更快速的应用交付和部署
- 更便捷的升级和扩缩容
- 更简单的系统运维
- 更高效的计算资源利用
镜像-容器-仓库
Docker镜像(Image):
- 就是一个只读的模板,镜像可以用来创建Docker容器,一个镜像可以创建很多容器。
Docker容器(Container):
- 利用容器独立运行的一个或一组应用。容器是用镜像创建的运行实例。
- 可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。
- 可以把容器看作一个简易版的Linux环境(包括root用户权限,进程空间,用户空间和网络空间等)和运行在其中的应用程序。
仓库(Repository):
-
仓库是集中存放镜像文件的场所
-
仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放了多个仓库,每个仓库有包含了多个镜像,每个镜像有不同的标签。
-
仓库有公开仓库(Public)和私有仓库(Private);
-
最大的公开仓库是Docker Hub(Https://hub.docker.com/)
Why Docker:
- 更轻量:基于容器的虚拟化,仅包含业务运行所需的runtime环境,centOS/Ubuntu基础镜像仅170M;宿主机可部署100-1000个容器。
- 更高效:无操作系统虚拟化开销
- 计算:轻量,无额外开销;
- 存储:系统盘,数据盘
- 网络:宿主机网络,NS隔离
- 更敏捷、更灵活:
- 分层的存储和包管理,DevOps理念
- 支持多种网络配置
Docker本身是一个容器运行载体或者称为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有用过这个镜像文件 才能生成Docker容器。image文件可以看做是容器的模板。Docker根据image文件生成容器的实例。同一个image文件,可以生成多个同时运行的容器实例。
- image文件生成的容器实例,本身也是一个文件,称为镜像文件。
- 一个容器运行一个服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器
- 仓储就是房里一堆镜像的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉下来。
2、实操
docker run
阿里云镜像;
原理:
- docker有着比虚拟机更少的抽象层,由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
- docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。避免引寻、加载操作系统内核这类费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS ,新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了这个过程,因此新建一个docker容器只需要几秒钟。
帮助命令
- docker version
- docker info
- docker --help
镜像命令
镜像是分层的。
- docker images 查看本地镜像
- docker search 镜像名 搜索镜像
- docker pull 镜像名 下载镜像
- docker rmi 镜像名 删除镜像
删除镜像,需要先删除相关的容器实例。
容器命令
- 新建并启动容器:
- 列出当前所以正在运行的容器:
理解:
宿主机相当于大海,docker就是鲸鱼,然后各类的容器就是集装箱(可以是服务,也可以是centos或者ubuntu).
- 退出容器:
- 启动容器:
docker start 容器名\ID
注:启动以前的容器
- 重启容器:
docker restart 容器ID或者容器名
- 停止容器:
- 删除容器:
docker rm 容器ID
- 启动守护式容器:
docker run -d 容器名
注:无法启动之前的容器,会像下面的情况,容器立即退出
- 查看容器日志:
docker logs -f -t --tail 容器ID
理解:
容器可以看成一个精简版的linux环境,只是这个环境没有硬件资源,调用的还是宿主机的内核。
- 查看容器内运行的进程:
docker top 容器ID
- 查看容器内部细节:
docker inspect 容器ID
- 进入正在运行的容器并以命令行交互
exec 可以在宿主机直接操作容器内部,也可以用/bin/bash进入容器;
attach是进入容器在操作。
- 复制容器中的文件到宿主机:
docker cp 容器ID: 容器内路径 目的主机路径
注意有个:冒号
3、镜像
原理
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
- UnionFs(联合文件系统):
一种分层、轻量级并且高性能的文件系统。支持对文件系统的修改作为一次提交来一层层的叠加。
一次同时加载了多个文件系统,但是从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来。
- docker镜像加载原理
- 为何Tomcat有400M,因为里面包含了运行时环境。
- 为何docker镜像要采用分层结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mFu2yIoU-1612581227631)(Docker笔记.assets/image-20210105204752167.png)]
分层之后,镜像可能有相同的base镜像构建,每一层资源可以共享。
特点:
- docker镜像都是只读的。
- 当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为容器层,容器层之下都是镜像层。
镜像commit
- 创建Tomcat容器并且运行
理解:
容器可以是个应用也可以是类似linux的环境。
- 创建新的镜像:
- 后台创建并运行Tomcat
4、docker容器数据卷
-
将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化。
-
容器之间希望有可能共享数据。
-
类似redis中的rdb和aof 文件
-
容器持久化;
-
容器间继承+ 共享数据,或者容器到宿主机
特点:
- 数据卷可在容器之间共享或者重用数据
- 卷中的更改可以直接生效
- 数据卷中更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
直接命令添加:
- 宿主机和容器的数据共享:
宿主机和容器的这个文件目录就会共享。
容器停止退出后,主机修改后数据还是可以同步过去。
-
带权限的数据共享(只读):
主机可以修改,但是容器只读
DockerFile添加:
在镜像中创建两个容器卷。
会有个默认的位置,给宿主机挂载。
- 数据卷容器:
命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称为数据卷容器
继承关系的父子容器之间数据是共享的。
删除父容器,子容器不受影响,子容器之间的数据同样还能共享。
结论:
- 容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。
5、DockerFile解析
DockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建步骤:
- 编写DockerFile文件
- docker build
- docker run
dockerfile内容基础知识:
大致流程:
总结:
保留字指令
FROM:基础镜像,当前新镜像是基于哪个镜像的。
MAINTAINER:镜像维护者的姓名和邮箱地址
RUN:容器构建时需要运行的命令
EXPOSE:当前容器对外暴露的端口
WORKDIR:指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
ENV:用来在构建镜像过程中设置环境变量
ADD:将宿主机目录下的文件拷贝进镜像且add命令会自动处理URL和解压tar压缩包
COPY:类似add,拷贝文件和目录到镜像中。将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像的<目标路径>位置。
COPY src dest
COPY [“src” “dest”]
VOLUME:容器数据卷,用于数据保存和持久化工作
CMD:指定一个容器启动时要运行的命令。DockerFIle中可以有多个cmd指令,但只有最后一个生效,cmd会被docker run之后的参数替换。
ENTRYPOINT:指定一个容器启动时要运行的命令。ENTRYPOINT的目的和cmd一样,都是在指定容器启动程序及参数,但是不会覆盖,而是追加。
ONBUILD:当构建一个被继承的DockerFIle时运行命令,父镜像在被子镜像继承后父镜像的onbuild被触发。
案例:修改进去容器的初始路径;给容器添加vim和ifconfig功能
curl命令:
CMD和ENTRYPOINT:
一个是覆盖和一个是追加。
总结:
6、安装mysql、redis、Tomcat
- Tomcat:
-
mysql:
- docker search mysql
- docker pull mysql:5.6 (不加版本就是latest)
-
redis
- 本地镜像发布到阿里云
Tips:
- docker:
Docker容器将应用和其依赖环境全部打包到一个单一对象中,在不包含完整的操作系统的情况下就能运行普通应用,更加轻量级,可移植性更好。所以它成为了PaaS(比如Kubernates)平台的基石。
- LXD/LXC
在介绍LXD之前先介绍LXC,因为LXD可以视作LXC的升级版。LXD的管理命令和LXC的管理命令大多相同。
LXC起源于cgroup和namespaces,使得进程之间相互隔离,即进程虚拟化。
LXC有一些缺点,比如无法有效支持跨主机之间的容器迁移、管理复杂。而LXD很好地解决了这些问题。
LXC/LXD和docker不同的地方在于LXC/LXD中包含完整的操作系统。
系统容器
系统容器,直接对标虚拟机 ,甚至可以直接运行虚拟机镜像(但是不启动内核)。
系统容器运行整套操作系统(再说一次,除了内核),应用容器(如 docker)运行应用,两者不冲突。
可以在 LXD 容器里安装和使用 docker,跟在物理机和虚拟机上没什么两样。
Docker 并非是一个通用的容器工具,它依赖于已存在并运行的 Linux 内核环境。
Docker 实质上是在已经运行的 Linux 下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的 Linux 主机。
因此,Docker 必须部署在 Linux 内核的系统上。如果其他系统想部署 Docker 就必须安装一个虚拟 Linux 环境。
-
docker的每一个容器都相当于一个简易的linux版本,有防火墙,基本命令集等。
-
端口暴露/端口转发: