一、Docker原理简介
1.1、为什么会有Docker出现
-
一款产品从开发到上线、从操作系统、运行环境,再到应用配置,作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验;
-
Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。
-
环境配置如此麻烦,换一台机器,就要重来一次,费力费时,很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。开发人员利用 Docker 可以消除协作编码时"在我的机器上可正常工作"的问题。
-
如果之前在服务器配置一个应用的运行环境,要安装各种软件,就拿一个最基本的项目的环境来说吧Java/Tomcat/MySQL/JDBC驱动包等。安装和配置这些东西有多麻烦就不说了,它还不能跨平台,假如我们是在 Windows 上安装的这些环境,到了 Linux 又得重新装,况且就算不跨操作系统,换另一台同样操作系统的服务器,要移植应用也是非常麻烦的。
-
传统上认为,软件编码开发/测试结束后,所产出的成果即是程序或是能够编译执行的二进制字节码等(java为例)。而为了让这些程序可以顺利执行,开发团队也得准备完整的部署文件,让运维团队得以部署应用程式,开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境,不过,即便如此,仍然常常发生部署失败的状况。
-
Docker镜像的设计,使得Docker得以打破过去【程序即应用】的观念,透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
1.2、Docker理念
-
Docker
是基于Go
语言实现的云开源项目 -
Docker
的主要目标是 “Build,Ship and Run Any App,Anywhere”,意思就是说:在任何地方构建、发布和运行任何应用程序,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到:“一次封装,到处运行”。 -
Linux 容器技术的出现就解决了这样一个问题,而
Docker
就是在它的基础上发展过来的,将应用运行在Docker
容器上面,而Docker
容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
1.3、Docker架构图
Registry
:注册Images
:镜像Containers
:容器
二、Docker安装教程
- 以下环节为Centos7安装Docker方式;
cat /etc/redhat-release
:查看自己的Centos版本;- 且虚拟机必须可以连接外网;
2.1、Docker网站
- 国外网站:
http://www.docker.com
- 国内网站:
https://dockerdocs.cn
- 镜像仓库:
https://hub.docker.com
2.2、更新Yum源信息
yum update
2.3、Yum安装Gcc相关
1、yum -y install gcc
2、yum -y install gcc-c++
2.4、Yum安装软件包
#卸载之前的旧版本Docker
1、yum -y remove docker docker-common docker-selinux docker-engine
2、yum install -y yum-utils device-mapper-persistent-data lvm2
2.5、设置stable镜像仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
2.6、Yum安装Docker-ce
yum -y install docker-ce
2.7、测试Docker安装成功
docker version
2.8、Docker系统命令
#启动docker
systemctl start docker
#重启docker
systemctl restart docker
#停止docker
systemctl stop docker
#开机启动docker
systemctl enable docker
#查看docker状态
systemctl status docker
2.9、配置镜像加速
- https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors:阿里云地址查看自己的镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://cjbhlr8d.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
三、Docker常用命令
3.1、帮助启动类命令
#启动docker
systemctl start docker
#停止docker
systemctl stop docker
#重启docker
systemctl restart docker
查看docker状态
systemctl status docker
开机启动docker
systemctl enable docker
查看docker概要信息
docker info
查看docker总体帮助文档
docker --help
查看docker命令帮助文档
docker 具体命令 --help
3.2、镜像命令
3.2.1、[docker images]
#列出本地主机上所有的镜像
docker images [OPTIONS] [REPOSITORY[:TAG]]
#注:
OPTIONS:指定参数
REPOSITORY:表示镜像的仓库源
TAG:镜像的标签
#参数说明:
Options:
-a, --all 显示所有镜像
--digests 显示摘要
-f, --filter filter 根据提供的条件筛选输出
--format string 使用Go模板漂亮地打印图像
--no-trunc 不要截断输出
-q, --quiet 只显示镜像的Id信息
#命令例子:
docker images -a helllo-world:latest
docker images --format "table{{.ID}}\t{{.Tag}}\t{{.Size}}"
REPOSITORY:表示镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小
同一个仓库源可以有多个TAG版本,代表这个仓库源的不同个版本,我们使用REPOSITORY:TAG来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 ubantu,那么docker将默认使用 ubantu 最新版本的镜像
3.2.2、[docker search]
#搜索远程仓库镜像
docker search [OPTIONS] TERM
#注:
OPTIONS:指定参数
TERM:表示镜像名称
#参数说明:
Options:
-f, --filter filter 根据提供的条件筛选输出
--format string 使用Go模板漂亮地打印图像
--limit int 最大搜索结果数(默认为25)
--no-trunc 不要截断输出
#命令例子:
docker search redis
docker search --limit 5 redis
NAME:镜像名称
DESCRIPTION:镜像说明
STARS:点赞数量
OFFICIAL:是否是官方的镜像
AUTOMATED:是否是自动构建的
3.2.3、[docker pull]
#从注册表中提取镜像或存储库
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
#注:
OPTIONS:指定参数
NAME:镜像名称
TAG:镜像标签
DIGEST:镜像摘要
例如拉取下来的镜像摘要:
Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
#参数说明:
Options:
-a, --all-tags 下载存储库中所有带标签的镜像
--disable-content-trust 跳过图像验证(默认为true)
--platform string 如果服务器支持多平台,则设置平台
-q, --quiet 抑制详细输出
#命令例子:
docker pull hello-world:latest
docker pull --all-tags fedora
3.2.4、[docker system df]
#显示docker 镜像、容器、挂在卷磁盘使用情况
docker system df [OPTIONS]
#注:
OPTIONS:指定参数
#参数说明
Options:
--format string 使用Go模板漂亮地打印图像
-v, --verbose 显示空间使用的详细信息
#命令例子
docker system df
docker system df --format "table{{.Type}}\t{{.Size}}"
3.2.5、[docker rmi]
#删除一个或多个图像
docker rmi [OPTIONS] IMAGE [IMAGE...]
#注:
OPTIONS:指定参数
IMAGE:指定镜像
IMAGE...:多个镜像
#参数说明
Options:
-f, --force 强制删除图像
--no-prune 不移除该镜像的过程镜像,默认移除
#命令例子:
docker rmi -f 镜像ID(单个)
docker rmi -f 镜像名1:TAG 镜像名2:TAG(多个)
docker rmi -f ${docker images -qa}(全部)
3.2.6、面试题
- 谈谈
Docker
当中的虚悬镜像是什么?- 仓库名、镜像标签都是的镜像,俗称虚悬镜像
- 推荐删除即可
3.3、容器命令
3.3.1、[docker run]
#新建启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
#注:
OPTIONS:指定参数(有些是一个减号,有些是两个减号)
IMAGE:指定镜像
COMMAND:指定命令
ARG...:指定参数
#常用参数:
--name:"容器新名字"-> 为容器指定一个名称
-d:后台运行容器并返回容器ID,也称为启动守护式容器(后台运行)
-i:以交互模式运行容器,通常与-t同时使用
-t:为容器重新分配一个伪输入终端,通常与-i同时使用也称为启动交互式容器(前台有伪终端,等待交互)
-P:随机端口映射,大写P
-p:指定端口映射,小写p
#命令例子:
docker run -it ubuntu /bin/bash(前台交互式启动)
docker run -it --name=myununtu ubuntu bash(前台交互式启动)\
docker run -d redis:5.0.8(后台交互式启动)
3.3.2、[docker ps]
#列出容器
docker ps [OPTIONS]
#注:
OPTIONS:指定参数
#常用参数
Options:
-a:列出当前所有正在运行的容器+历史上运行过的容器
-l:显示最近创建的容器
-n int:显示最近n个创建的容器
-q:静默模式,只显示容器编号
#命令例子:
docker ps -a
docker ps -l
docker ps -n 1
docker ps -q
docker ps -qa
3.3.3、[docker restart]
#重启容器
docker restart [OPTIONS] CONTAINER [CONTAINER...]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
CONTAINER...:指定多个容器
#常用参数(不经常使用)
-t int:在杀死容器之前等待停止的秒数(默认为10秒)
#命令例子
docker restart 容器ID或容器名
docker restart 容器1 容器2
3.3.4、[docker start]
#启动一个或多个停止的容器
docker start [OPTIONS] CONTAINER [CONTAINER...]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
CONTAINER...:指定多个容器
#常用参数(不经常使用)
Options:
-a: 在前台运行容器并输出日志
-i: 启动并进入交互模式
#命令例子
docker start 容器名
docker start 容器名 容器ID(启动两个容器)
3.3.5、[docker stop]
#停止一个或多个启动的容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
CONTAINER...:指定多个容器
#常用参数(不经常使用)
-t int:在杀死容器之前等待停止的秒数(默认为10秒)
#命令例子
docker stop 容器名
docker stop 容器名 容器ID(停止两个容器)
3.3.6、[docker kill]
#杀死一个或多个正在运行的容器
docker kill [OPTIONS] CONTAINER [CONTAINER...]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
CONTAINER...:指定多个容器
#命令例子
docker kill 容器名
docker kill 容器名 容器ID(杀死两个容器)
3.3.7、[docker rm]
#移除一个或多个容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
CONTAINER...:指定多个容器
#常用参数
-f:强制删除正在运行的容器
-l:删除指定的链接
-v:删除与容器关联的匿名卷
#命令例子
docker rm 容器名(该命令须容器在停止状态下执行)
docker rm -f 容器名
#补充(一次性删除多个容器实例)
docker rm -f ${docker ps -a -q}
docker ps -a -q | xargs docker rm
3.3.8、优雅退出容器
exit
:利用docker run
命令进去容器的话,exit退出,容器停止ctrl + p + q
:利用docker run
命令进去容器,ctrl + p + q退出,容器不会停止
3.3.9、[docker logs]
#获取容器日志
docker logs [OPTIONS] CONTAINER
#注:
OPTIONS:指定参数
CONTAINER:指定容器
#常用参数
--details 显示更多的信息
-f, --follow 跟踪日志输出
--since string 显示自时间戳(例如2013-01-02T13:23:37Z)或相对时间戳(例如42分钟为42m)以后的日志
-n, --tail string 从日志末尾开始显示的行数(默认为“all”)
-t, --timestamps 显示时间戳
--until string 在时间戳(例如2013-01-02T13:23:37Z)或相对时间戳(例如42分钟为42m)之前显示日志
#命令例子
docker logs -f -t --since="2018-02-08" --tail=100 CONTAINER_ID(查看指定时间后的日志,只显示最后100行)
docker logs --since 30m CONTAINER_ID(查看最近30分钟的日志)
docker logs -t --since="2021-08-18T11:46:37" CONTAINER_ID(查看某时间之后的日志)
docker logs -t --since="2021-08-18T11:46:37" --tail=100 CONTAINER_ID(查看某时间之后的100条日志记录)
docker logs -t --since="2021-08-18T11:46:37" --until "2021-08-18T11:47:37" CONTAINER_ID(查询某时间段的日志)
docker logs CONTAINER_ID | grep 'error'(管道符grep过滤日志级别)
docker logs -t CONTAINER_ID | grep 'error' >> logs_error.txt(将日志写入指定文件)
3.3.10、[docker top]
#显示容器正在运行的进程
docker top CONTAINER [ps OPTIONS]
#注:
CONTAINER:指定容器
ps OPTIONS:指定选择
#命令例子
docker top 容器ID
docker top 容器ID | grep PID
3.3.11、[docker inspect]
#查看容器内部细节
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
#注:
OPTIONS:指定参数
NAME:指定容器名称 或 容器ID
NAME|ID...:指定多个容器名称 或 容器ID
#命令例子
docker inspect 容器ID
3.3.12、[docker exec]
#在运行的容器中运行命令
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
COMMAND:指定命令
ARG...:指定参数
#命令例子
docker exec -it 容器ID /bin/bash
docker exec -it 容器ID bash
exec:是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止(推荐使用)
3.3.13、[docker attach]
#将本地标准输入、输出和错误流附加到正在运行的容器
docker attach [OPTIONS] CONTAINER
#注:
OPTIONS:指定参数
CONTAINER:指定容器
#命令例子
docker attach 容器ID
attach:直接进入容器启动命令的终端,不会启动新的进程,用exit退出,会导致容器的停止(不推荐使用)
3.3.14、[docker cp]
#在容器和本地文件系统之间复制文件/文件夹
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
#注:
OPTIONS:指定参数
CONTAINER:SRC_PATH:容器内路径
DEST_PATH:宿主机目标路径
#命令例子
docker cp 容器ID:/usr/local/abc.txt /usr/local/abc.txt
docker cp /usr/local/abc.txt 容器ID:/usr/local/abc.txt
3.3.15、[docker export]
#将容器的文件系统导出为tar归档文件
docker export [OPTIONS] CONTAINER
#注:
OPTIONS:指定参数
CONTAINER:指定容器
#常用参数
Options:
-o string:写入后缀名tar文件
#命令例子
docker export -o ubuntu-`date +%Y%m%d`.tar 容器ID
docker export:就相当于备份了整个容器,日常开发经常使用此命令进行备份
3.3.16、[docker import]
#从压缩包中导入内容以创建文件系统映像
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
#注:
OPTIONS:指定参数
REPOSITORY:指定仓储名称
TAG:指定标签
URL:tar文件路径地址
#命令例子
docker import ubuntu-20221220.tar ubuntu:3.1.0
docker import:将tar压缩文件重新生成一份新的Image镜像,开发经常使用此命令来进行一些tar压缩文件的导入重新生成
3.3.17、[docker tag]
#创建镜像标签
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
#注:
SOURCE_IMAGE:源镜像
TARGET_IMAGE:目标镜像
TAG:标签
#命令例子
docker tag redis:5.0.8 redis:5.0.9
四、Docker镜像概述
4.1、镜像概念
- 镜像可以理解为:是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是 image 镜像文件。
- 只有通过这个镜像文件才能生成Docker容器实例(类似Java new出来一个对象)。
4.2、Docker镜像加载原理
-
Docker
的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS(联合文件系统)。 -
bootfs(boot file system):主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
-
rootfs (root file system):在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
4.3、什么是UnionFS文件系统
- UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。
- 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
- 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
4.4、[docker commit]
#根据容器的更改创建一个新映像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
#注:
OPTIONS:指定参数
CONTAINER:指定容器
REPOSITORY:仓储名称
TAG:镜像标签
#参数说明:
-a,--author string:作者(例如,"John Hannibal Smith <hannibal@a-team.com>")
-m,--message string:提交消息
#命令例子:
docker commit -m="添加Vim重新创建镜像" -a="haohao" 容器ID newImage:1.0.1
4.5、本地镜像发布到阿里云
- 进入到阿里云容器镜像服务中心
- https://cr.console.aliyun.com/cn-hangzhou/instance/repositories
- 创建镜像命名空间
- 提交制作完成的镜像信息
docker commit -m="添加Vim重新创建镜像" -a="haohao" 8b40d699c81a my-centos8:1.0.1
- 创建镜像仓库
- 推送阿里远程仓库
#登录阿里远程仓库
docker login --username=zihaojava registry.cn-hangzhou.aliyuncs.com
#设置镜像标签
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/hao-hao/my-centos8:[镜像版本号]
#推送阿里远程仓库
docker push registry.cn-hangzhou.aliyuncs.com/hao-hao/my-centos8:[镜像版本号]
- 推送成功
4.6、本地镜像发布到私有库
- 下载镜像
registry
docker pull registry
- 运行私有库
registry
docker run -it -d --name=myDocker-registry -p=5000:5000
-v=/usr/local/sbin/myRegistry:/var/lib/registry registry:latest
- 防火墙添加
5000
端口
firewall-cmd --list-all //查看是否暴露过5000端口
firewall-cmd --add-port=5000/tcp --permanent //添加端口
firewall-cmd --reload //重启防火墙
- 浏览器访问私有库地址
http://192.168.47.155:5000/v2/_catalog
- 配置
daemon.json
文件
#insecure-registries:添加此内容
{
"registry-mirrors": ["https://cjbhlr8d.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.47.155:5000"]
}
#重启操作
systemctl daemon-reload && systemctl restart docker
- 为镜像打上私有库的标签
docker tag 25653a2f0a4e 192.168.47.155:5000/my-centos8:1.0.2
#25653a2f0a4e:为镜像ID
- 推送私有库
docker push 192.168.47.155:5000/my-centos8:1.0.2
- 测试是否推送成功
curl --get http://192.168.47.155:5000/v2/_catalog
- 拉取私有库镜像
docker pull 192.168.47.155:5000/my-centos8:1.0.2
五、Docker容器数据卷
5.1、容器数据卷能干嘛
- 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性
- 卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
- 特点:
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
5.2、容器数据卷的使用
docker run -it -d -v=宿主机绝对路径:容器内映射路径 --privileged=true --name=mydata1 镜像名称
#注:即使容器突然因为某些原因挂掉,只要容器启动就会重新挂载
#使用以下命令可以查看容器挂载数据卷情况
docker inspect 容器ID
–privileged=true:防止Docker容器内出现cannot open directory:Permission denied权限访问问题
5.3、容器数据卷之间的继承
docker run -it -d --volumes-form 父类 --privileged=true --name=mydata1 镜像名称
–volumes-form:此启动的容器将继承实现父类的数据卷信息,类似于Java当中的extends操作
5.4、容器数据卷挂载读写
5.4.1、容器内可读写
docker run -it -d -v=宿主机绝对路径:容器内映射路径:rw --privileged=true --name=mydata1 镜像名称
5.4.2、容器内只读
docker run -it -d -v=宿主机绝对路径:容器内映射路径:ro --privileged=true --name=mydata1 镜像名称
六、Dockerfile文件概述
6.1、什么是Dockerfile文件
Dockerfile
是用来构建Docker
镜像的构建文件,是由一系列命令和参数构成的脚本。- 如何构建文件?
- 编写一个
Dockerfile
文件 docker build
命令打包构建成一个新的镜像docker run
命令创建一个容器
- 编写一个
Dockerfile
、images
、Containers
三者关系-
从应用软件的角度来看,
Dockerfile
、images
、Containers
分别代表着应用软件的不同阶段。Dockerfile
:像是应用软件的材料images
:镜像就像是软件的交付品Containers
:容器则可以认为是软件的运行状态
-
Dockerfile
面向开发,Docker
镜像称为交付标准,从而Docker
容器则涉及部署与运维,三者缺一不可,合力充当Docker
体系的基石。
-
Dockerfile
:需要定义一个Dockerfile
,Dockerfile
定义了进程需要的一切东西。Dockerfile
涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;Docker镜像
:在用Dockerfile
定义一个文件之后,docker build
时会产生一个Docker
镜像,当运行Docker
镜像时,会真正开始提供服务;Docker容器
:说白了可以理解为就是最后的提供服务者;
6.2、Dockerfile保留字指令
6.2.1、FROM
#FROM:保留字指定可以理解为新镜像来自哪儿或者说基于那个镜像(只能有一个FROM保留字)
#保留字例子
FROM java:8
FROM centos
FROM redis
6.2.2、MAINTAINER
#MAINTAINER:该保留字是为了定义编写Dockerfile的作者的信息(只能有一个MAINTAINER保留字)
#保留字例子
MAINTAINER ChenZiHao
MAINTAINER 27182122090@qq.com
6.2.3、RUN
#RUN:容器构建时需要运行的命令,相当于一个系统命令(可以指定该保留字有多个)
#保留字例子
RUN yum update
RUN yum -y install vim
RUN yum -y install net-tools
RUN bash -c 'touch /app.jar'
6.2.4、EXPOSE
#EXPOSE:通知Docker容器在运行时监听指定的网络端口(该保留字可以指定多个)
#保留字例子
EXPOSE 端口号/协议
EXPOSE 8000/tcp
EXPOSE 8100/udp
6.2.5、WORKDIR
#WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点(该保留字只能有一个)
#保留字例子
WORKDIR /usr/local
#上述/usr/local那么执行该docker run 容器ID /bin/bash 会直接进入到/usr/local目录下
6.2.6、ENV
#ENV:用来在构建镜像过程中设置环境变量(该保留字可以有多个)
#保留字例子
ENV MYPATH /usr/local
#这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
#也可以在其它指令中直接使用这些环境变量,
#比如如下:
ENV $MYPATH/java/bin
6.2.7、ADD
#ADD:将宿主机目录下的文件拷贝进镜像
#并且ADD命令会自动处理URL和解压tar压缩包(该保留字通常情况下只有一个,但也可以有多个)
#保留字例子
ADD target/*.jar /app.jar
# 通配符,test 不存在自动创建
ADD test*.txt /mydir/test/
# 特殊字符串
ADD add[[]0].txt /mydir/
6.2.8、COPY
#COPY:类似ADD该保留字拷贝文件和目录到镜像中(该保留字可以有多个)
#将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
#保留字例子
COPY src dest
COPY ["src", "dest"]
6.2.9、VOLUME
#VOLUME:容器数据卷,用于数据保存和持久化工作(该保留字只能有一个)
#保留字例子
VOLUME /tmp
6.2.10、CMD
#CMD:指定一个容器启动时要运行的命令(该保留字可以有多个)
#保留字例子
FROM busybox
CMD ["/bin/echo", "this is a echo test"]
#保留字分析
#如果此时运行此容器会输出:this is a echo test 类似于 docker run 镜像ID /bin/echo this is a echo test
#如果你再运行此容器例如这样:docker run 镜像ID /bin/echo hello
#那么此时就会输出 hello,则会覆盖掉上一个CMD参数
#注:
#Dockerfile中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
6.2.11、ENTRYPOINT
#ENTRYPOINT:指定一个容器启动时要运行的命令(该保留字可以有多个)
#保留字例子
ENTRYPOINT ["java","-jar","-Xms128m","-Xmx300m","/app.jar","--spring.profiles.active=prod"]
#注:
#ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数
6.3、构建一个Dockerfile文件
6.3.1、下载JDK环境
https://mirrors.yangxingzhen.com/jdk/
6.3.2、编写Dockerfile文件
#基于centos7镜像没有直接拉取
FROM centos:centos7
#作者信息
MAINTAINER ChenZiHao
#指定工作目录
WORKDIR /usr/local
#安装Centos7环境
RUN yum -y install vim
RUN yum -y install net-tools
#安装创建Java环境
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#上传Java压缩包
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java
#配置Java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
#配置容器暴露端口
EXPOSE 80
#配置CMD参数
CMD echo "success ----- ok "
CMD /bin/bash
6.3.3、[docker build]
#从Dockerfile文件构建出一个映像
docker build [OPTIONS] .
#注:
OPTIONS:指定参数(有些是一个减号,有些是两个减号)
后面还有一个点 .
#常用参数:
-f, --file string:Dockerfile的名称(默认为'PATH/Dockerfile')
-t, --tag list:名称和'Name:tag'格式的标签(可选)
#命令例子:
docker build -f Dockerfile -t mycentos7:1.0.2 .
6.4、关于虚悬镜像的操作
6.4.1、虚悬镜像的查看
docker images ls -f dangling=true
6.4.2、虚悬镜像的删除
docker images prune
七、Docker网络概述
7.1、能干嘛
- 容器间的互联和通信以及端口映射;
- 容器IP变动时候可以通过服务名直接网络通信而不受到影响;
7.2、网络模式
网络模式 | 简介 |
---|---|
bridge | 为每一个容器分配、设置IP等,并将容器连接到一个docker0 |
虚拟网桥,默认为该模式; | |
host | 容器将不会虚拟出自己的网卡,配置自己的IP |
等,而是使用宿主机的 IP 和端口; | |
none | 容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair和网桥连接,IP等; |
container | 新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP,端口范围等; |
7.2.1、总体介绍
- bridge模式
- 使用
--network bridge
指定,默认使用docker0
;
- 使用
- host模式
- 使用
--network host
指定;
- 使用
- none模式
- 使用
--network none
指定;
- 使用
- container模式
- 使用
--network container:NAME
或者容器ID指定;
- 使用
7.3、[docker network]
#管理网络
docker network COMMAND
#注:
COMMAND:指定命令参数
#常用参数:
connect 将容器连接到网络
create 创建一个网络模式
disconnect 断开容器与网络的连接
inspect 显示一个或多个网络的详细信息
ls 列出所有的网络模式
prune 删除所有未使用的网络
rm 删除一个或多个网络模式
#命令例子
docker network connect --ip 10.10.36.122 multi-host-network 容器ID(指定容器的IP地址)
docker network create my-host
docker network ls
docker network inspect 网络名称
docker network rm 网络名称
docker network prune
7.4、自定义网络模式
- 分别启动两个容器实例,以
Tomcat8
为例子
#启动第一个tomcat8实例
docker run -it -d -p=8081:8080 --name=my-tomcat1 tomcat:8.5
#启动第二个tomcat8实例
docker run -it -d -p=8082:8080 --name=my-tomcat2 tomcat:8.5
- 查看两个容器实例的网络IP地址
#查看第一个tomcat8实例
docker inspect my-tomcat1 | tail -n 20
#查看第二个tomcat8实例
docker inspect my-tomcat2 | tail -n 20
- 分别进入两个容器查看默认网络模式
bridge
,利用Ping
命令查询是否容器互通
#进入第一个tomcat8实例
docker exec -it my-tomcat1 /bin/bash
#进入第二个tomcat8实例
docker exec -it my-tomcat2 /bin/bash
- 上述使用IP地址,利用
Ping
命令是可以Ping
通,但如果Ping
容器名称是否能Ping
通那?
在实际容器开发过程当中不推荐容器与容器之间利用IP地址的方式,做交互操作,理应当使用容器名进行容器与容器之间的交互
- 解决办法:
- 自定义一个网络模式
docker network create tomcat-host
- 启动两个容器并且指定网络模式即可
#启动第一个tomcat8容器指定网络模式
docker run -it -d --network=tomcat-host -p=8081:8080 --name=my-tomcat1 tomcat:8.5
#启动第二个tomcat8容器指定网络模式
docker run -it -d --network=tomcat-host -p=8082:8080 --name=my-tomcat2 tomcat:8.5
- 利用
Ping
命令加上容器名查看是否根据容器名相互交互
八、Docker容器编排
8.1、Compose是什么
Compose
是Docker
公司推出的一个工具软件,可以管理多个Docker
容器组成一个应用,你需要定义一个YAML格式的配置文件;docker-compose.yaml
,写好多个容器之间的调用关系,然后,只要一个命令,就能同时或关闭这些容器;
8.2、Compose能干嘛
Docker
建议我们每一个容器中只运行一个服务,因为Docker
容器本身资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临一个问题?- 如果我们需要同时部署好多个服务,难道要每个服务单独写
Dockerfile
然后在构建镜像、构建容器,那么这样就会大大的降低开发以及编写人员的效率,所以Docker
官方提供了给我们一个docker-compose
多服务部署的工具; - 例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要一些数据库和一些中间件还有一些注册中心、负载均衡等等;
Compose
允许用户通过一个单独的docker-compose.yaml
模板文件(YAML格式)来定义一组相关联的应用容器为一个项目;- 可以很容器地用一个配置文件定义一个多容器的应用,然后一个命令安装这个应用的所需的一些的配置信息,完成构建,其实这个
docker-compose
就解决了容器与容器之间如何管理编排的问题;
- 如果我们需要同时部署好多个服务,难道要每个服务单独写
8.3、Compose下载
- 查看本机上的docker版本
docker --version
#Docker version 20.10.22, build 3a2c30b
-
docker-compose
对应docker
版本
| 撰写档案格式 | Docker Engine版本 |
| — | — |
| 撰写规格 | 19.03.0+ |
| 3.8 | 19.03.0+ |
| 3.7 | 18.06.0+ |
| 3.6 | 18.02.0+ |
| 3.5 | 17.12.0+ |
| 3.4 | 17.09.0+ |
| 3.3 | 17.06.0+ |
| 3.2 | 17.04.0+ |
| 3.1 | 1.13.1+ |
| 3.0 | 1.13.0+ |
| 2.4 | 17.12.0+ |
| 2.3 | 17.06.0+ |
| 2.2 | 1.13.0+ |
| 2.1 | 1.12.0+ |
| 2.0 | 1.10.0+ |
| 1.0 | 1.9.1。+ | -
下载
docker-compose
二进制文件
#下载二进制文件
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#赋予权限
sudo chmod +x /usr/local/bin/docker-compose
#查看版本
docker-compose --version
- 下载安装成功
8.4、Compose使用步骤
- 编写
Dockerfile
定义各个微服务应用并构建出对应的镜像文件; - 使用
docker-compose.yaml
定义一个完整业务单元,安排好整体应用中的各个容器服务; - 最后,执行
docker-compose up
命令来启动并运行整个应用程序,完成一键部署上线;
8.5、Compose常用命令
#查看帮助
docker-compose -h
#启动所有docker-compose服务
docker-compose up
#后台启动所有docker-compose服务
docker-compose up -d
#停止并删除容器、网络、卷、镜像
docker-compose down
#进入容器实例内部 docker-compose exec docker-compose.yml文件当中写的服务id /bin/bash
docker-compose exec yml文件里面的服务Id
#展示当前docker-compose编排过的运行的所有容器
docker-compose ps
#展示当前docker-compose编排过的容器进程
docker-compose top
#查看容器输出日志
docker-compose logs yml文件里面的服务Id
#检查配置
docker-compose config
#检查配置,有问题才有输出
docker-compose config -q
#重启服务
docker-compose restart
#启动服务
docker-compose start
#停止服务
docker-compose stop
8.6、编写一个Compose文件
version : '3.9'
services:
ruoyi-nacos:
container_name: ruoyi-nacos
image: nacos/nacos-server
build:
context: ./nacos
environment:
- MODE=standalone
volumes:
- ./nacos/logs/:/home/nacos/logs
- ./nacos/conf/application.properties:/home/nacos/conf/application.properties
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
depends_on:
- ruoyi-mysql
ruoyi-mysql:
container_name: ruoyi-mysql
image: mysql:5.7
build:
context: ./mysql
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'ry-cloud'
MYSQL_ROOT_PASSWORD: password
ruoyi-redis:
container_name: ruoyi-redis
image: redis
build:
context: ./redis
ports:
- "6379:6379"
volumes:
- ./redis/conf/redis.conf:/home/ruoyi/redis/redis.conf
- ./redis/data:/data
command: redis-server /home/ruoyi/redis/redis.conf
ruoyi-nginx:
container_name: ruoyi-nginx
image: nginx
build:
context: ./nginx
ports:
- "80:80"
volumes:
- ./nginx/html/dist:/home/ruoyi/projects/ruoyi-ui
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
- ruoyi-gateway
links:
- ruoyi-gateway
ruoyi-gateway:
container_name: ruoyi-gateway
build:
context: ./ruoyi/gateway
dockerfile: dockerfile
ports:
- "8080:8080"
depends_on:
- ruoyi-redis
links:
- ruoyi-redis
ruoyi-auth:
container_name: ruoyi-auth
build:
context: ./ruoyi/auth
dockerfile: dockerfile
ports:
- "9200:9200"
depends_on:
- ruoyi-redis
links:
- ruoyi-redis
ruoyi-modules-system:
container_name: ruoyi-modules-system
build:
context: ./ruoyi/modules/system
dockerfile: dockerfile
ports:
- "9201:9201"
depends_on:
- ruoyi-redis
- ruoyi-mysql
links:
- ruoyi-redis
- ruoyi-mysql
ruoyi-modules-gen:
container_name: ruoyi-modules-gen
build:
context: ./ruoyi/modules/gen
dockerfile: dockerfile
ports:
- "9202:9202"
depends_on:
- ruoyi-mysql
links:
- ruoyi-mysql
ruoyi-modules-job:
container_name: ruoyi-modules-job
build:
context: ./ruoyi/modules/job
dockerfile: dockerfile
ports:
- "9203:9203"
depends_on:
- ruoyi-mysql
links:
- ruoyi-mysql
ruoyi-modules-file:
container_name: ruoyi-modules-file
build:
context: ./ruoyi/modules/file
dockerfile: dockerfile
ports:
- "9300:9300"
volumes:
- ./ruoyi/uploadPath:/home/ruoyi/uploadPath
ruoyi-visual-monitor:
container_name: ruoyi-visual-monitor
build:
context: ./ruoyi/visual/monitor
dockerfile: dockerfile
ports:
- "9100:9100"
九、Docker第三方控件
9.1、可视化工具Portainer
9.1.1、什么是Portainer
Portainer
是Docker
的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。
9.1.2、Portainer有什么好处
- 为了方便可视化管理
Docker
集群、容器、镜像、内存…。 - 如果说以后的容器服务实例渐渐的多了起来的话,不可能再使用
docker system df
该命令进行查看以及监控,所以说还得有个dashBoard
进行统一的管理。 - 目前
Docker
集群的Swarm
逐渐被云原生K8S
取代。 - 使用
Portainer
轻量级可视化工具之后,就很少使用Docker
原生命令。
9.1.3、下载安装Portainer
- 拉取
Portainer
镜像
docker pull portainer/portainer
- 创建
Portainer
容器
docker run -it -d -p=9000:9000 -p=9443:9443 -p=8000:8000 --name=my-Portainer
-v /usr/local/sbin/myPortainer/data:/data -v /var/run/docker.sock:/var/run/docker.sock
--restart=always portainer/portainer
- 防护墙暴露端口
#防火墙添加9000端口
firewall-cmd --add-port=9000/tcp --permanent
#重启防火墙
firewall-cmd --reload
#查看防护墙暴露端口
firewall-cmd --list-all
- 本地
http://IP地址:9000
访问Portainer
可视化工具
The password must be at least 8 characters long:密码长度至少为8个字符
- 将
Portainer
连接到要管理的Docker
环境,选择本地localDocker
9.1.4、Portainer面板介绍
- Stacks:本地情况下有多少个容器编排实例
- Images:本地情况下有多少个镜像
- Networks:本地情况下创建了多少个网络环境
- Containers:本地情况下创建了多少个容器实例包括未启动的
- Volumes:容器实例挂载了多少个容器数据卷
9.2、监控系统CIG
9.2.1、容器监控存在的问题
- 通过
docker stats
命令可以很方便的看到当前宿主机上所有的容器的CPU,内存以及网络流量等数据,一般小公司够用了。。。 docker stats
统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储,没有健康指标过线预警等功能。
9.2.2、什么是CIG
- 简单一句话概括是由三个第三方组件结合起来的三件客
- CAdvisor:监控收集
- InfluxDB:存储数据
- Granfana:展示图表
9.2.3、什么是CAdvisor
CAdvisor
是一个容器资源监控工具,包括容器的内存,CPU、网络I/O、磁盘I/O等监控,同时提供了一个Web界面用于查看容器的实时运行状态,CAdvisor
默认存储2分钟的数据,只是针对单物理机,不过,CAdvisor
提供了很多数据集成接口,支持InfluxDB
,Redis
,kafka
,ElasticSearch
等集成,可以加上对应配置将监控数据发往这些数据库存储起来。CAdvisor
功能主要有两点:- 展示Host和容器两个层次的监控数据。
- 展示历史变化数据。
9.2.4、什么是Granfana
Granfana
是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括InfluxDB
,ElasticSearch
,Mysql
,OpenTSDB
,Graphite
等)和丰富的插件以及模板功能,支持图表权限控制和报警。Granfana
主要特性:- 灵活丰富的图形化选项。
- 可以混合多种风格。
- 支持白天和夜间模式。
- 多个数据源。
9.2.5、什么是InfluxDB
InfluxDB
是用Go
语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。CAdvisor
默认只在本机保存最近2分钟的数据,为了持久化存储数据和统一收集展示监控数据,需要将数据库存储到InfluxDB
中,InfluxDB
是一个时序数据库,专门用于存储时序相关数据,很适合存储CAdvisor
的数据,而且,CAdvisor
本身已经提供了InfluxDB
的集成方法,启动容器时指定配置即可。InfluxDB
主要功能:- 基于时间序列,支持与时间有关的相关函数(如最大、最小、求和等)。
- 可度量性:你可以实时对大量数据进行计算。
- 基于事件:它支持任意的事件数据。
9.2.6、容器编排搭建CIG三剑客
- 编写
Yaml
文件创建CIG
version: '3.9'
volumes:
grafana_data:
services:
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor
ports:
- "8083:8083"
- "8086:8086"
volumes:
- ./data/influxdb:/data
cadvisor:
image: google/cadvisor
links:
- influxdb
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxdb:8086
restart: always
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
user: "104"
image: grafana/grafana
user: "104"
restart: always
links:
- influxdb
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxdb
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
- 防火墙分别开放CIG端口
#防火墙添加8080端口(Cadvisor)
firewall-cmd --add-port=8080/tcp --permanent
#防火墙添加3000端口(Grafana)
firewall-cmd --add-port=3000/tcp --permanent
#防火墙添加8083端口(influxdb)
firewall-cmd --add-port=8083/tcp --permanent
#防火墙添加8086容器映射内部端口(influxdb)
firewall-cmd --add-port=8086/tcp --permanent
#重启防火墙
firewall-cmd --reload
#查看防护墙暴露端口
firewall-cmd --list-all
- 访问
http://本地IP地址:8080
端口,查看Cadvisor
组件,初次访问可能有点慢
- 访问
http://本地IP地址:8083
端口,查看InfluxDB
组件- 在启动
InfluxDB
的时候,配置文件配置过环境变量所以会有一个数据库 environment: - PRE_CREATE_DB=cadvisor
- 随后配置一个账号密码(也可以不用配置)
- 在启动
- 访问
http://本地IP地址:3000
端口,查看Granfana
组件- 首次登录会提示修改密码。
- 初次登录账号密码均为:admin。
9.2.7、配置Granfana数据源
- 添加
InfluxDB
数据源信息
- 搜索
InfluxDB
数据库作为数据源信息
Granfana
配置InfluxDB
数据库信息,请提前确认是否容器与容器之间存在Ping不通情况
Granfana
配置pannel
监控
- 根据自己的喜好选择对应的数据报表
- 输入
pannel
标题信息
- 此时的数据报表数据不是真实的因为还没有配置数据库,点击Edit进行修改
- 进行
InfluxDB
数据源信息配置
- 查看
Portainer
容器内存使用情况
- 点击右上角保存即可看出容器的内存使用情况