掘金 后端 ( ) • 2024-03-20 13:36

温馨提示:所有文章中所提及的Docker相关的案例的安装包和工具,都可以在我的网盘中直接下载并跟着实操:

链接:https://pan.baidu.com/s/1pgboR8O5DjZoZK9f1NvK9g

提取码:30in

1. Docker简介

image-20220823094713541.png

1.1 虚拟化技术发展概述

在虚拟化技术出现之前,如果想要搭建一台Java服务器大致流程如下:

  • 购买一台硬件服务器
  • 在硬件服务器上安装配置Linux操作系统
  • 在操作系统之上配置应用运行环境JDK、Tomcat、MySQL等
  • 部署并运行应用

这种方式的缺点:

  • 部署应用非常慢
  • 应用迁移麻烦,要将应用迁移到一台新机器,又需要重来一遍

所以,随着技术发展,改进了这一问题,出现了虚拟化技术,它是一种计算机资源管理技术,它将计算机的各种硬件资源,比如硬盘、网络、CPU、内存等硬件资源,予以抽象和转换从而呈现出一套新的硬件资源环境,在这一套新的硬件环境下可以安装我们的操作系统,部署我们的应用运行环境等,它打破了计算机硬件资源不可切割的问题,使我们可以更加充分更加合理地利用计算机硬件资源,虚拟化技术又分为:硬件级虚拟化操作系统级虚拟化

1.2 硬件级虚拟化

硬件级虚拟化是运行在硬件之上的虚拟化技术,它的核心技术是Hypervisor ,Hypervisor是一种运行在基础物理服务器硬件之上的软件层,可以虚拟化硬件资源,例如CPU、硬盘、内存、网络资源等,然后我们可以通过在虚拟化出来的资源之上安装操作系统,这也就是所谓的虚拟机,像VMWare, VirtualBox等都是使用该技术,通过Hypervisor层,我们可以创建不同的虚拟机,并且每个虚拟机都是隔离独立的,这样一来,我们就可以在一台硬件服务器和操作系统之上虚拟化出多个虚拟服务器,用来部署我们的应用

硬件级虚拟化技术的优点:

  • 一台物理服务器可以虚拟化出多个虚拟的操作系统,让计算机资源得以充分利用

硬件级虚拟化技术的缺点:

  • 每创建一个虚拟机的时候,都会创建一个操作系统,操作系统本身就会占用很多资源,这样无疑大大的增加了硬件资源的消耗,当安装的虚拟机越多,硬件资源消耗就越多
  • 环境兼容性问题,多个虚拟机之间会有操作系统环境的差异化,例如部分虚拟机正常部署运行,部分虚拟机则有可能出现异常情况
  • 部署不便捷,随着我们的软件系统越来越庞大,需要部署的服务会越来越多,每次进行软件升级时,每台虚拟机服务器都需要进行重新部署,工作量巨大,而且出错情况增加

1.3 操作系统级虚拟化

基于硬件级虚拟化技术的缺点和不足,随着技术的发展,发展出了另一种虚拟化技术,即操作系统级虚拟化技术。操作系统级虚拟化是运行在操作系统之上的虚拟化技术,它模拟的是运行在一个操作系统上的多个不同进程,并将其封装在一个密闭的容器里面,该技术也称为容器化技术,在容器化技术领域,Docker是目前最流行的一种实现

1.4 Docker概述

  • Docker发布于2013年,基于LXC技术,LXC是Linux平台上的容器化技术实现。LXC是Linux Container的简写,它是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源,它与宿主机使用同一个内核,性能损耗小,这种技术是Linux提供的,但是直到Docker出世,该技术才被发挥出来,官方网站:https://www.docker.com

  • Docker是一个开源的应用容器引擎,基于 Go 语言并遵从Apache2.0协议开源,项目代码托管在GitHub上进行维护 :https://github.com/docker/docker-ce

  • Docker技术让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,打包好的容器可以发布到任何流行的 Linux服务器上运行,这样就可以解决开发环境与运维环境不一致的问题了,所以容器技术解决了开发和运维之间的矛盾,让开发专注于开发,运维专注于运维,不要被环境问题所打扰

  • Docker彻底释放了虚拟化的威力,极大降低了计算机资源供应的成本,Docker重新定义了程序开发测试、交付和部署过程,Docker 提出了“构建一次,到处运行”的理念,让应用的开发、测试、部署和分发都变得前所未有的高效和轻松

  • Docker是一种轻量级的操作系统虚拟化解决方案,Docker 的基础是 Linux 容器(LXC)技术,在LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单,其资源的开销是极低的

  • Docker 自开源后受到广泛的关注,Docker最早是基于Ubuntu开发的,但后续CentOS、Debian、Fedora等主流的Linux操作系统都支持Docker

  • Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了

  • 简单地说,Docker是对软件和其依赖环境的标准化打包(类似于一个集装箱),应用之间相互隔离,共享一个操作系统内核(解决了资源浪费的问题),可以运行在很多主流操作系统上。但是需要注意的是Docker本身不是容器,Docker只是管理容器的引擎

1.5 容器和虚拟机的区别

容器是将代码和环境的关系打包在一起的一个集合,而虚拟机是在物理层面上,分出来的一个操作系统。多个容器可以运行在同一台物理服务器上,并共享一个操作系统的内核资源。多个虚拟机也可以运行在同一台机器上,但每个虚拟机都需要一个完整的操作系统,其对比可见下面:

特性 容器 虚拟机 启动 秒级 分钟级 硬盘空间 一般为几十MB 一般为10GB 性能 接近原生 弱于原生 系统支持量 单机支持上千个容器 一般几十个 操作系统 与宿主机共享OS 宿主机OS上运行虚拟机OS

1.6 为什么要使用Docker

作为一种新兴的虚拟化技术,Docker跟传统的硬件虚拟化方式相比具有众多的优势:

  • Docker容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多
  • Docker对系统资源的利用率很高,一台主机上可以同时运行数千个Docker容器
  • 容器除了运行其中的应用外,基本不消耗额外的系统资源,使得应用的性能很高,传统虚拟机方式运行10个完全不同的应用可能我们会起10个虚拟机来部署,而Docker 只需要启动10个隔离的应用即可
  • Docker可以更快速的交付和部署,大量地节约开发、测试、部署的时间,对开发和运维人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行
  • 更高效的虚拟化,Docker容器的运行不需要额外的Hypervisor支持,它是内核级的虚拟化,因此可以实现更高的性能和效率
  • 更轻松的迁移和扩展,Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等,这种兼容性可以让用户轻松地把一个应用程序从一个平台直接迁移到另一个平台

2. Docker安装

  • Docker从2013年3月20日发布Docker 0.1,到现在已经发布了多个版本,从2017年3月开始Docker在原来的基础上分为两个分支版本: Docker CEDocker EEDocker CE即社区免费版,可永久免费使用,Docker EE即企业版,功能更全,更强调安全,但需付费使用
  • Docker官方网站:https://www.docker.com/
  • 中文社区:https://www.docker.org.cn/index.html
  • 首先我们知道Docker并不是容器,它是一个管理容器的引擎,我们采用的Linux版本是CentOS7,学习Docker也更推荐在Linux环境下使用,目前Docker支持CentOS7及以后的版本,CentOS版安装网站:https://docs.docker.com/engine/install/centos/

2.1 在线安装

  1. Docker要求CentOS系统的内核版本高于3.10 ,验证你的CentOS版本是否支持 Docker

    uname -r
    
  2. Docker可以使用yum直接安装,首先在root账号下确保yum工具更新到最新

    yum update
    
  3. 安装前可以查看一下系统是否已经安装了Docker,如果安装过旧版本的话

    yum list installed | grep docker
    ​
    #如果已经安装了Dokcer则执行卸载
    yum -y remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
    
  4. 设置Dokcer的存储库,在首次安装Docker之前,需要设置Docker的存储库,之后我们就可以从存储库中安装和更新Docker

    #安装yum-utils工具,它提供了yum-config-manager工具
    yum -y install yum-utils
    ​
    #设置存储库,官方推荐的存储库
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    ​
    #官方推荐的存储库,可能会有网络延迟等问题,导致下载速度较慢或超时,所以我们可以改用阿里云镜像
    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  5. 更新yum缓存,设置完毕yum存储库后,我们需要对其缓存数据进行更新

    yum makecache fast
    
  6. 安装Docker

    yum -y install docker-ce docker-ce-cli containerd.io
    
  7. 查看Docker是否安装成功

    docker -v
    
  8. Docker系统服务相关命令

    #启动Docker服务
    systemctl start docker
    ​
    #停止Docker服务
    systemctl stop docker
    ​
    #重启Docker服务
    systemctl restart docker
    ​
    #设置开机启动
    systemctl enable docker
    ​
    #查看Dokcer运行状态
    systemctl status docker
    ​
    #查看Docker进程
    ps -ef | grep docker
    ​
    #查看Docker系统信息
    docker info
    ​
    #查看Docker所有帮助信息
    docker --help
    ​
    #查看某个commond命令的帮助信息
    docker commond --help
    

