【Docker】基本介绍
Docker - 基础
Docker简介
什么是Docker
Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。
Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。
为什么使用Docker
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
更高效的利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
一致的运行环境
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
持续交付和部署
开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。
而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
更轻松的维护和扩展
Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
对比传统虚拟机总结
虚拟机 VS 容器
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为 MB | 一般为 GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
Docker基本概念
镜像
操作系统分为 内核 和 用户空间 对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统
Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)
相关命令
docker image ls # 列出镜像
docker image build # 根据Dockerfile文件创建镜像
docker image history <image> # 列出镜像历史
docker image import # 从文件/目录导入生成镜像
docker image inspect <image> # 显示镜像详情
docker image pull <image> # 从远程仓库拉取镜像
docker image push <image> # 推送镜像到远程仓库
docker image rm <image> # 删除镜像
docker image save <image> -o <path> # 保存镜像到文件
docker image tag <image> <image>:<tag> # 镜像打标签
Dockerfile 指令详解
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建
指令 | 作用 | 说明 |
---|---|---|
FROM | 指定基础镜像 | FROM 是必备的指令,并且必须是第一条指令 |
COPY | 复制文件 | 两种格式,一种类似于命令行,一种类似于函数调用 |
ADD | 更高级的复制文件 | 在COPY基础上增加自动解压缩的场合 |
RUN | 执行命令 | 镜像构建步骤 |
CMD | 容器启动命令 | 容器默认执行的命令 |
ENTRYPOINT | 入口点 | 容器启动程序及参数 |
ENV | 设置环境变量 | 定义了环境变量,那么在后续的指令中,就可以使用这个环境变量 |
ARG | 构建参数 | ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的 |
VOLUME | 定义匿名卷 | 对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume) |
EXPOSE | 暴露端口 | 声明容器运行时提供服务的端口 |
WORKDIR | 指定工作目录 | 指定当前目录,如该目录不存在,WORKDIR 会帮你建立目录 |
USER | 指定当前用户 | 这个用户必须是事先建立好的,否则无法切换 |
HEALTHCHECK | 健康检查 | 告诉 Docker 应该如何进行判断容器的状态是否正常 |
ONBUILD | 为构建下一层镜像准备 | 构建下一级镜像的时候才会被执行 |
LABEL | 镜像添加元数据 | 指令用来给镜像以键值对的形式添加一些元数据(metadata) |
SHELL | 指令 | SHELL 指令可以指定 RUN ENTRYPOINT CMD 指令的 shell,Linux 中默认为 |
镜像构建上下文
当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件
容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间
容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。
按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
相关命令
docker run # 构建并启动镜像
docker run -t -i ubuntu:18.04 /bin/bash # 启动一个 bash 终端,允许交互
docker run -d ubuntu:18.04 # 后台运行容器
docker container start <container> # 重启已经停止容器
docker container stop <container> # 终止容器
docker attach <container> # 附加到容器中,执行exit导致容器推出
docker exec -it <container> bash # 进入容器, 执行exit不会容器推出(推荐)
docker export <container> > ubuntu.tar # 导出镜像
cat ubuntu.tar | docker import - ubuntu:v1.0 # 导入容器快照
docker container rm <container> # 删除一个处于终止状态的容器
docker container prune # 清理所有处于终止状态的容器
仓库
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。
相关命令
docker search centos # 搜索仓库
docker pull centos # 拉取镜像
docker push username/ubuntu:18.04 # 推送镜像