1. 简介
Docker 是一个供开发人员和系统管理员构建、运行和与容器共享应用程序的平台。Docker 通常用于 web 应用的自动化打包和发布,自动化测试和持续集成、发布等场景。
1.1 应用部署的环境问题
大型项目组件较多,运行环境也较为复杂,部署时经常会遇到一些问题。例如一个项目中,部署时需要依赖于 node.js、Redis、Kafka、MySQL 等,这些服务部署时所需要的函数库、依赖项各不相同,甚至会有冲突。给部署带来了极大的困难。
Docker为了解决依赖的兼容问题的,采用了两个手段:
- 将应用的Libs(函数库)、Deps(依赖)、配置与应用一起打包
- 将每个应用放到一个容器去运行,避免互相干扰。
这样打包好的应用包(镜像)中,既包含应用本身,也包含应用所需要的Libs、Deps,无需在操作系统上安装这些,自然就不存在不同应用之间的兼容问题了。
1.2 操作系统环境差异问题
Linux 有多种不同的发行版本,例如:Ubuntu、Fedora、CentOS。但实际上这些发行版是共用一套 Linux 内核,只是系统应用不同,以 Ubuntu 系统的架构为例。
图中的系统应用,本质上是对内核指令的封装,目的是为了提供更便于使用的应用和函数库。
应用于计算机交互的流程如下:
- 应用调用操作系统应用(函数库),实现各种功能
- 系统函数库是对内核指令集的封装,会调用内核指令
- 内核指令操作计算机硬件
补充一下 OS 内核的知识:
现代 OS 一般将 OS 划分为若干层次,再将 OS 的不同功能分别设置在不同的层次中。通常将一些与硬件紧密相关的模块(如中断处理程序等)、各种常用设备的驱动程序以及运行频率较高的模块(如时钟管理、进程调度和许多模块所公用的一些基本操作),都安排在紧靠硬件的软件层次中,将它们常驻内存,即通常被称为的 OS 内核。这种安排方式的目的在于两方面:一是便于对这些软件进行保护,防止遭受其他应用程序的破坏;二是可以提高 OS 的运行效率。
如果我们将一个 Ubuntu 版本的 MySQL 应用安装到 CentOS 系统中,MySQL 在调用 Ubuntu 函数库时,会发现找不到或者不匹配(因为 MySQL 运行在 CentOS 下),就会出现错误,如下图所示:
为了解决系统环境问题,Docker 将用户程序与所需要调用的系统(比如 Ubuntu)函数库一起打包。所以 Docker 的应用包在不同的 OS 下运行时,直接调用打包的函数库,借助于统一了 Linux 内核来运行。
1.3 Docker 的优点
-
简化程序: Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可以实现虚拟化。Docker 改变了虚拟化的方式,使开发者可以直接将自己的成果放入 Docker 中进行管理。方便快捷已经是 Docker 的最大优势,过去需要用数天乃至数周的任务,在 Docker 容器的处理下,只需要数秒就能完成。
-
避免选择恐惧症: 如果你有选择恐惧症,还是资深患者。Docker 帮你打包你的纠结!比如 Docker 镜像;Docker 镜像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。比如 Web 应用、后台应用、数据库应用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。
-
节省开支: 一方面,云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化的方式。
-
一致性:
容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:
- 您的开发人员在本地编写代码,并使用 Docker 容器与同事共享他们的工作。
- 他们使用 Docker 将其应用程序推送到测试环境中,并执行自动或手动测试。
- 当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中,以进行测试和验证。
- 测试完成后,将修补程序推送给生产环境,就像将更新的镜像推送到生产环境一样简单。
Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。
2. Docker 架构
Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程 API 来管理和创建 Docker 容器。Docker 服务端是一个服务进程,管理控制着所有的 Docker 容器。Docker 客户端用于控制 Docker 服务端进程。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类。
| Docker | 面向对象 |
|---|---|
| 容器 | 对象 |
| 镜像 | 类 |
| 概念 | 说明 |
|---|---|
| Docker 镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板,类似于面向对象中的类。 |
| Docker 容器(Container) | 容器是独立运行的一个或一组应用,是镜像运行时的实体,类似于实例化的对象(镜像的实例化),容器与容器之间通过沙箱机制,相互隔离。 |
| Docker 客户端(Client) | Docker 客户端是用户和 Docker 进行交互的工具。Docker 客户端通过命令行或者其他工具使用 Docker API (docs.docker.com/engine/api/) 与 Docker 的守护进程通信。 |
| Docker 主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
| Docker 仓库(Registry) | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(hub.docker.com) 提供了庞大的镜像集合供使用。 |
| Docker Machine | Docker Machine 是一个简化 Docker 安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如 VirtualBox、 Digital Ocean、Microsoft Azure。 |
3. 基于 yum 安装 Docker(CentOS7)
1、环境查看
Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。
所以在安装之前,首先通过 uname -r 命令查看你当前的内核版本
uname -r
2、安装需要的安装包
sudo yum install -y yum-utils
3、设置镜像的仓库
这里设置了阿里云的镜像仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4、更新yum软件包索引
yum makecache fast
5、安装 Docker
yum -y install docker # 默认为社区版
如果要指定安装版本(社区版 or 企业版),参考如下:
# docker-ce 为社区版
yum install docker-ce docker-ce-cli containerd.io
# docker-ee 为企业版
yum install docker-ee docker-ee-cli containerd.io
注意:如果下载企业版 Docker,要对应修改镜像仓库地址(在第三步)
6、启动 Docker 后台服务
service docker start
或者
systemctl start docker
7、使用docker version 查看是否安装成功
docker version
8、测试运行 hello-world
docker run hello-world
由于本地没有 hello-world 这个镜像,所以 Docker 会下载一个 hello-world 的镜像,并在容器内运行。
可以通过 docker ps 指令查看容器是否在运行中
4. 常用指令
更多指令及实例可参考:菜鸟教程——Docker 教程
4.1 Docker 镜像使用指令
-
docker images 查看所有本地主机上的镜像
[root@AlibabaECS ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 8 months ago 13.3kB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的id CREATED 镜像的创建时间 # 可选项 -a, --all # 列出所有的镜像 -q, --quiet # 只显示镜像的id -
docker search 搜索镜像
[root@AlibabaECS ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 9911 # 可选项 --filter , -f Filter output based on conditions provided docker search mysql -f=stars=5000 -
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag] [root@AlibabaECS ~]# docker pull mysql Using default tag: latest # 如果不写tag,默认就是latest latest: Pulling from library/mysql bf5952930446: Pull complete # 分层下载,docker image的核心 联合文件系统 8254623a9871: Pull complete 938e3e06dac4: Pull complete ea28ebf28884: Pull complete f3cef38785c2: Pull complete 894f9792565a: Pull complete 1d8a57523420: Pull complete 6c676912929f: Pull complete ff39fdb566b4: Pull complete fff872988aba: Pull complete 4d34e365ae68: Pull complete 7886ee20621e: Pull complete Digest: sha256:c358e72e100ab493a0304bda35e6f239db2ec8c9bb836d8a427ac34307d074ed # 签名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址 # 两条命令等价 docker pull mysql docker.io/library/mysql:latest # 指定版本下载 docker pull mysql:5.7 [root@AlibabaECS ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql bf5952930446: Already exists 8254623a9871: Already exists 938e3e06dac4: Already exists ea28ebf28884: Already exists f3cef38785c2: Already exists 894f9792565a: Already exists 1d8a57523420: Already exists 5f09bf1d31c1: Pull complete 1b6ff254abe7: Pull complete 74310a0bf42d: Pull complete d398726627fd: Pull complete Digest: sha256:da58f943b94721d46e87d5de208dc07302a8b13e638cd1d24285d222376d6d84 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7
-
docker rmi 删除镜像
[root@AlibabaECS ~]# docker rmi -f 容器id # 删除指定的容器 [root@AlibabaECS ~]# docker rmi -f 容器id 容器id 容器id # 删除多个容器 [root@AlibabaECS ~]# docker rmi -f $(docker images -aq) # 删除全部容器 -
docker build 构建镜像
我们使用命令 docker build , 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。
[root@AlibabaECS ~]# cat Dockerfile FROM centos:6.7 MAINTAINER Fisher "xxxx@qq.com" RUN /bin/echo 'root:123456' |chpasswd RUN useradd addd RUN /bin/echo 'addd:123456' |chpasswd RUN /bin/echo -e "LANG="en_US.UTF-8"" > /etc/default/local EXPOSE 22 EXPOSE 80 CMD /usr/sbin/sshd -D每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
第一条FROM,指定使用哪个镜像源
RUN 指令告诉docker 在镜像内执行命令,安装了什么。。。
然后,我们使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像。
[root@AlibabaECS ~]# docker build -t addd/centos:6.7 . Sending build context to Docker daemon 17.92 kB Step 1 : FROM centos:6.7 ---> d95b5ca17cc3 Step 2 : MAINTAINER Fisher "xxxx@qq.com" ---> Using cache ---> 0c92299c6f03 Step 3 : RUN /bin/echo 'root:123456' |chpasswd ---> Using cache ---> 0397ce2fbd0a Step 4 : RUN useradd addd ...... # 参数说明 -t :指定要创建的目标镜像名 . :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
4.2 Docker 容器使用指令
-
新建容器并启动
docker run [可选参数] image # 参数说明 --name = "Name" 容器名字 tomcat01,tomcat02,用来区分容器 -d 后台方式运行 -it 使用交互方式运行,进入容器查看区分 -p 指定容器的端口 -p 8080:8080 -p ip:主机端口:容器端口 -p 主机端口:容器端口(常用) -p 容器端口 容器端口 -p 随机指定端口 # 测试,启动并进入容器 [root@AlibabaECS bin]# docker run -it centos /bin/bash # 从容器中退回主机 [root@AlibabaECS bin]# exit -
列出所有的运行的容器
# docker ps 命令 # 列出当前正在运行的容器 -a # 列出当前正在运行的容器+带出历史运行过的容器 -n=? # 显示最近创建的容器 -q # 只显示容器的编号 -
退出容器
exit # 直接容器停止并退出 Ctrl + P + Q # 容器不停止退出 -
删除容器
docker rm 容器id # 删除指定容器,不能删除正在运行的容器,如果要强制删除 rm -f docker rm -f $(docker ps -aq) # 删除所有的容器 docker ps -aq|xargs docker rm # 删除所有的容器 -
启动和停止容器的操作
docker start 容器id # 启动容器 docker restart 容器id # 重启容器 docker stop 容器id # 停止当前正在运行的容器 docker kill 容器id # 强制停止当前容器 -
查看容器网络端口
docker port 容器id # 查看容器网络端口 -
查看容器日志
docker logs -f 容器id # -f:让 dokcer logs 像使用 tail -f 一样来输出容器内部的标准输出。 -
查看容器的进程
可以使用 docker top 来查看容器内部运行的进程
docker top 容器id -
检查容器底层信息
docker inspect 容器id -
进入当前正在运行的容器
# 方式一 docker exec -it 容器id /bin/bash # 方式二 docker attach 容器id -
从容器内拷贝到主机上
# 命令 docker cp [r] 容器id :容器内路径 目的地主机路径 # 参数r : 递归拷贝 # 测试 [root@AlibabaECS home]# docker cp a485a9d900b4:/home/test.java /home
5. Docker 日志查看指南
语法
docker logs [OPTIONS] 容器id
OPTIONS说明:
- -f : 跟踪日志输出
- --since : 显示某个开始时间的所有日志
- -t : 显示时间戳
- --tail : 仅列出最新N条容器日志
使用示例:
docker logs -f -t --tail 10 ax1111aadd456 # 实时查看docker容器名为smartbus的最后10行日志
docker logs -f -t --since="2023-01-16" --tail=100 ax1111aadd456 # 查看指定时间后的日志,只显示最后100行
docker logs --since 30m ax1111aadd456 # 查看最近30分钟的日志
docker logs -t --since="2023-01-16T18:43:13" ax1111aadd456 # 查看某时间之后的日志
# 查看某时间段的日志
docker logs -t --since="2023-01-16T18:43:13" --until "2023-01-16T18:53:13" ax1111aadd456
# 将错误日志写入文件
docker logs -f -t --since="2023-01-16" ax1111aadd456 | grep error >>logs_error.txt
话外——浅谈 Docker 和 VM 的区别
早期我是一个苦逼的虚拟机使用者,电脑开一个虚拟机别提有多卡多慢了。后来学了 Docker,我直接卸载了虚拟机,Docker 牛逼!!!
Docker 可以让一个应用在任何操作系统中非常方便的运行。而虚拟机也能在一个操作系统中,运行另外一个操作系统,保护系统中的任何应用。
不同的是,虚拟机(virtual machine)是在操作系统中模拟硬件设备,然后运行另一个操作系统,比如在 Windows 系统里面运行 Ubuntu 系统,这样就可以运行任意的Ubuntu应用了。
Docker仅仅是封装函数库,并没有模拟完整的操作系统,如图:
从使用体验上来说:
- Docker 的性能更加接近原生,而虚拟机性能较差
- Docker 的资源占用更少,虚拟机会占用大量的资源(内存资源、硬盘资源等...)
- Docker 启动更快,虚拟机启动较慢
- Docker 出错率更低,虚拟机容易出现各种难以排查的错误
- Docker 使用简单,虚拟机配置繁杂