2.2 离线安装

  1. 下载 Docker 离线包

    #在这里可以选择自己需要的版本进行下载,我们这里选择x86_64中docker-20.10.18.tgz版本下载即可
    https://download.docker.com/linux/static/stable/
    

    image-20221008113341589.png

    image-20221008113404762.png

  2. 下载离线安装工具

    #在github中下载离线安装工具
    https://github.com/Jrohy/docker-install/
    
    image-20221008112144661.png
  3. 将Docker安装包和离线安装工具,上传至CentOS7中/soft目录下并解压

    #在/soft目录中解压离线安装工具
    unzip docker-install-master.zip
    ​
    #将docker-20.10.18.tgz移动至解压后的离线工具docker-install-master目录中
    mv docker-20.10.18.tgz docker-install-master
    ​
    #解压最后一定要保证在/soft/docker-install-master目录下包含以下三个文件
    docker-20.10.18.tgz
    install.sh
    docker.bash
    
  4. 卸载之前在线安装的Docker

    yum list installed | grep docker
    ​
    #注意这里的卸载命令和之前在线安装卸载旧版本的命令是不一样的,新版本的docker应该使用以下方式卸载
    yum -y remove docker-ce.x86_64 \
                  docker-ce-cli.x86_64 \
                  docker-ce-rootless-extras.x86_64 \
                  docker-scan-plugin.x86_64 \
                  containerd.io.x86_64     
    
  5. 执行安装

    #进入docker-install-master目录
    cd /soft/docker-install-master
    ​
    #为install.sh脚本添加执行权限
    chmod +x install.sh
    或
    chmod 655 install.sh
    ​
    #执行脚本进行安装,其中-f指定docker的安装包名字
    ./install.sh -f docker-20.10.18.tgz
    ​
    #执行完上述安装命令后出现以下信息,则证明脚本安装完成
    Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
    docker 20.10.18 install success!
    
  6. 查看Docker是否安装成功

    docker -v
    
  7. Docker系统服务相关命令

    #启动Docker服务
    systemctl start docker
    ​
    #停止Docker服务
    systemctl stop docker
    ​
    #重启Docker服务
    systemctl restart docker
    ​
    #设置开机启动
    systemctl enable docker
    ​
    #查看Dokcer运行状态
    systemctl status docker
    ​
    #查看Docker进程
    ps -ef | grep docker
    ​
    #查看Docker系统信息
    docker info
    ​
    #查看Docker所有帮助信息
    docker --help
    ​
    #查看某个commond命令的帮助信息
    docker commond --help
    

3. Dokcer核心组成

Docker使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。镜像与容器的关系类似于面向对象编程中的类与对象的关系:

Docker 面向对象 镜像 类 容器 对象

3.1 核心三要素

  • Docker 包括三个核心要素镜像(Image)容器(Container)仓库(Repository)
  • 理解了这三个概念,就理解了Docker的整个生命周期,Docker 的运行离不开以上核心几个组件的支持,Docker的成功也是拜这几个组件所赐,不能错误地理解为Docker就是容器,实际上Docker不是容器,而是管理容器的引擎

3.2 镜像概念

  • Docker镜像就是一个只读的模板,可以用来创建Docker容器,例如:一个镜像可以包含一个完整的Centos操作系统环境,里面仅安装了MySql或用户需要的其它应用程序。
  • Docker提供了一个非常简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
  • 镜像就好比是我们Java中的类,类是对象的模板

3.3 容器概念

  • 容器是从镜像创建的运行实例,它可以被启动、停止、删除,每个容器都是相互隔离的、能够保证安全,可以把容器看做一个简易版的Linux环境,包括root用户权限、进程空间、用户空间和网络空间和运行在其中的应用程序。
  • Docker利用容器来运行应用,镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
  • 容器就好比我们Java中的对象,我们可以通过类,来创建多个对象的实例

3.4 仓库概念

  • 仓库是集中存放镜像文件的场所,很多时候会把仓库(Repository)仓库注册服务器(Registry) 看做同一事物,并不严格区分。但实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)
  • 仓库分为公开仓库(Public)私有仓库(Private) 两种形式。最大的公开仓库是 Docker Hubhttps://hub.docker.com/,存放了数量庞大的镜像供用户下载,当然,用户也可以在本地网络内创建一个私有仓库
  • 当用户创建了自己的镜像之后就可以将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上拉取下来即可
  • Docker 仓库的概念跟Git类似,注册服务器也类似于GitHub、Gitee这样的托管服务

4. Docker运行机制

我们知道Docker并不是容器,Docker只是一个管理容器的引擎,Docker的底层运行原理大致是:

  1. 安装并启动Docker服务
  2. 下载镜像(如果本地仓库已经有了该镜像,则跳过下载步骤)
  3. 启动该镜像得到一个容器
  4. 容器里运行着我们想要的程序

如下图所示:

image-20221008143213863.png

英文名称 中文名称 描述 Docker daemon Docker守护进程 Docker守护进程监听Docker命令请求,并管理Docker对象,如镜像、容器、网络和卷 Client Docker客户端 Docker客户端是用户与Docker交互的主要方式,当我们使用例如docker run这样的命令时,客户端会将这些命令发送给Docker守护进程来执行这些命令 Registry Docker注册表 Docker注册表是用于存储Docker镜像的地方,其中Docker Hub是Docker为我们提供的公共注册中心,默认情况下,Docker的镜像在Docker Hub中寻找并下载。我们也可以搭建自己的注册表。当使用docker pull或docker run命令时,将从配置的注册表中提取所需的镜像,使用docker push命令时,镜像会被推送到配置的注册表中 Images Docker镜像 Docker镜像就是一个只读的模板,可以用来创建Docker容器,例如:一个镜像可以包含一个完整的 Centos 操作系统环境,里面仅安装了 MySql或用户需要的其它应用程序,Docker提供了一个非常简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用 Containers Docker容器 容器是从镜像创建的运行实例,它可以被启动、停止、删除,每个容器都是相互隔离的、能够保证安全,可以把容器看做一个简易版的 Linux环境,包括root用户权限、进程空间、用户空间和网络空间和运行在其中的应用程序,Docker利用容器来运行应用,镜像是只读的,容器在启动的时候创建一层可写层作为最上层

4.1 HelloWorld实现

  1. 将Docker服务启动

  2. 运行官方提供的HelloWorld容器

    docker run hello-world
    
  3. 出现以下内容则证明容器创建成功

    image-20221010095840045.png

4.2 Docker究竟干了什么

在上述案例中,我们执行完docker run hello-world就能得到一个测试容器,并打印输出对应的内容,那么这个API命令究竟干了什么呢?我们参考下面这个图来说明这个过程

image-20221010102909961.png

5. Docker镜像实践

  • 镜像是容器运行容器的前提,是Docker的核心之一
  • 镜像的获取有两种方式,一个是下载别人在镜像仓库中提供好的镜像,一种是自己导入或自己制作镜像

5.1 配置阿里云镜像加速器

Docker运行一个容器前需要本地有对应的镜像,如果镜像不存在本地,Docker会从镜像仓库中下载

默认是从Docker Hub公共注册表服务器中下载:https://hub.docker.com

但是这个仓库的下载速度实在是太慢了,我们需要更改一下阿里云加速器来实现提速

#进入阿里云容器镜像服务页面,使用你的淘宝账号密码登录
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
​
#在镜像加速器页面中,找到加速器地址
https://d2lhm394.mirror.aliyuncs.com 
或
https://registry.docker-cn.com (官方加速)
​
#在/etc/docker目录下找到在daemon.json文件(没有就新建),将下面内容写入
{
  "registry-mirrors": ["https://d2lhm394.mirror.aliyuncs.com"]
}
​
#重启daemon
systemctl daemon-reload
​
#重启docker服务
systemctl restart docker

5.2 搜索镜像

语法:docker search 镜像名

docker search tomcat

image-20221024104229409.png 在列出信息中,可以看到几个字段信息:

名字 描述 NAME 镜像的名称 DESCRIPTION 镜像的描述 STARTS 点星数 OFFICI 是否是官方镜像

也可以从docker hub官网搜索要使用的镜像:https://hub.docker.com,如下图:

image-20221024102813405.png

5.3 下载镜像

语法:docker pull 镜像名

#默认是下载最新版本的镜像,也就是latest版本
docker pull tomcat
​
#以上命令等价于,其中:latest就是版本
docker pull tomcat:latest

image-20221024111335818.png

image-20221024143638167.png

