一、背景
最近,Docker技术真是一片火热,它的出现也弥补了虚拟机资源消耗过高的问题,直接让虚拟化技术有了质的飞跃。那么本文我们来聊一聊Docker,和大家一起认识Docker,简单入门Docker.
二、虚拟化技术简介和发展
1. 阶段一:无虚拟化技术
众所周知,在虚拟化技术出现之前,我们依靠扩展物理机的方式来扩展我们的应用,这个阶段很痛苦,也有很多的缺点,比如:
- Capex费用昂贵
- Go to Product速度极其慢
- 系统可移植行极低
- 资源利用率极低
2. 阶段二:基于Hypervisor的虚拟化技术
这个阶段,出现的虚拟化技术让很多人开心不已,随着时间的流逝,市面上也出现不少相关的实际应用的技术,如:VMware、KVM、AWS、Microsoft的Hyper-V等。
基于Hypervisor的虚拟化技术的优点:
- 资源利用率高
- 易于扩展、伸缩
- Go to Product快速
- 成本降低
基于Hypervisor的虚拟化技术的缺点:
- OS内核资源被重复消耗资源
- 应用移植性较低
3. 阶段三:基于容器的虚拟化技术
由于Hypervisor的虚拟化技术不是很完美,对内核的资源重复消耗,那随着技术的发展就出现了基于容器的虚拟化技术,最热的就是Docker Container了。它底层使用CGroup和Namespace来实现多个容器之间共享内核资源。而且它还能保证运行时相互隔离,互不影响。
基于容器虚拟化技术的优点:
- 资源利用率更高
- 非常高效
- 更易于扩展、伸缩
- Go to Product更快速
- 一致性
- 可封装性
- 应用隔离性
运行时隔离,最典型的应用就是使得我们可以很方便和简单的实现在同一台机器上运行基于不同版本Java开发的应用。如下图:
基于Hypervisor的虚拟化技术 VS 基于容器的虚拟化技术
- 容器提供OS层的虚拟化(OS Virtualization)
- 容器可以避免Machine Virtualiztion启动的开销
- 容器主要给应用提供虚拟化的运行环境
- 容器只提供给应用所需的可执行文件和依赖库
- 虚拟机主要给操作系统提供运行环境
三、Docker架构
- Docker daemon
- 处理Docker API 请求
- 管理Docker对象:如镜像、容器、网络等。
- Docker client
- Docker client使用Docker API 跟 Docker daemon进行通信交互
- 可以跟多个不同的Docker Daemon进行通信
- Docker Registries
- 存储Docker镜像
- 公有和私有Docker Registry
- Docker对象
- 镜像
- 容器
四、Docker术语
- 镜像
- 镜像是用来创建容器的只读模板
- 镜像是通过Docker build命令创建的
- 镜像由镜像层构成
- 镜像存储于Docker Registry
- 容器
- 容器是镜像的运行实例
- 容器是应用运行环境的封装,具有轻量级、移植性高等特点
- 容器由镜像创建,内部封装所有运行应用所需依赖及可执行文件
- Registries和Repositories
- Registry是存储Docker镜像的地方(可类比为Maven仓库)
- 可自建私有Registry和使用公用Registry,如:Docker Hub
- 在Registry中,镜像存储在Repository
- Docker Repository是具有相同名字,不同标签的Docker镜像的集合(可类比为Maven仓库中的某个依赖所在的文件夹,可以有不同版本)
- Docker Hub
- 公有:Docker Registry
- 私有:Docker Registry
- 官方Docker镜像
- 文档清晰、完整
- 安全,更新及时
- 安全性更高
五、Docker的安装
- 环境准备
- Centos 7
- Docker社区版安装步骤
- 删除已安装所有老版本docker相关(docker或者docker-engine)
yum remove -y docker docker-common docker-selinux docker-engine - 安装devicemapper驱动和yum工具
yum install -y yum-utils device-mapper-persistent-data lvm2 - 配置repo
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
- 安装docker社区版
yum install -y docker-ce - 启动docker
systemctl start docker
docker info]命令,则会出现:Cannot connect to the Docker daemon. Is the docker daemon running on this host?
- Centos官方版安装步骤
yum install -y docker - 验证安装
docker version
docker info
六、Docker常用命令
- docker version 查看docker版本信息
- docker info 查看docker基本信息
- docker images 查看所有本地镜像
- docker ps [-a] 查看所有正在运行的容器
- -a查看所有的容器
- docker search repository:tag 在远程仓库搜索指定镜像
- docker pull repository:tag 从远程仓库下载指定镜像
- docker run [-t -i -d --name containerName -p port] repository:tag cmd命令 基于一个镜像运行一个容器
- -t 绑定终端
- -i 交互模式
- -d 后台运行
- --name 指定容器的名称
- -p 指定容器暴露的端口,如:8080:8080
- -P 和-p互斥,当使用 -P 标记时,Docker 会随机映射一个
49000~49900
的端口到内部容器开放的网络端口
- docker start containerId 启动一个已经停止的容器
- docker stop containerId 停掉一个正在运行的容器
- docker rm [-f] containerId/containerName 删除指定容器
- -f 强制删除,不论容器是否正在运行
- docker rmi imageId/imageName 删除指定镜像
- docker commit [-a author] containerId repository:tag
- -a author 指定作者
- docker logs [-f] containerId 查看容器日志
- docker history imageId/repository:tag 查看镜像的各层信息
- docker inspect containerId/containerName 查看容器更底层的信息
- docker save -o fileName imageId/repository:tag 将指定的镜像打包保存
- docker import fileName repository:tag 使用指定文件创建镜像
- docker exec [-t -i] containerId/containerName CMD 利用指定容器执行指定的cmd命令
- docker build -t repository:tag . [--no-cache=true] 使用当前目录下的Dockerfile文件构建镜像
- “.” 代表使用当前目录下Dockerfile
- --no-cache=true 不使用缓存,默认是缓存
- docker login 登陆到远程仓库
- docker push repository[:tag] 提交镜像到远程仓库
- docker rm -f $(docker ps -qa -f status=exited) 删除所有已经停掉的容器
前台运行 VS 后台运行
- 前台运行Docker容器
- 默认方式
- docker run 运行容器中的应用并将console和应用进程中的标准输入、输出及错误关联起来
- 容器启动后不能在console中执行其他命令
- 后台运行Docker容器
- 需要指定 -d 选项
- docker run 将容器在后台启动,通常容器中的主程序退出后容器随之退出
- 容器启动后可以在console中继续执行其他命令
七、Docker端口映射和日志
最典型的案例是:当我们运行tomcat镜像的时候,我们需要为该容器指定向外暴露的端口以及查看容器运行时tomcat的日志信息。
- 端口暴露
- 运行时指定 -p或者-P选项,-p允许我们指定端口信息,-P是docker默认随机映射一个
49000~49900
的端口到内部容器开放的网络端口
- 查看日志
- docker logs containerId 查看容器输出的日志信息
- 也可以后台运行容器,然后使用docker exec -ti containerId bash 命令进到logs目录下查看catlina.log日志信息
八、Docker 镜像
- Docker镜像是容器的基础
- Docker镜像是由有序文件系统层以及容器运行时所需参数组成
- Docker镜像是无状态的
- Docker镜像是不可更改的
- 运行中的容器,所有的变化被写入可写层
- 一旦容器被删除,可写入层随之删除,但base镜像依旧存在
- 多个容器共享相同的base镜像层
九、创建Docker镜像
- 通过docker commit命令来基于容器创建Docker镜像
- 通过docker build 命令配合Dockerfile文件创建Docker镜像
下面是一个简单的Dockerfile文件
FROM centos:7
LABEL maintainer "hafiz.zhang(hafiz.zhang@example.com)"
RUN yum update -y
RUN yum install -y git
- Dockerfile是一个包含用户创建Docker镜像的所有命令的文本文件
- Dockerfile中的命令指定在创建Docker镜像时做什么操作
- Docker读取Dockerfile中的命令来创建Docker镜像
- Dockerfile中的每个命令都将被Docker使用来创建一个新的Docker镜像层
Docker build 上下文
- Docker客户端以当前目录为build上下文
- 默认读取当前目录的Dockerfile进行build
- Docker客户端开始build后会将build上下文目录的文件打包成tar包并上传给Docker Daemon守护进程
十、深入Dockerfile
- RUN指令
- RUN指令在容器的可写入层执行命令,并commit容器为新的镜像
- 上一步RUN命令生成的镜像会被接下来的RUN指令使用,每次RUN指令生成一个新的镜像
- Dockerfile中最好使用链式输入命令以减少创建镜像层的数量
- CMD指令
- CMD指令指定容器启动时执行什么命令
- 如果在Dockerfile中不指定CMD指令,Docker将使用基础镜像提供的默认命令
- CMD指令在创建Docker镜像时不执行,只有在容器启动时才执行
- 既可以以exec形式也可以以shell形式指定要执行的命令
- CMD 指令指定命令使用JSON格式,只能使用双引号,不能使用单引号
- CMD ["echo", "HelloWorld"] 使用exec形式,不能获取到$HOME等环境变量信息
- CMD ["sh", "-c", "echo $HOME"] 使用shell脚本形式,能获取到HOME等环境变量信息
- build镜像的时候不会运行CMD指令指定的命令,只要在使用镜像启动容器时才运行CMD指令指定的命令
- COPY指令
- COPY指令从build上下文复制文件或者文件夹到容器文件系统
- ADD指令
- ADD指令不但可以复制文件到容器文件系统,而且还可以从internet上下载文件并复制到容器
- ADD指令可以自动解压压缩文件
- 通常我们使用COPY指令,除非明确需要ADD指令
- Docker缓存
- 每次Docker执行一个指令将创建新的镜像
- 如果下一次指令没有发生变化,Docker默认使用现有的缓存
- 可以通过指定 --no-cache=true 来指定不使用缓存
- 也可以使用链式命令来避免使用缓存
十一、上传Docker镜像到Docker Hub
- 首先注册Docker Hub账号
- docker tag 给镜像打标签
- Repository格式:ID/镜像名字
- Latest标签
- 默认Docker使用latest作为标签
- 通常Repository用latest表示竟像是最新稳定版,但这只是默认传统,不是强制要求
- 当新版本镜像上传到Repository,latest标签的镜像不会自动更新
- 尽量避免使用latest标签
十二、总结
通过本文,我们就对Docker有了一个直观的理解,也明白了如何从远程仓库拉取镜像,运行镜像,如何进行端口映射等等Docker基础知识。感觉很充实~