Docker
一、Docker简介
1、什么是Docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
2、为什么使用Docker
- 简化程序:
问题1:
某IT部门要上线一个项目。常规操作,直接去线上服务器,拷贝一个tomcat,然后改端口号,然后部署应用到webapps文件夹下,重启就好。
一个服务器上可能会部署多个应用服务。如果某个应用出现问题,CPU100%,可能这个服务器上的其他应用也会出现问题。
对于一个大型应用拆分为几十个微服务,分别交由不同的团队开发,不同团队之间水平参差不齐。如果还采用这种部署方式,你的应用可能会因为另一个团队的应用发生意外。因部署在了同一台服务器上,导致全部出现问题。
问题2:
开发和线上代码(同一套代码)问题。开发阶段部署一套软件环境,测试人员在开发中测试没有问题,运维进行部署。但是正式部署到服务器时,发生了问题(启动参数、环境问题、漏配了参数)等意外。
问题3:
随着微服务技术的兴起,一个大的应用需要拆分成多个微服务。多个微服务的生成,就会面临庞大系统的部署效率,开发协同效率问题。然后通过服务的拆分,数据的读写分离、分库分表等方式重新架构,而且这种方式如果要做的彻底,需要花费大量人力物
力。可能需要部署很多个服务器。
问题4:
持续的软件版本发布/测试项目。到线上环境的集成Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可以实现虚拟化。Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管理。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的 任务,在Docker容器的处理下,只需要数秒就能完成。 - 避免选择恐惧症: 如果你有选择恐惧症,还是资深患者。Docker 帮你 打包你的纠结!比如 Docker 镜像;
Docker 镜像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。比如 Web 应用、后台应用、数据库应用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。 - 节省开支 一方面,云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化的方式。
- 持续交付和部署
对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像 - 更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况
3、与虚拟机的对比
实现原理技术不同 虚拟机是⽤来进⾏硬件资源划分的完美解决⽅案,利⽤的是硬件虚拟化技术,如此VT-x 、
AMD-V会通 过⼀个 hypervisor 层来实现对资源的彻底隔离。 而容器则是操作系统级别的虚拟化,利⽤的是内核的 Cgroup 和 Namespace 特性,此功能通过软件 来实现,仅仅是进程本身就可以实现互相隔离,不需要任何辅
助。使⽤资源⽅⾯不同 Docker 容器与主机共享操作系统内核,不同的容器之间可以共享部分系统资源,因此更加
轻量级, 消耗的资源更少。 虚拟机会独占分配给⾃⼰的资源,不存在资源共享,各个虚拟机之间近乎完全隔
离,更加重量级,也 会消耗更多的资源。应⽤场景不同 若需要资源的完全隔离并且不考虑资源的消耗,可以使用虚拟机。 若是想隔离进程并且需要运
行大量进程实例,应该选择 Docker 容器。
4、Docker中三个重要概念
- 仓库:Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。
- 镜像:Docker 镜像是用于创建 Docker 容器的模板,类似于Java中类的概念。
- 容器:是独立运行的一个或一组应用。通过镜像创建生成,类似于Java中的对象概念。
二、安装Docker
docker安装的官方文档是:https://docs.docker.com/engine/install/。docker现在支持Linux、Windows与Mac。由于我们使用的是CentOS,所以这里只讲在CentOS下安装docker的方式
1、系统需求
CentOS版本必须7+
2、安装前置环境
yum install -y yum-utils device-mapper-persistent-data lvm2
3、设置docker-ce版安装源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
4、安装docker
yum -y install docker-ce
5、启动/停止docker
systemctl start/stop docker
6、基于阿里云配置镜像加速
去阿里云注册一个账号然后登录,选择容器镜像服务->镜像加速器,按照官方文档修改配置文件即可 。就是给/etc/docker/daemon.json这个文件增加源。
操作完成之后,重启docker
三、Docker的基本命令
1、镜像相关的命令
1.1 搜索镜像
docker search [镜像名称]
参数介绍:
-f, --filter 根据提供的条件过滤器输出
--format 用Go模板打印出漂亮的搜索结果
--limit [n] 搜索结果的最大数量(默认值为25)
--no-trunc 不要截断输出
不过更加常用的是去https://hub.docker.com/这个网站搜索。
1.2 拉取镜像
拉取镜像类似从maven仓库中下载jar包。
docker pull [镜像名称][:标签]
注意:
拉取镜像时如果没有显示的指定tag标签,默认会拉取latest标签的版本镜像
1.3 查看本地镜像
docker images
参数介绍:
-q 只显示镜像唯一的标识信息
1.4 删除镜像
docker rmi [镜像名称:tag]/[镜像ID]
参数介绍:
-f 强制删除镜像
后面所有用到名称:tag的地方都可以用id代替,反过来也一样
2、容器相关的命令
2.1 根据镜像运行容器
docker run [镜像名称][:tag]
参数介绍:
-i 保持和 docker 容器内的交互
-t 为容器的标准输入,虚拟一个tty
-d 后台运行容器
--rm 容器在启动后,执行完成命令或程序后就销毁(不可于 -d 一起使用)
--name 给容器起一个自定义名称
--restart docker 1.12 新增加的参数,用来指定容器的重启策略, 当前提供的策略包括:
no 默认值,如果容器挂掉不自动重启。
on-failure,若容器的退出状态非0,则docker自动重启容器,还可以指定重启次数
always,只要容器退出,则docker将自动重启容器
-p 将宿主机中的某个端口映射到容器中的某个端口上
-e 动态设置容器的运行环境变量
注意:如果run的镜像在本地不存在,就会自动的进行拉取
比较常用的参数是-d --name -p
2.2 查看容器
docker ps
参数介绍:
-a 查看所有容器(默认不查询停止的容器)
-q 只查询容器的id
2.3 容器启动/停止/重启
docker start/stop/restart 容器名称
2.4 查看容器的元数据(容器的详细信息)
docker inspect 容器名称
2.5 删除容器
docker rm 容器名称
参数介绍:
-f 表示强制删除一个容器(默认不能删除一个运行中的容器)
2.6 进入容器中
docker exec [option] 容器名称 [args]
参数介绍:
-i 保持和 docker 容器内的交互
-t 为容器的标准输入,虚拟一个tty
-w 指定进入容器后的工作路径args:表示进入容器后执行的命令,如果需要和容器进行交互式访问,需要配置参数为-it,并且命令设置为bash(表示通过命令行的方式交互访问容器)
注意:
该命令只能进入到运行中的容器
一般使用的方式是:docker exec -it 容器名称 bash
2.7 查看容器运行日志
docker logs 容器名称
参数介绍:
--tail n 选项可以指定查看最后n条日志
-t 选项则可以对日志条目附加时间戳。
--until 显示在某个时间戳(例如:2018-05-25T 13:23:37)之前的日志,还可以相对时间(例如:42m 42 minutes)
-f 实时打印日志内容
2.8 宿主机和容器间的数据拷贝
docker cp [OPTIONS] 容器名称:容器内路径 宿主机路径
docker cp [OPTIONS] 宿主机路径 容器名称:容器内路径
注意:
1、复制文件夹不需要添加任何参数(和Linux的命令有区别)
2、无论需要从哪儿拷贝到哪里,命令都是在宿主机执行
四、容器数据卷
1、 什么是容器数据卷?
数据卷存在于宿主机中,独立于容器,和容器的生命周期是分离的
数据卷可以目录也可以是文件
容器可以利用数据卷与宿主机进行数据共享,实现了容器间的数据共享和交换
2、 容器数据卷的特点
1、容器启动时初始化数据卷,如果容器使用的镜像包含了数据,这些数据也会拷贝到数据卷中
2、对 数据卷 的修改会立马生效
3、数据卷的变化不会影响镜像的更新
4、数据卷是宿主机中的一个目录
3、 数据卷的运用场景
1、在多个运行容器之间共享数据。如果您没有明确创建它,则会在第一次将其装入容器时创建卷。当该容器停止或被移除时,该卷仍然存在。多个容器可以同时安装相同的卷,无论是读写还是只读。仅当您明确删除卷时才会删除卷
2、当您想要将容器的数据存储在远程主机或云提供商上而不是本地时
3、当您需要备份,还原或将数据从一台Docker主机迁移到另一台时,卷是更好的选择。您可以停止容器,然后备份卷的目录
4、数据卷的相关命令
4.1 创建容器数据卷
docker volume create 数据卷名称
注意
容器卷默认保存在宿主机的/var/lib/docker/volumes路径下
4.2 创建容器时指定数据卷
docker run -it
--mount source=数据卷名称,target=容器中的挂载路径,type=volume
--name 容器别名 镜像名称
参数介绍:
source 指定宿主机中数据卷的名称
target 指定容器中对应的挂载路径
type 指定为数据卷的方式挂载,还可以选择bind、tmpfs,默认为volume
注意:
1、如果挂载一个空的数据卷到容器中的一个非空目录中,那么这个目录下的文件会被复制到数据卷中
2、如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录中会显示数据卷中的数据。如果原来容器中的目录中有数据,那么这些原始数据会被隐藏掉
此外还有一种简写方式:
docker run ... [-v 宿主机数据卷:docker容器路径:ro] []...
注意:
1、通过这种方式可以任意指定宿主机的数据卷位置
2、如果随意指定数据卷的位置,容器中对应路径的文件就不会复制到宿主机的数据卷中,而是全部被清空
3、:ro表示以只读的方式挂载容器卷,不写再表示以读写的方式挂载
4、可以通过-v连续设置多个容器卷路径
总结:
数据卷未显示声明路径(默认在/var/lib/docker/volumes下)
1、数据卷为空,对应的容器路径有数据,则容器中的数据直接同步到数据卷中
2、数据卷有数据,对应的容器路径不存在,则启动容器时,自动创建该容器路径,并且将数据卷的数据同步到该路径下
3、数据卷有数据,对应的容器路径也有数据(数据不同),会把数据卷中的数据同步到容器路径中,容器路径中的文件会被隐藏(宿主机 覆盖 容器)如果宿主机的数据卷为空,容器覆盖宿主机,如果数据卷不为空,则宿主机覆盖容器
数据卷声明指定路径
1、数据卷为空,对应的容器路径有数据,则直接将容器路径中的数据隐藏
2、数据卷有数据,对应的容器路径不存在,则启动容器时,自动创建该容器路径,并且将数据卷的数据同步到该路径下
3、数据卷有数据,对应的容器路径也有数据(数据不同),会把数据卷中的数据同步到容器路径中,容器路径中的文件会被隐藏(宿主机 覆盖 容器)无论情况如何,永远是宿主机 覆盖 容器路径
数据卷是文件的情况
1、数据卷指定一个文件,对应的容器文件不存在,直接将数据卷文件覆盖到容器中
2、数据卷指定的文件不存在,容器的文件存在,启动容器会报错如果需要绑定文件,则必须保证宿主机的数据卷中文件必须存在
五、Docker的应用
1、使用docker安装MySQL
1.1 拉取mysql的镜像
docker pull mysql:5.7
1.2 根据镜像创建容器
docker run -d
-v ~/mysql/conf:/etc/mysql/conf.d //2
-v ~/mysql/logs:/logs //3
-v ~/mysql/data:/var/lib/mysql //4
-p 3306:3306 //5
-e MYSQL_ROOT_PASSWORD='root' //6
--name mysql
mysql:5.7
代码解释
第二行:挂载mysql配置文件到宿主机
第三行:挂载mysql日志文件到宿主机
第四行:挂载mysql的数据路径到宿主机
第五行:将容器中3306端口映射到宿主机的3306端口上
第六方:设置MySQL的root账号密码为root
设置数据库编码
进入~/mysql/conf中,创建一个文件my.cnf,填写如下内容:
[mysqld]
character-set-server=utf8重启mysql容器
2、 使用docker安装tomcat
2.1 拉取tomcat的镜像
docker pull tomcat:8
2.2 运行tomcat容器
docker run -d
--name tomcat
-p 8080:8080
-v ~/tomcat/webapps:/usr/local/tomcat/webapps
tomcat:8
2.3 进入容器中进行相关拷贝
docker exec -it tomcat bash
cp -r webapps.dist/* webapps
注意:
docker镜像tomcat8之后容器中webapps中没有任何内容,需要将欢迎页导入
2.4 将自定义工程部署到tomcat中
1、使用maven命令或者工具将自定义工程打包
2、到工程的target目录下找到打的war包
3、将war包拷贝到宿主机的tomcat数据卷中
4、重启tomcat容器 docker restart tomcat
六、Docker镜像的制作与管理
1、 什么是Dockerfile?
Dockerfile简单来说就是docker镜像的描述文件,最基础原始的镜像文件都是通过dockerfile文件构建而来
2、 Dockerfile模板指令介绍
FROM:指定基础镜像,必备的指令,并且必须是第一条指令。
MAINTAINER:指明该镜像的维护者和点子邮件。
比如:MAINTAINER xxxx "xxxxx@qq.com"ENV:设置环境变量。
比如:EVN key1=value1 key2=value2...RUN:在新镜像内部执行的命令,比如安装一些软件、配置一些基础环境,可使用\来换行。
比如:RUN yum install -y mysql-serverCOPY:将主机的文件复制到镜像文件中,如果目标位置不存在会自动创建。
比如:COPY application.yml /etc/resourcesADD:和COPY一样,但是ADD会加上解压操作
EXPOSE:暴露镜像的端口供主机做映射,可以暴露多个端口。
比如:EXPOSE 8080WORKDIR:在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录,而且在进入容器时,会默认定位到该路径下。
比如:WORKDIR /usr/localVOLUME:用来向基础镜像中添加数据卷
比如 VOLUME /root/mydata /root/condataCMD:容器启动时需要执行的命令。
比如 CMD /bin/bash
3、 案例:使用Dockerfile构建自定义工程的运行镜像
3.1 准备好Dockerfile文件以及需要部署的工程war包
3.2 Dockerfile文件内容
FROM tomcat:8
WORKDIR /usr/local/tomcat
COPY test.war ./webapps
EXPOSE 8080
CMD ["catalina.sh", "run"]
解释:
第一行:该镜像时基于tomcat:8镜像构建
第二行:设置当前基础路径,也是后续命令的相对路径
第三行:将工程war包复制到tomcat的webapps路径下
第四方:对外暴露8080端口,也就是tomcat访问路径
第五行:设置容器启动时命令,即启动tomcat
3.3 通过Dockerfile构建镜像
执行命令
docker build -f ./Dockerfile -t mytest:v1 .
解释:
-f 用来指定Dockerfile模板文件
-t 用来指定自定义镜像的名称以及tag
最后的.表示当前路径
4、 将自定义镜像推送至镜像中心(私服、阿里云等,这里以阿里云举例)
登录阿里云,并且选择容器镜像服务
创建容器仓库
登录阿里云的仓库并且通过命令推送镜像到阿里云
docker login --username=账号 registry.cn-hangzhou.aliyuncs.com docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/ken-hub/myhub:[镜像版本号] docker push registry.cn-hangzhou.aliyuncs.com/ken-hub/myhub:[镜像版本号]
七、Docker -Compose
1、 什么是Docker-compose
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务
2、 Docker-Compose安装
前置条件:安装好Docker
下载docker-compose二进制文件到服务器指定目录
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
执行授权操作
sudo chmod +x /usr/local/bin/docker-compose
测试
docker-compose --version
3、 Docker-Compose模板文件
3.1 什么是模板文件?
模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多。但是这里面大部分指令跟 docker run 相关参数的含义都是类似的。
默认的模板文件名称为 docker-compose.yml ,格式为 YAML 格式。
3.2 docker-compose模板基本格式案例
version: "3.1"
services:
webapp:
image: examples/web
ports:
- 80:80
volumes:
- /data
3.3 docker-compose模板文件常用指令
image:指定为镜像名称或镜像 ID
ports:设置暴露端口,容器端口 (HOST:CONTAINER) 格式
volumes:数据卷所挂载路径设置
command:覆盖容器启动后默认执行的命令
container_name:指定容器名称
environment:设置环境变量
build:指定 Dockerfile 所在文件夹的路径
3.4 docker-compose基本命令
创建并运行容器
docker-compose up -d
参数:
-d 表示后台运行
启动容器
docker-compose start
停止容器
docker-compose stop
停止并移除容器
docker-compose down
注意:命令必须在docker-compose.yml文件所在位置执行