5.4 镜像的分层

  • 在上图中,我们下载镜像的时候可以看出,镜像是由许多层(layer)的文件系统叠加构成的,例如:cf92e523b49e这样的字符串是层的唯一ID,使用docker pull命令下载中会获取并输出镜像的各层信息
  • 分层中最下面是一个引导文件系统bootfs,第二层是一个root文件系统rootfs,root文件系统通常是某种操作系统的运行环境。例如:CentOS、Ubuntu,在root文件系统之上又有很多层文件系统,这些文件系统叠加在一起,构成Docker中的镜像
  • 这样做的最大好处是共享资源,当不同的镜像包括相同的层时,本地仅存储了一份内容,减少了存储空间。例如:有多个镜像都从相同的base镜像构建而来,那么本地磁盘只需保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务了

image-20221025143449570.png

5.5 显示本地已有的镜像列表

语法:docker images or docker images 镜像名

#显示全部镜像
docker images
​
#按需显示指定名称的镜像
dokcer images tomcat

在列出信息中,可以看到几个字段信息:

名字 描述 REPOSITORY 来自于哪个仓库,比如tomcat TAG 镜像的标签,比如latest代表最新的版本 IMAGE ID 镜像的ID号,ID号是唯一的 CREATED 镜像的创建时间 SIZE 镜像的大小

5.6 Tag标签

镜像的名称实际上由两部分组成:repository:tag,其中的 tag 一般用来表示版本,默认的 taglatest,表示最近的版本,如果我们不写版本,默认下载的就是latest最新版本,镜像的名称相当于在镜像上贴的一个标签,在一个镜像上可以贴多个标签,例如:tomcat:latesttomcat:10,等价于给镜像取了不同的名字,语法:docker tag 原repository:tag 新repository:tag

#给tomcat镜像另起一个名字
docker tag tomcat:latest tomcat:10
​
#查看镜像,可以看到同一个镜像(ID相同)可以有多个名称
docker images tomcat

image-20221031151134556.png

5.7 查看镜像详情

我们可以查看镜像的详情信息,包括镜像名字、镜像ID、镜像的作者、镜像大小、镜像各层的数字ID等,语法:docker inspect 镜像名

docker inspect tomcat

image-20221025145531726.png

5.8 导出镜像文件

我们可以把镜像导出为本地文件,然后在需要镜像的其他机器中导入此镜像即可,导出镜像的语法:docker save 镜像名 > 压缩包名

#将tomcat镜像导出为tomcat.tar.gz
docker save tomcat > tomcat.tar.gz
​
#导出多个镜像文件
docker save tomcat hello-world > images.tar.gz

5.9 删除镜像

在删除镜像的时候需要注意的是,只有当镜像只有唯一的一个名称时才会删除镜像,否则只是删除当前的名称,语法:docker rmi 镜像名

#删除名字叫tomcat:10的镜像,注意:这里其实只是把名字删除了
docker rmi tomcat:10
​
#删除tomcat:latest,因为是唯一的一个名字了,所以这里才会做最终的删除
docker rmi tomcat:latest

5.10 导入镜像文件

我们可以把本地导出好的镜像文件,导入到我们当前机器的docker中,语法:docker load < 压缩包名

docker load < tomcat.tar.gz

6. Docker容器实践

  • 启动容器有两种方式,一个是将处于停止状态的容器启动,一种是基于镜像新建一个容器并直接启动
  • 容器的命令格式大致是这样的形式:docker 容器命令 [参数选项][可选] 镜像名称 or 镜像id or 容器id
  • 由于容器是整个Dokcer的核心之一,所有有关于容器的操作命令可以支持很多参数选项,它们大致分为与容器运行模式相关与容器环境配置相关与容器资源限制和安全保护相关,常用的一些选项我们在命令讲解的过程中逐一说明
  • 具体每个容器命令可以有哪些参数选项,使用docker 容器命令 --help来进行查看

6.1 创建容器

语法:docker create [参数选项] 镜像名 or 镜像id,容器创建好之后,默认处于停止状态

#创建容器
docker create tomcat
或
dokcer create 543fd2c4284f
​
#创建容器,并给容器取上一个名字
dokcer create --name tomcat01 tomcat
或
dokcer create --name tomcat01 543fd2c4284f

执行以上命令后会看到标准输出里打印了一个字符串,这个字符串是容器的ID

image-20221026111536893.png

需要注意的是:当我们创建一个容器的时候,容器一旦被创建完成分配好容器ID后,则会一直存在于我们的容器列表中,如果我们再次使用镜像创建一个容器,不是做覆盖操作,而会再次创建一个新的容器并分配新的容器ID,我们可以简单的理解从面向对象的角度来理解,每次我们创建容器,就是从类中创建了一个新的对象

6.2 查看容器

语法:dokcer ps [参数选项]

#查看当前正在运行的容器
docker ps
​
#查看当前所有容器,其中-a参数代表所有容器
docker ps -a
​
#查看当前所有容器,仅列出其容器id,其中-q参数代表只列出容器id
docker ps -aq

image-20221026113758415.png 在列出信息中,可以看到几个字段信息:

名字 描述 CONTAINER ID 当前容器ID,唯一 IMAGE 当前容器属于哪一个镜像的实例 COMMAND 容器运行时所执行的命令 CREATED 容器创建的时间 STATUS 容器的运行状态 PORTS 容器向外暴露的访问端口 NAMES 容器的名字

6.3 启动容器

语法:dokcer start 容器id or 容器名

#启动容器时,这里的容器id可以只填写容器id的前几位,但最少要有3位
docker start 6d52
或
docker start tomcat01
​
#查看容器是否启动成功
ps -ef | grep tomcat

6.4 停止容器

语法:docker stop 容器id or 容器名

docker stop 6d52
或
docker stop tomcat01

6.5 删除容器

语法:docker rm [参数选项] 容器id or 容器名

#删除容器时,容器必须是停止状态,否则会报错
docker rm f2f9
或
docker rm tomcat01
​
#强制性删除容器
docker rm -f f2f9
或
dokcer rm -f tomcat01

6.6 通过镜像直接启动容器

Docker提供了一种直接通过镜像创建容器的时候同时启动当前容器的方式,语法:docker run [参数选项] 镜像名or镜像id ,它等同于前面我们所说的创建容器命令docker create [参数选项] 镜像名 or 镜像id和启动容器命令dokcer start 容器id or 容器名的结合,也是我们最常使用的一种方式

#通过tomcat镜像,后台启动一个tomcat容器,其中-d参数的意义是让容器启动时采用后台方式启动,默认容器启动时是采用前台启动,当我们自己挂断控制台窗口时就会停止容器
docker run -d tomcat
或
docker run -d 543fd2c4284f
​
#直接通过镜像启动容器时,为容器取上一个名字
docker run -d --name tomcat02 tomcat
或
docker run -d --name tomcat02 543fd2c4284f

6.7 重启容器

这个命令与启动容器命令不同的地方在于,启动命令只能启动正处于停止状态下的容器,而重启容器命令可以重启正在运行状态的容器,也能启动整处于停止状态下的容器,语法:docker restart 容器id or 容器名

#重启处于运行或停止状态的容器
docker restart 6d52
或
docker restart tomcat02
​
#通过镜像直接启动容器时指定容器默认自动重启,docker系统服务重启,或者操作系统重启,容器可以随系统自动启动
docker run -d --name tomcat03 --restart=always tomcat
或
docker run -d --name tomcat03 --restart=always 543fd2c4284f

6.8 进入容器

当容器进行-d后台启动的时候,用户无法看到容器中的信息,也无法进行操作,这个时候需要进入容器进行操作,官方有两个命令用于进入容器,attchexec,推荐使用exec,语法:docker exec [参数选项] 容器id or 容器名 需要执行的命令

#进入容器,运行指定命令,其中i表示交互式的,也就是保持标准输入流打开,t表示虚拟控制台,分配到一个虚拟控制台
docker exec -it 82c045 pwd
docker exec -it 82c045 ls
或
docker exec -it tomcat02 pwd
docker exec -it tomcat02 ls
​
#进入容器,并启动bash命令行,输入exit可以退出命令行
docker exec -it 82c045 bash
或
docker exec -it tomcat02 bash

6.9 查看容器日志

语法:docker logs [参数选项] 容器id or 容器名

#查看容器中的过往日志
docker logs 82c045
或
docker logs tomcat02
​
#查看容器中的实时日志,-f代表显示滚动日志
docker logs -f 82c045
或
docker logs -f tomcat02

6.10 复制文件

Docker支持在容器和宿主机之间复制文件,语法格式:docker cp 容器名 or 容器id:要拷贝的容器中的文件或目录 拷贝到的宿主机目录 或者 docker cp 要拷贝的宿主机文件或目录 容器名 or 容器id:拷贝到的容器中的目录

#将tomcat02容器中的server.xml配置文件拷贝到宿主机中的/root目录下
docker cp tomcat02:/usr/local/tomcat/conf/server.xml /root
或
docker cp 82c045:/usr/local/tomcat/conf/server.xml /root
​
#我们将拷贝下来的server.xml文件中的端口号修改为9090
vim server.xml
​
<Connector port="9090" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
​
#将宿主机中/root目录下的server.xml文件拷贝到tomcat02容器中
docker cp /root/server.xml tomcat02:/usr/local/tomcat/conf
或
docker cp /root/server.xml 82c045:/usr/local/tomcat/conf
​
#重新启动tomcat02容器,并查看日志情况
docker restart tomcat02
docker logs tomcat02

6.11 查看容器元信息

查看某容器的具体信息,会以 json 格式返回包括容器 ID、创建时间、路径、状态、镜像、配置等在内的各项信息,语法:docker inspect 容器id or 容器名

docker inspect 82c045
或
docker inspect tomcat02

6.12 容器的组合命令

在Docker中,我们可以对命令进行组合从而达到我们预期的效果,这里列出一些高频使用的组合命令

#停用全部运行中的容器
docker stop $(docker ps -q)
​
#删除全部容器
docker rm $(docker ps -aq)
​
#停用并删除所有容器
docker stop $(docker ps -q) & docker rm -f $(docker ps -aq)

6.13 容器端口映射

在启动容器的时候,如果不指定对应参数,在容器外部是无法通过网络来访问容器的网络应用和服务的,当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-P-p 参数来指定端口映射。当使用大写的-P时,Docker会随机映射一个49000~49900的端口到内部容器中,当使用小写的-p时,我们可以自定义映射端口到内部容器中,语法:docker run -d -P or -p [宿主机开放ip]宿主机端口号:容器映射端口号 镜像名 or 镜像id,这里我们以tomcat为例,来为大家进行说明,步骤如下:

  1. 启动tomcat容器,并指定端口映射:

    #启动一个tomcat,自动分配宿主机和容器的端口映射
    docker run -d -P tomcat
    或
    docker run -d -P 543fd2c4284f
    ​
    #启动一个tomcat,自定义宿主机和容器的端口映射
    docker run -d -p 8080:8080 tomcat
    或
    docker run -d -p 8080:8080 543fd2c4284f
    ​
    #启动一个tomcat,自定义宿主机和容器的端口映射,并限制ip地址为127.0.0.1的机器才可以访问
    docker run -d -p 127.0.0.1:8080:8080 tomcat
    或
    docker run -d -p 127.0.0.1:8080:8080 543fd2c4284f
    
  2. 查看端口映射关系

    #主要关注PORTS这一栏,这里指的是任意IP地址都可以访问宿主机的8080端口号来访问容器内部的tomcat的8080端口0.0.0.0:8080->8080/tcp
    docker ps 
    

    image-20221031153024149.png

  3. 我们可以在windows的浏览器上输入测试,出现tomcat的首页则成功

    http://192.168.177.128:8080
    

    image-20221031154050511.png 有两个地方值得注意:

    3.1 如果输入浏览器地址时,发现浏览器一直处于转圈的一个加载状态,过一会出现404,说明是linux宿主机的防火墙未关闭

    #查看防火墙状态
    systemctl status firewalld 
    ​
    #关闭防火墙
    systemctl stop firewalld
    ​
    #让防火墙禁用
    systemctl disable firewalld
    

    3.2 如果出现页面,但页面显示的是tomcat404,则说明是tomcat的首页没有正确配置,我们可以进入docker容器配置tomcat首页

    image-20221031153536726.png

    #进入容器
    docker exec -it 1d812 bash
    ​
    #查看tomcat在容器中的哪个目录
    whereis tomcat
    ​
    #进入tomcat目录
    cd /usr/local/tomcat
    ​
    #进入webapps.dist中的ROOT文件夹拷贝到webapps下,刷新页面即可
    cp -r webapps.dist/ROOT webapps
    

7. Docker数据管理

在使用Docker时,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作,容器中的管理数据主要有两种方式:目录挂载数据卷挂载

7.1 目录挂载

目录挂载就是我们将宿主机的真实文件路径和容器中的路径做一个映射,当宿主机的数据发生变化会同步到容器中,反之,当容器中的数据发生变化,也会直接同步到宿主机的挂载目录中。在Docker中,在启动容器时,我们可以通过配置-v 参数选项来启用挂载宿主机目录功能,语法:docker run -v 宿主机目录:容器目录 镜像名 or 镜像id

我们这里以Tomcat为例:

  1. 在宿主机中创建mydata/tomcat目录

    mkdir -p /mydata/tomcat
    
  2. 启动一个tomcat容器,将宿主机的/mydata/tomcat目录挂载到容器的/usr/local/tomcat/webapps/ROOT

    docker run -d -p 8080:8080 -v /mydata/tomcat/:/usr/local/tomcat/webapps/ROOT tomcat
    
  3. 在/mydata/tomcat目录下建立test.html

    vim /mydata/tomcat/test.html
    

    填入以下内容:

    <html>
      <head>
        <meta charset="utf-8">
      </head>
      <body>
        <p>测试目录挂载</p>
      </body>
    </html>
    
  4. 用浏览器访问测试

    http://192.168.177.128:8080/test.html
    

    image-20221108110950213.png

  5. 修改/mydata/tomcat/test.html的内容

    vim /mydata/tomcat/test.html
    
    <html>
      <head>
        <meta charset="utf-8">
      </head>
      <body>
        <p>测试目录挂载修改</p>
      </body>
    </html>
    
  6. 再次用浏览器访问观察变化

    http://192.168.177.128:8080/test.html
    

    image-20221108111134261.png

  7. 我们也可以进入容器观察挂载情况

    #进入容器
    docker exec -it d55b27 bash
    ​
    #切换到tomcat的ROOT目录下
    cd /usr/local/tomcat/webapps/ROOT
    

    image-20221108142050707.png

7.2 数据卷挂载

数据卷是一个可供一个或多个容器使用的特殊目录,它将宿主机目录直接映射进容器,在容器之间共享和重用,默认会一直存在,即使容器被删除。数据卷目录挂载的区别在于数据卷是受控存储,是由Docker引擎进行管理维护的。因此使用数据卷,你可以不必处理 uid、SELinux 等各种权限问题,Docker引擎在建立卷时会自动添加安全规则,以及根据挂载点调整权限。并且可以统一列表、添加、删除。而目录挂载那就没人管了,属于用户自行维护,就必须手动处理所有权限问题。特别是在CentOS 上,很多时候碰到 Permission Denied(权限被拒绝),就是因为没有使用数据卷,而是目录挂载,Docker提供了 volume子命令来管理数据卷

我们这里以Tomcat为例:

  1. 新建数据卷

    docker volume create tomcat-vol
    ​
    #创建完毕后,查看/var/lib/docker/volumes路径下,会发现所创建的数据卷位置
    cd /var/lib/docker/volumes
    

    image-20221109104119708.png

  2. 查看数据卷

    #列出所有数据卷
    docker volume ls
    ​
    #查看指定数据卷的详情
    docker inspect tomcat-vol
    
  3. 启动Tomcat容器,并挂载数据卷

    #--mount选项用于进行数据卷的挂载,其中source是指定数据卷的名字,target指定容器的挂载目录
    docker run -d -p 8080:8080 --mount source=tomcat-vol,target=/usr/local/tomcat/webapps/ROOT tomcat
    ​
    #以上命令也可以采用目录挂载的方式进行简写
    docker run -d -p 8080:8080 -v tomcat-vol:/usr/local/tomcat/webapps/ROOT tomcat
    
  4. 在数据卷目录中添加test.html

    #切换到数据卷目录
    cd /var/lib/docker/volumes/tomcat-vol/_data
    ​
    #添加test.html
    vim test.html
    

    添加内容如下:

    <html>
      <head>
        <meta charset="utf-8">
      </head>
      <body>
        <p>测试数据卷挂载</p>
      </body>
    </html>
    
  5. 用浏览器访问测试

    http://192.168.177.128:8080/test.html
    

    image-20221109153515034.png

  6. 删除数据卷

    docker volume rm tomcat-vol
    

    删除数据卷时会出现以下异常:原因是正在被容器使用的数据卷是无法删除的!

    image-20221109154141784.png 我们可以先删除容器,再尝试删除数据卷

    #查询容器列表
    docker ps
    ​
    #删除容器
    docker rm -f 3b6c856e1ae7
    ​
    #删除数据卷
    docker volume rm tomcat-vol
    
  7. 清理无用数据卷

    #没有被挂载的数据卷执行此命令会被删除掉
    docker volume prune
    

7.3 Commit命令

Docker提供了一个比较特殊的命令commit,该命令可以将设置好的容器数据状态保存为一个新的镜像,语法:docker commit 镜像id or 镜像名 新镜像名

我们以仍然Tomcat为例:

  1. 启动一个新的Tomcat容器

    docker run -d -p 8080:8080 tomcat
    
  2. 进入容器,在/usr/local/tomcat/webapps下创建ROOT目录

    #进入容器
    docker exec -it a48c66 bash 
    ​
    #进入webapps目录
    cd /usr/local/tomcat/webapps
    ​
    #创建ROOT目录
    mkdir ROOT
    ​
    #退出容器
    exit
    
  3. 将宿主机的/mydata/tomcat/test.html文件复制容器中

    docker cp /mydata/tomcat/test.html a48c66:/usr/local/tomcat/webapps/ROOT/test.html
    
  4. 访问如下地址看到页面

    http://192.168.177.128:8080/test.html
    

    image-20221125142849703.png

  5. 使用commit保存修改后的容器作为新的镜像

    docker commit a48c66 my_tomcat
    或
    docker commit a48c66 my_tomcat:latest
    
  6. 从新镜像中启动容器

    #先停止并删除掉之前的容器
    docker rm -f a48c66
    ​
    #从保存的新镜像中启动容器
    docker run -d -p 8080:8080 my_tomcat
    
  7. 再次访问页面,之前commit保存的新镜像已经保留了我们之前复制进去的页面

    http://192.168.177.128:8080/test.html
    

    image-20221125142849703.png

    如果我们希望把一个运行着的容器,由于里面改了一些数据或配置,并希望把该容器保存起来,可以使用上面这种做法,得到一个新镜像,下次用该新镜像运行新的容器,这是一种数据持久化的特殊做法,也是一种自定义一个镜像的方式之一

8. 本地镜像上传仓库

  • 我们知道仓库是集中存放镜像的地方,仓库又分公共仓库私有仓库
  • 最大的公开仓库是 Docker Hub国内第三方仓库,例如:腾讯云、华为云、阿里云等
  • 私有仓库又分为本地私有仓库国内第三方仓库,例如:腾讯云、华为云、阿里云等
  • 有时候容易把仓库注册服务器混淆实际上注册服务器是存放仓库的具体服务器, 一个注册服务器上可以有多个仓库,而每个仓库下面可以有多个镜像,仓库可以被认为是一个具体的项目或目录,例如对于仓库地址 private-docker.com/ubuntu 来说, private-docker.com 是注册服务器地址, ubuntu是仓库名

8.1 本地镜像上传Docker Hub

我们以之前自己commit保存的my_tomcat镜像为例,上传本地的镜像到官方提供的Docker Hub中

  1. 注册

    #在如下网站注册下得到docker id和密码
    https://hub.docker.com/ 
    

    image-20221117094802004.png

    image-20221117094832189.png

    image-20221117094448310.png

  2. 在本地虚拟机登陆hub服务器

    #输入如下命令,并根据提示输入docker id和密码即可
    docker login
    

    image-20221117101848546.png

  3. 修改镜像名称,在推送之前,你要确保镜像不能随意取名,需要遵循docker hub的命名规则

    #其中docker.io是注册服务器地址,gudashi是我们的dokcer id,my_tomcat是我们的仓库名
    docker tag my_tomcat docker.io/gudashi/my_tomcat
    ​
    #因为默认使用的注册服务器就是dokcer.io所以这里也可以省略不写
    docker tag my_tomcat gudashi/my_tomcat
    
  4. 推送镜像

    #推送过程可能因为网络原因会有失败的情况,可以反复尝试一下
    docker push docker.io/gudashi/my_tomcat
    或
    docker push gudashi/my_tomcat
    
  5. 验证是否成功

    登陆如下网站,点击Repositories菜单,此时已经出现了我们的镜像
    https://hub.docker.com/
    

    image-20221117103844116.png

  6. 下载镜像

    #删掉之前本地的镜像
    docker rmi gudashi/my_tomcat
    或
    docker rmi docker.io/gudashi/my_tomcat
    ​
    #执行下载
    docker pull docker.io/gudashi/my_tomcat
    或
    docker pull gudashi/my_tomcat
    

8.2 本地镜像上传私有仓库

私有仓库其本质就是我们启动一个docker的镜像仓库容器,通过这个容器服务来帮助我们管理镜像,我们以之前自己commit保存的my_tomcat镜像为例,上传本地的私有仓库中

  1. 下载registry镜像

    docker pull registry
    
  2. 启动镜像

    #启动容器,-d后台启动 -p端口映射(端口号默认为5000) -v目录挂载
    docker run -d -p 5000:5000 -v /mydata/registry:/var/lib/registry registry
    
  3. 查看镜像

    #在浏览器访问如下地址,此时仓库里是空的
    http://192.168.177.128:5000/v2/_catalog
    

    image-20221117141758667.png

  4. 修改镜像名称,在推送之前,仍然要确保镜像不能随意取名,需要遵循命名规则

    #其中127.0.0.1:5000是注册服务器地址,这里设置成我们本机地址,gucaini是我们的dokcer id,my_tomcat是我们的仓库名
    docker tag my_tomcat 127.0.0.1:5000/gucaini/my_tomcat
    
  5. 推送镜像

    docker push 127.0.0.1:5000/gucaini/my_tomcat
    
  6. 再次查看镜像

    #在浏览器访问如下地址,此时仓库里已经有了我们推送上去的镜像
    http://192.168.177.128:5000/v2/_catalog
    

    image-20221117141839902.png 我们也可以在挂载的目录中找到我们的镜像文件

    cd /mydata/registry/docker/registry/v2/repositories
    

    image-20221117142034884.png

  7. 下载镜像

    #修改/etc/docker/daemon.json,让docker信任私有仓库地址
    vim /etc/docker/daemon.json
    {
      "registry-mirrors": ["https://d2lhm394.mirror.aliyuncs.com"],
      "insecure-registries": ["192.168.177.128:5000"]
    }
    ​
    #然后重启docker
    systemctl restart docker
    ​
    #重启registry容器
    docker start e2124c23ba8a
    ​
    #删掉之前本地的镜像
    docker rmi 127.0.0.1:5000/gucaini/my_tomcat
    ​
    #执行下载
    docker pull 192.168.177.128:5000/gucaini/my_tomcat
    

8.3 本地镜像上传阿里云

国内很多厂商提供了第三方仓库可以帮助我们统一管理我们的镜像,这里我们以阿里云为例,用我们以之前自己commit保存的my_tomcat镜像为例,上传本地的镜像到阿里云中

  1. 进入阿里云容器镜像服务

    https://cr.console.aliyun.com/cn-hangzhou/instances
    

    image-20221117150129301.png

  2. 创建个人实例

    在实例列表中,选择个人实例,进行创建

    image-20221117150236147.png

  3. 设置Registry登录密码

    image-20221117150317703.png

    image-20221117150408612.png

  4. 创建命名空间

    在个人实例的仓库管中找到命名空间进行创建,命名空间类似于我们Java中的包,其主要目的是区分不同的环境,统一管理,推荐使用公司、组织、或者个人用户来命名,例如:aliyun、gucaini,不推荐使用对应的一个模块或系统,例如:tomcat、mysql

    image-20221118103821478.png

  5. 设置命名空间仓库的类型

    命名空间创建完毕之后,可以选择在该命名空间下创建的仓库类型,默认为私有

    image-20221124143746072.png

  6. 创建镜像仓库

    选择镜像仓库进行仓库创建,填写仓库基本信息,在代码源中选择本地仓库,然后执行创建

    image-20221124144145782.png

    image-20221124144429855.png

  7. 完成创建

    完成仓库创建后,会出现下图所示界面,该界面有具体的操作指南,我们根据指南就可进行本地镜像推送到阿里云私有镜像仓库中

    image-20221124144642632.png

  8. 在本地虚拟机登陆阿里云服务器

    #输入如下命令进行登录,--username为你自己的阿里云账号,提示输入密码时,是你自己开通服务时所设置的密码
    docker login [email protected] registry.cn-hangzhou.aliyuncs.com
    

    image-20221124145239995.png

  9. 修改镜像名称,在推送之前,你要确保镜像不能随意取名,需要遵循阿里云的命名规则

    #其中registry.cn-hangzhou.aliyuncs.com是注册服务器地址,gucaini是我们的命名空间,tomcat是我们的仓库名
    docker tag my_tomcat registry.cn-hangzhou.aliyuncs.com/gucaini/tomcat
    
  10. 推送镜像

    docker push registry.cn-hangzhou.aliyuncs.com/gucaini/tomcat
    
  11. 查看镜像

    推送完毕后,可在镜像版本中查看我们所推送的镜像,如下图

    image-20221124154418784.png

  12. 下载镜像

    #先删除本地镜像
    docker rmi registry.cn-hangzhou.aliyuncs.com/gucaini/tomcat
    ​
    #下载镜像
    docker pull registry.cn-hangzhou.aliyuncs.com/gucaini/tomcat
    

9. 常用软件基础安装

Docker可以安装几乎比较全面的主流软件,我们一一例举显然是不太现实的,这里我们以4个常用软件作为基础软件安装教学,它们分别是:MySQL、Redis、RabbitMQ、ElasticSearch

9.1 MySQL基础安装

MySQL 是全球最流行的开源关系型数据库之一,由于其具有高性能、成熟可靠、高适应性 易用性而得到广泛应用

  1. 下载MySQL镜像

    #我们可以在Docker Hub中找到MySQL镜像
    https://hub.docker.com/_/mysql
    ​
    #拉取MySQL镜像,默认拉取的版本是latest的,这里下载的是8.0版本的MySQL镜像
    docker pull mysql
    ​
    #也可以指定版本拉取,这里下载的是5.7版本的MySQL镜像
    docker pull mysql:5.7.40
    

    image-20221129102719295.png

  2. 快速启动一个MySQL容器

    #其中-d代表后台启动,-p代表端口映射,--name是容器的名称,-e是指定容器启动时所需要配置的环境变量,例如:MYSQL_ROOT_PASSWORD就是指定数据库的密码
    docker run -d -p 3306:3306 --name my_mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
    ​
    #查看容器是否启动
    docker ps
    ​
    #查看容器启动时的日志
    docker logs b87dd
    
  3. 进入容器,并登陆MySQL客户端

    docker exec -it b87dd bash
    ​
    #进入容器后输入MySQL客户端连接命令,其中-u是数据库用户名,默认为root,-p是数据库密码
    mysql -uroot -p123456
    

    image-20221129103532075.png

  4. 进行数据库操作

    #查看所有的库
    show databases;
    ​
    #创建一个数据库
    create database docker;
    ​
    #切换数据库
    use docker;
    ​
    #查看所有表
    show tables;
    ​
    #创建一张表
    create table t_user(
        id int primary key,
        user_name varchar(20),
        passsword varchar(50)
    );
    ​
    #插入数据
    insert into t_user values(1,'Tom','123456');
    ​
    #查询表
    select * from t_user;
    
  5. 授权远程登录访问:

    #修改远程用户访问密码,其中root@'%'中的root表示用户名,%表示任意ip地址
    alter user 'root'@'%' identified with mysql_native_password by '123456';
    ​
    #授权访问,其中*.* 的第一个*表示所有数据库名,第二个*表示所有的数据库表
    grant all privileges on *.* to 'root'@'%';
    ​
    #刷新权限
    flush privileges;
    
  6. 使用SQLyog远程连接MySQL

    主机地址:192.168.177.128
    用户名:root
    密码:123456
    端口:3306
    

    image-20221129112001983.png

    image-20221129112032192.png

  7. 删除容器,并重新启动一个MySQL容器,观察现象

    #删除容器
    docker rm -f b87dd
    ​
    #启动一个新容器
    docker run -d -p 3306:3306 --name my_mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
    ​
    #查看新容器的进程
    docker ps
    ​
    #进入新容器
    docker exec -it 486042 bash
    ​
    #连接MySQL客户端
    mysql -uroot -p123456
    ​
    #查看数据库
    show databases;
    
  8. 再次尝试用SQLyog进行连接,观察现象

    image-20221129143135186.png

    结论:启动新容器后,原有MySQL容器的数据和配置就失效了,容器是瞬态的,所以应当给MySQL的配置数据做持久化。除此之外,如果希望自定义MySQL的配置,例如:指定字符集,配置慢查询日志等功能,也应该将其核心配置文件my.cnf做持久化保存。MySQL的系统日志最好也做持久化保存

  9. 使用数据持久化方式创建MySQL容器

    我们知道,Docker在进行数据管理的时候,支持两种方式,一种是目录挂载,一种是数据卷挂载。本案例中,我们采用目录挂载方式做演示,目录挂载方式需要注意特别是在CentOS 上,很多时候碰到 Permission Denied(权限被拒绝),就是因为没有使用数据卷,而是目录挂载,例如:MySQL中使用目录挂载方式,就会出现chown: changing ownership of '/var/lib/mysql/': Permission denied 这样的错误,所以此处我们需要自行处理掉这个问题,或者干脆使用数据卷的方式

    #启动MySQL容器
    docker run --name=my_mysql --privileged=true --restart=always \
    -v /mydata/mysql/data:/var/lib/mysql \
    -v /mydata/mysql/conf:/etc/mysql/conf.d \
    -v /mydata/mysql/logs:/var/log/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    -d -p 3306:3306 mysql
    ​
    #以上命令解析
    --name:容器的名称
    ​
    --privileged=true:为了防止出现Centos7安全Selinux禁止了一些安全权限
    ​
    --restart=always:开机自动重启MySQL容器
    ​
    -v:目录挂载
    -v /mydata/mysql/data:/var/lib/mysql
    将宿主机的/mydata/mysql/data目录挂载到容器中的/var/lib/mysql目录中(这是MySQL容器默认存储数据文件的目录)
    -v /mydata/mysql/conf:/etc/mysql/conf.d
    将宿主机的/mydata/mysql/conf目录挂载到容器中的/etc/mysql/conf.d目录(这是MySQL容器默认的配置文件目录)
    -v /mydata/mysql/logs:/var/log/mysql 
    将宿主机的/mydata/mysql/conf目录挂载到容器中的/etc/mysql/conf.d目录(这是MySQL容器默认的配置文件目录)
    ​
    -e:指定环境变量,其中MYSQL_ROOT_PASSWORD指定数据库的密码
    ​
    -d:后台启动
    ​
    -p:端口映射
    
  10. 添加MySQL自定义配置

    #在宿主机中切换到/mydata/mysql/conf目录下
    cd /mydata/mysql/conf
    ​
    #添加my.cnf数据库核心配置文件
    vim my.cnf
    ​
    #添加以下内容
    [client]
    default-character-set=utf8mb4
    ​
    [mysqld]
    character-set-server=utf8mb4
    autocommit=1
    ​
    #[clinet]代表配置MySQL客户端连接时的相关配置
    default-character-set:设置MySQL客户端连接时的字符集
    ​
    #[mysqld]代表MySQL服务端的相关配置
    character-set-server:设置服务端的字符集
    autocommit:开启自动提交
    ​
    #配置完毕后重启容器
    docker restart my_mysql
    
  11. 进入容器,重新尝试之前的数据操作,远程授权,并删掉容器,重新以目录挂载方式启动,观察现象

    image-20221130102931705.png

    image-20221130103611566.png

    结论:启动新容器后,原有MySQL容器的数据由于做了目录挂载进行了持久化,数据被保留了。由于自定义了MySQL的配置,现在插入数据也支持中文插入。远程授权访问的设置也被完整的保留了下来

9.2 Redis基础安装

Redis是一个基于内存的数据结构存储服务器,常被用作数据库、缓存、消息队列,是目前最主流的Nosql数据库之一

  1. 下载Redis镜像

    #我们可以在Docker Hub中找到Redis镜像
    https://hub.docker.com/_/redis
    ​
    #拉取Redis镜像,默认拉取的版本是latest的,注意官方latest版本默认是7.0版本,但由于我们配置了阿里云镜像加速器,默认下载下来的版本还是6.0的版本
    docker pull redis
    ​
    #也可以指定版本拉取,这里下载的是7.0版本的Redis镜像
    docker pull redis:7.0.5
    

    image-20221130110111242.png

  2. 快速启动一个Redis容器

    docker run -d -p 6379:6379 --name my_redis redis:7.0.5
    
  3. 进入Redis客户端工具,进行测试

    #进入容器
    docker exec -it my_redis bash
    ​
    #查看Redis的版本
    redis-server -v
    ​
    #进入Redis命令窗口
    redis-cli
    ​
    #输入以下命令
    set test 1
    get test
    

    image-20221201100309891.png

  4. 创建用于持久化Redis数据的数据卷

    显然快速启动Redis的方式,并不是我们想要的方式,在前面MySQL中,我们使用了目录挂载方式来进行数据持久化。Redis因本身是一个内存结构的数据库,但如果容器关闭或宿主机重启了,就会丢失内存数据,但其内部也做了数据持久化方案,通常是使用RDBAOF的方式进行持久化,为了保证数据不丢失,也应当进行持久化工作。同时Redis本身支持很多自定义配置,这些配置都是记录在其核心配置文件redis.conf中,所以此文件,我们也应当进行持久化。本例中我们采用数据卷的方式来进行持久化

    #新建两个数据卷,一个用于存储redis配置文件数据,一个用于存储redis的持久化数据
    docker volume create redis-config
    docker volume create redis-data
    ​
    #查看数据卷详情
    docker inspect redis-config
    docker inspect redis-data
    ​
    #切换到/var/lib/docker/volumes/redis-config/_data目录中,放入我们准备好的redis.conf文件
    cd /var/lib/docker/volumes/redis-config/_data
    ​
    #编辑redis.conf配置文件,修改如下配置
    protected-mode no (改为不保护,否则远程访问不了)
    bind 127.0.0.1 (注释掉,否则只能本机ip访问)
    requirepass 设置密码
    

    一个比较大的坑:在redis.conf核心配置文件中有一个配置daemonize no,此配置的含义是Redis在运行的时候是否进行后台启动,在不使用Docker的情况下,原生安装Redis软件我们通常会把此配置改为daemonize yes,使Redis以后台方式进行启动,但在使用Docker的情况下,此配置修改之后就会导致Redis容器无法正常启动,因为Docker在启动容器时本身有一个选项-d就支持后台启动,这就会与该配置产生冲突。

  5. 使用数据持久化方式创建Redis容器

    docker run --name my_redis --restart=always \
    -v redis-data:/data \
    -v redis-config:/usr/local/etc/redis \
    -d -p 6379:6379 \
    redis:7.0.5 redis-server /usr/local/etc/redis/redis.conf
    ​
    #以上命令解析
    --name:容器的名称
    ​
    --restart=always:开机自动重启Redis容器
    ​
    -v:目录挂载
    -v redis-data:/data
    将宿主机的数据卷redis-data挂载到容器中的/data目录中(这是Redis容器默认存储数据文件的目录)
    -v redis-config:/usr/local/etc/redis \
    将宿主机的数据卷redis-config目录挂载到容器中的/usr/local/etc/redis目录(这是官方推荐我们挂载配置文件的目录)
    ​
    -d:后台启动
    ​
    -p:端口映射
    ​
    redis-server /usr/local/etc/redis/redis.conf: 在Redis容器启动的时候执行一个命令,该命令指定了我们自定义的配置文件来启动Redis
    
  6. 进入容器,效验我们自定义的配置是否生效

    #进入容器
    docker exec -it my_redis bash
    ​
    #登录redis命令客户端
    redis-cli
    ​
    #输入密码
    auth 123456
    

    image-20221201110034735.png

  7. 使用可视化工具连接Redis

    Another Redis Desktop Manager是国内开源免费的一个用于可视化操作Redis的热门桌面工具,GitHub地址:https://github.com/qishibo/AnotherRedisDesktopManager,如能正常连接,说明Redis允许远程访问的配置也生效了

    image-20221201110602442.png

  8. 测试Redis持久化

    Redis默认开启了RDB持久化方式,我们往Redis里写入数据,然后在客户端中执行save命令进行内存数据强制性保存,观察数据卷目录的持久化情况。之后删掉容器,重新启动一个新的Redis容器,观察数据是否恢复

    #进入容器
    docker exec -it my_redis bash
    ​
    #登录redis命令客户端
    redis-cli
    ​
    #输入密码
    auth 123456
    ​
    #输入命令
    set test 1
    get test
    save
    ​
    #删掉容器
    docker rm -f my_redis
    ​
    #重新创建新的容器
    docker run --name my_redis --restart=always \
    -v redis-data:/data \
    -v redis-config:/usr/local/etc/redis \
    -d -p 6379:6379 \
    redis:7.0.5 redis-server /usr/local/etc/redis/redis.conf
    

    image-20221201112811623.png

    image-20221201113340423.png

  9. 开启RDB备份和AOF备份

    • Redis提供两种机制对数据进行持久化,便于恢复数据。一种是RDB方式、另一种是AOF方式
    • RDB是默认开启的,是指在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存
    • AOF是指Redis每次接收到一条改变数据的命令时,它将把该命令写到一个AOF文件中(只记录写操作,不记录读操作),当Redis重启时,它通过执行AOF文件中所有的命令来恢复数据
    • 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效,RDB的缺点是最后一次持久化后的数据可能丢失
    • AOF这种方式的持久化让Redis的数据不会丢失,AOF需要手动开启,AOF可以将Redis执行的每一条写命令追加到硬盘文件中,这一过程会降低Redis的性能,但大部分情况下这个影响是能够接受的
    • RDB和AOF两种持久化方式是可以共存的
    #编辑redis.conf文件
    cd /var/lib/docker/volumes/redis-config/_data
    vim redis.conf
    ​
    #配置文件搜索SNAPSHOTTING部分,设置RDB的自动备份方式,配置格式:save <seconds> <changes>
    save 900 1
    save 300 10
    save 60 10000
    ​
    #配置文件搜索APPEND ONLY MODE部分,设置AOF的备份,AOF的相关配置选项如下
    appendonly  默认是no,改成yes即开启了aof持久化
    appendfilename 指定AOF文件名,默认文件名为appendonly.aof
    appendfsync 配置向aof文件写命令数据的策略:
    no:不主动进行同步操作,而是完全交由操作系统来做(即每30秒一次),比较快但不是很安全
    always:每次执行写入都会执行同步,慢一些但是比较安全
    everysec:每秒执行一次同步操作,比较平衡,介于速度和安全之间
    ​
    #配置完毕之后,重启Redis容器
    docker restart my_redis
    
  10. 测试RDB自动备份和AOF备份

    #进入容器
    docker exec -it my_redis bash
    ​
    #登录redis命令客户端
    redis-cli
    ​
    #输入密码
    auth 123456
    ​
    #输入命令
    set test1 2
    ​
    #在宿主机查看数据卷目录
    cd /var/lib/docker/volumes/redis-data/_data
    

    image-20221201150244522.png

9.3 RabbitMQ基础安装

RabbitMQ是部署最广泛的开源消息中间件之一,RabbitMQ在全球的小型初创企业和大型企业中都有使用。

  1. 下载RabbitMQ镜像

    #我们可以在Docker Hub中找到RabbitMQ镜像
    https://hub.docker.com/_/rabbitmq
    ​
    #拉取Rabbit镜像,默认拉取的版本是latest的,默认是3.11的版本,但此版本不包含RabbitMQ的可视化管理端工具
    docker pull rabbitmq
    ​
    #拉取Rabbit镜像,且包含RabbitMQ的可视化管理端工具
    docker pull rabbitmq:management
    

    image-20221201163031903.png

  2. 以持久化的方式启动RabbitMQ容器

    前面两个案例中,我们都做了持久化启动的详细讲解,本例中,我们就直接以目录挂载持久化方式进行容器的启动

    docker run --name my_rabbitmq --restart=always \
    --hostname=rabbitmq \
    -v /mydata/rabbitmq:/var/lib/rabbitmq \
    -p 5672:5672 \
    -p 15672:15672 \
    -d rabbitmq:management
    ​
    #以上命令解析
    --name:容器的名称
    ​
    --restart=always:开机自动重启RabbitMQ容器
    ​
    --hostname=rabbitmq:这个配置是需要特别注意的,在官方文档中,告诉我们,RabbitMQ它根据所谓的“节点名”来存储数据,默认为主机名。这意味着在Docker中,我们应该为每个守护进程显式地指定 ——hostname,这样我们就不会得到一个随机的主机名。如果不指定,我们做RaabitMQ的数据持久化将不会生效
    ​
    -v:目录挂载
    -v /mydata/rabbitmq:/var/lib/rabbitmq:目录挂载,将宿主机的/mydata/rabbitmq目录挂载到容器中的/var/lib/rabbitmq目录中(这是rabbitmq容器默认存储数据文件的目录)
    ​
    -p:端口映射
    -p 5672:5672:这是rabbitMQ服务进程的默认端口号
    -p 15672:15672:这是rabbitMQ可视化管理端工具的默认端口号
    ​
    -d:后台启动
    
  3. 访问RabbitMQ可视化管理端

    我们可以在Windows浏览器中,输入如下地址来访问RabbitMQ可视化管理端

    http://192.168.177.128:15672
    

    image-20221208144640505.png

  4. 登录可视化管理端

    成功访问可视化管理端口后,默认的登录名和密码都是guest,如果想要修改默认用户名和密码,可以通过启动容器时添加RABBITMQ_DEFAULT_USERRABBITMQ_DEFAULT_PASS环境变量来实现。

    docker run --name my_rabbitmq --restart=always \
    --hostname=rabbitmq \
    -v /mydata/rabbitmq:/var/lib/rabbitmq \
    -p 5672:5672 \
    -p 15672:15672 \
    -e RABBITMQ_DEFAULT_USER=admin \
    -e RABBITMQ_DEFAULT_PASS=123456 \
    -d rabbitmq:management
    

    image-20221208145527165.png

  5. 添加一个交换机测试下

    image-20221208150027472.png

  6. 测试持久化

    我们删掉正在运行的RabbitMQ容器,重新启动一个新的容器。启动成功后再次访问客户端工具,看一下之前创建的交换机是否正确被持久化。同时我们也可以观察宿主机目录/mydata/rabbitmq的情况

    #删掉之前的rabbitMQ容器
    docker rm -f my_rabbitmq
    ​
    #启动新的容器
    docker run --name my_rabbitmq --restart=always \
    --hostname=rabbitmq \
    -v /mydata/rabbitmq:/var/lib/rabbitmq \
    -p 5672:5672 \
    -p 15672:15672 \
    -d rabbitmq:management
    ​
    #查看宿主机挂载目录
    cd /mydata/rabbitmq
    

9.4 ElasticSearch基础安装

ElasticSearch是一个基于Apache Lucene作为其核心来实现目前最为主流的搜索引擎之一,它通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

  1. 下载ElasticSearch镜像

    ElasticSearch的更新频率是特别快的,有可能几个小时就会有更新,所以官方建议在下载镜像时,最好要加上tag标签指定版本,目前ElasticSearch的最新版本是8.0+,但实际公司中用的比较多的版本是6.0+和7.0+的版本,我们这里以7.0+版本为例

    #我们可以在Docker Hub中找到ElasticSearch镜像
    https://hub.docker.com/_/elasticsearch
    ​
    #拉取ElasticSearch镜像,默认拉取的版本是latest的,官方强烈不推荐这么干
    docker pull elasticsearch
    ​
    #拉取ElasticSearch镜像,指定版本为7.17.6
    docker pull elasticsearch:7.17.6
    

    image-20221208164605195.png

  2. 准备持久化目录

    本例中,我们仍然以目录挂载持久化方式进行容器的启动,不同的是,在启动前,我们需要自己去创建一下挂载目录,这样做的目的是为了手动更改一下目录的访问权限,在ES的官方中提到,如果我们在Docker中尝试以挂载目录的方式来持久化数据,那么需要对持久化目录的访问权限进行授权,因为Docker中的ES默认是以elasticsearch用户身份运行的,如果宿主机目录是以root用户身份创建的,那么就会导致权限不足,从而启动失败

    #在宿主机中创建持久化目录
    mkdir -p /mydata/es/plugins
    mkdir -p /mydata/es/data
    ​
    #目录解释
    plugins:用于存储es的插件
    data:用于存储es的持久化数据
    ​
    #更改文件权限
    chmod -R 777 /mydata/es
    
  3. 以持久化方式启动ElasticSearch容器

    本例中,我们就直接以目录挂载持久化方式进行容器的启动

    docker run --name my_es --restart=always \
    -e "discovery.type=single-node" \
    -e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
    -v /mydata/es/plugins:/usr/share/elasticsearch/plugins \
    -v /mydata/es/data:/usr/share/elasticsearch/data \
    -p 9200:9200 \
    -p 9300:9300 \
    -d elasticsearch:7.17.6
    ​
    #以上命令解析
    --name:容器的名称
    ​
    --restart=always:开机自动重启ES容器
    ​
    -e:指定环境变量
    -e "discovery.type=single-node" :es在启动的时候默认是需要以集群的方式来运行的,如果我们期望以单机版的方式来启动es,则必须加上此环境变量,告诉容器我们运行的模式是单节点模式
    -e ES_JAVA_OPTS="-Xms256m -Xmx256m":es容器默认设置的JVM内存大小是"-Xms512m -Xmx512m",我们可以指定环境变量来调整JVM的内存大小
    ​
    -v:挂载目录
    -v /mydata/es/plugins:/usr/share/elasticsearch/plugins:目录挂载,将宿主机的/mydata/es/plugins目录挂载到容器中的/usr/share/elasticsearch/plugins目录中(这是es容器默认存储插件的目录)
    -v /mydata/es/data:/usr/share/elasticsearch/data:目录挂载,将宿主机的/mydata/es/data目录挂载到容器中的/usr/share/elasticsearch/data目录中(这是es容器默认存储数据的目录)
    ​
    -p:端口映射
    -p 9200:9200:9200端口是http协议的,用于操作访问es的数据端口
    -p 9300:9300:9300端口是tcp通讯端口,用于ES集群节点之间通讯使用端口
    ​
    -d:后台启动
    
  4. 查看ElasticSearch版本信息

    在我们的Windows浏览器中访问如下地址,出现版本信息则说明启动成功

    http://192.168.177.128:9200 
    

    image-20221209161832583.png

  5. 下载Kibana镜像

    Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用Kibana搜索、查看存放在Elasticsearch中的数据。Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等,直观的展示数据,从而达到高级的数据分析与可视化的目的。简单的说,Elasticsearch本身只是一个搜索引擎存储数据的地方,好比我们的MySQL服务,如果我们希望操作Elasticsearch最简单的方式就是直接通过HTTP请求来进行方法,但这非常的不直观,借助Kibana可以让我们的操作和数据的查看更为直观

    #我们可以在Docker Hub中找到kibana镜像
    https://hub.docker.com/_/kibana
    ​
    #拉取Kibana镜像,需要与我们的ES版本对应
    docker pull kibana:7.17.6
    

    image-20221209164353550.png

  6. 启动Kibana容器

    docker run --name my_kibana --restart=always \
    -e ELASTICSEARCH_HOSTS=http://192.168.177.128:9200 \
    -p 5601:5601 \
    -d kibana:7.17.6
    ​
    #以上命令解析
    --name:容器的名称
    ​
    --restart=always:开机自动重启kibana容器
    ​
    -e:指定环境变量
    -e ELASTICSEARCH_HOSTS=http://192.168.177.128:9200:指定ES的服务端地址和端口号
    ​
    -p:端口映射
    ​
    -d:后台启动
    
  7. 访问Kibana

    在Windows浏览器中输入一下地址对kibana的可视化界面进行访问

    http://192.168.177.128:5601/app/kibana
    

    image-20221214094956746.png

  8. 测试ES

    本篇中,我们以Docker作为教学基础,不对ES做过多教学,这里我们进行基本ES访问测试即可。在kibana中我们找到Dev Tools工具,对ES进行操作访问

    image-20221214095512670.png

    image-20221214095536883.png 在该界面,我们执行以下命令进行测试

    <!-- 索引一个文档,PUT /索引名/类型名/文档id {请求体} -->
    PUT /phone/_doc/1 
    {
      "name" : "xiao mi shou ji",
      "price" : 2998.00,
      "store" : 5000
    }
    ​
    PUT /phone/_doc/2
    {
      "name" : "hua wei shou ji",
      "price" : 3998.00,
      "store" : 8000
    }
    ​
    <!-- 查询索引 -->
    GET /phone/_doc/1
    GET /phone/_doc/2
    ​
    <!-- 返回值内容 -->
    {
      "_index" : "phone", //在哪个索引
      "_type" : "_doc", //在哪个类型
      "_id" : "1", //记录id
      "_version" : 1, //版本号
      "_seq_no" : 0, //并发控制字段,每次更新都会+1,用来做乐观锁
      "_primary_term" : 1, //同上,主分片重新分配,如重启,就会变化
      "found" : true,
      "_source" : {
        "name" : "xiao mi shou ji",
        "price" : 2998.0,
        "store" : 5000
      }
    }
    
  9. 分词器

    在ES中所有的语言分词器,默认使用的都是Standard Analyzer,但是这些分词器针对于中文的分词,并不友好。比如中华人民共和国国歌,不能简单的分成一个一个的词,也不能粗暴的分成中华人民共和国和国歌,而中华人民共和国国歌等都是一个词。因此常见的分词算法就是拿一个标准的词典,关键词都在这个词典里面,然后按照几种规则去查找有没有关键词。为此需要安装中文的分词器。我们可以进行一个测试

    <!-- 使用标准分词器 -->
    GET _analyze
    {
      "analyzer":"standard",
      "text":"中华人民共和国国歌"
    }
    
  10. 下载IK分词器

    ElasticSearch官方自带elasticsearch-analysis-ik分词器,并且支持自定义词典,源代码托管在github上:https://github.com/medcl/elasticsearch-analysis-ik,是ElasticSearch中国社区负责维护的项目,我们可以进行在如下地址进行对应版本的下载,版本一定要和ElasticSearch所匹配

    https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.17.6
    
  11. 安装IK分词器

    在前面安装的启动ElasticSearch容器时,我们已经将ElasticSearch容器的/usr/share/elasticsearch/plugins目录,映射到宿主机的/mydata/es/plugins目录下,所以比较方便的做法就是下载/elasticsearch-analysis-ik-7.17.6.zip文件,然后解压到该文件夹下即可。安装完毕后,需要重启ElasticSearch容器

    #在/mydata/es/plugins/目录下创建ik目录
    cd /mydata/es/plugins
    mkdir ik
    ​
    #将elasticsearch-analysis-ik-7.17.6.zip上传到/mydata/es/plugins/ik目录下,并解压
    cd /mydata/es/plugins/ik
    unzip elasticsearch-analysis-ik-7.17.6.zip
    ​
    #重启ES容器
    docker restart my_es
    
  12. 测试分词器

    在kibana中输入以下测试案例,IK分词安装后有两种分词策略:ik_max_wordik_smart ik_max_word:细力度分割策略

    ik_smart:粗粒度分割策略

    <!-- 细粒度分割策略 -->
    GET _analyze
    {
      "analyzer": "ik_max_word",
      "text": ["中华人民共和国国歌"]
    }
    ​
    <!-- 粗粒度度分割策略 -->
    GET _analyze
    {
      "analyzer": "ik_smart",
      "text": ["中华人民共和国国歌"]
    }