当前位置:   article > 正文

Docker 安装 命令 数据卷 应用部署 网络优化 Dockerfile 服务编排Compose 私有仓库_docker 网卡优化

docker 网卡优化

Docker

1. 初识docker

1.1 Docker是什么

Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于Google 公司推出的 Go 语言实现。项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码
GitHub 上进行维护。
Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc,Redhat 已经在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 产品中广泛应用。
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案,Docker 的基础是 Linux 容器(LXC)等技术。

了解Docker的前生LXC

Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源
LXC为Linux Container的简写,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性,相当于C++中的NameSpace,容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。
与传统虚拟化技术相比,它的优势在于:

  • 与宿主机使用同一个内核,性能损耗小;
  • 不需要指令级模拟;
  • 不需要即时(Just-in-time)编译;
  • 容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;
  • 避免了准虚拟化和系统调用替换中的复杂性;
  • 轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享

Linux Container提供了在单一可控主机节点上支持多个相互隔离的server container同时执行的机制。Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源的虚拟化。

LXC与docker的关系

docker并不是LXC替代品,docker底层使用了LXC来实现,LXC将linux进程沙盒化,使得进程之间
相互隔离,在LXC的基础之上,docker提供了一系列更强大的功能。
在这里插入图片描述

Docker 的特点

容器化越来越受欢迎,因为容器是:

  • 灵活:即使是最复杂的应用也可以集装箱化。
  • 轻量级:容器利用并共享主机内核。
  • 可互换:您可以即时部署更新和升级。
  • 便携式:您可以在本地构建,部署到云,并在任何地方运行。
  • 可扩展:您可以增加并自动分发容器副本。
  • 可堆叠:您可以垂直和即时堆叠服务。

1.2 为什么使用Docker

作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
首先,Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。其次,Docker 对
系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。

Docker的优势

具体说来,Docker 在如下几个方面具有较大的优势。

更高效的利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker对系统资源的利用率更高,无论是应用执行速度,内存消耗以及文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而Docker容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级,甚至毫秒级的启动时间,大大的节约了开发,测试,部署的时间。
一致的运行环境
开发过程中一个常见的问题是环境一致性问题,由于开发环境,测试环境,生产环境不一致,导致有些bug并未在开发过程中被发现,而Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性。
持续交付和部署
对于开发和运维人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
在这里插入图片描述
使用Docker可以通过定制应用镜像来实现持续集成,持续交付,部署。开发人员可以通过Dockerfile来进行镜像构建,并结合持续集成系统进行集成测试,而运维人员则可以在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署

更轻松的迁移
由于Docker确保了执行环境的一致性,使得应用的迁移更加容易,Docker可以在很多平台上运行,无论是物理机,虚拟机,公有云,私有云,其运行结果是一致的,因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

缺点

隔离性
基于hypervisor的虚机技术,在隔离性上比容器技术要更好,它们的系统硬件资源完全是虚拟化的,当一台虚机出现系统级别的问题,往往不会蔓延到同一宿主机上的其他虚机。但是容器就不一样了,容器之间共享同一个操作系统内核以及其他组件,所以在收到攻击之类的情况发生时,更容易通过底层操作系统影响到其他容器
性能
不管是虚机还是容器,都是运用不同的技术,对应用本身进行了一定程度的封装和隔离,在降低应用和应用之间以及应用和环境之间的耦合性上做了很多努力,但是随即而来的,就会产生更多的网络连接转发以及数据交互,这在低并发系统上表现不会太明显,而且往往不会成为一个应用的瓶颈(可能会分散于不同的虚机或者服务器上),但是当同一虚机或者服务器下面的容器需要更高并发量支撑的时候,也就是并发问题成为应用瓶颈的时候,容器会将这个问题放大,所以,并不是所有的应用场景都是适用于容器技术的。
存储方案
容器的诞生并不是为OS抽象服务的,这是它和虚机最大的区别,这样的基因意味着容器天生是为应
用环境做更多的努力,容器的伸缩也是基于容器的这一disposable特性,而与之相对的,需要持久化存
储方案恰恰相反。
这一点docker容器提供的解决方案是利用volume接口形成数据的映射和转移,以实现数据持久化的目的。但是这样同样也会造成一部分资源的浪费和更多交互的发生,不管是映射到宿主机上还是到网络磁盘,都是退而求其次的解决方案。

对比传统虚拟机
在这里插入图片描述

Docker版本

随着Docker的不断流行与发展,docker公司(或称为组织)也开启了商业化之路,Docker 从17.03版本之后分为 CE(Community Edition) 和 EE(Enterprise Edition)。我们来看看他们之间的区别与联系。
版本区别
Docker EE
Docker EE由公司支持,可在经过认证的操作系统和云提供商中使用,并可运行来自Docker Store
的、经过认证的容器和插件。
Docker EE提供三个服务层次:
在这里插入图片描述
https://www.docker.com/pricing

Docker CE
Docker CE是免费的Docker产品的新名称,Docker CE包含了完整的Docker平台,非常适合开发人员和运维团队构建容器APP。
Docker公司认为,Docker CE和EE版本的推出为Docker的生命周期、可维护性以及可升级性带来了巨大的改进。
版本说明
在此之前docker的最新版本更新到docker1.13,而在1.13的基础之上,在2017年的3月1号开始,版本的格式变为如下
在这里插入图片描述
小结

  • Docker从17.03开始分为企业版与社区版,社区版并非阉割版,而是改了个名称;企业版则提供了 一些收费的高级特性。
  • EE版本维护期1年;CE的stable版本三个月发布一次,维护期四个月;另外CE还有edge版,一个月发布一次。
Docker使用场景
  1. Web 应用的自动化打包和发布。
  2. 自动化测试和持续集成、发布。
  3. 在服务型环境中部署和调整数据库或其他的后台应用。
  4. 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境

1.3 安装docker

卸载旧版本

较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关
的依赖项。

yum remove docker \
docker-client \ 
docker-client-latest \ 
docker-common \ 
docker-latest \ 
docker-latest-logrotate \ 
docker-logrotate \ 
docker-engine

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
安装Docker依赖环境

在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库,之后,您可以从
仓库安装和更新 Docker。

sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
  • 1
  • 2
  • 3

设置 Docker 安装地址
在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库,之后,您可以从
仓库安装和更新 Docker,使用以下命令来设置稳定的仓库(阿里云)

sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  • 1
  • 2
  • 3

安装 Docker Engine-Community
安装最新版本的 Docker Engine-Community 和 containerd

sudo yum install -y docker-ce docker-ce-cli containerd.io
  • 1

如果提示您接受 GPG 密钥,请选是。
Docker 安装完默认未启动,并且已经创建好 docker 用户组,但该用户组下没有用户。
Docker 镜像加速
阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors,登陆
后,左侧菜单选中镜像加速器就可以看到你的专属地址了:
在这里插入图片描述
配置daemon.json
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker 
sudo tee /etc/docker/daemon.json <<-'EOF' 
{ 
"registry-mirrors": ["https://ffunzkst.mirror.aliyuncs.com"] 
}
EOF 
sudo systemctl daemon-reload 
sudo systemctl restart docker 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

多个版本安装docker

https://www.baiyp.ren/Docker%E5%AE%89%E8%A3%85.html

启动 Docker
systemctl start docker
  • 1

验证docker服务
通过运行 hello-world 镜像来验证是否正确安装了 Docker Engine-Community 。

docker run hello-world
  • 1

运行该代码后首先会从仓库拉取 hello-world 镜像,然后运行该镜像,运行后会输出一个 Hello from Docker!
在这里插入图片描述

开启Docker自动补全

使用docker时无法自动补全镜像名和其他参数,这样使用效率大大降低,下面是解决方法
bash-complete

yum install -y bash-completion
  • 1

刷新文件

source /usr/share/bash-completion/completions/docker 
source /usr/share/bash-completion/bash_completion 
  • 1
  • 2

测试
输入 docker p 后docker会将可选项列出来

docker p
  • 1

在这里插入图片描述

1.3 docker架构

Docker总体架构为c/s架构,模块之间松耦合,包含了Client, Daemon, Registry, Graph, Driver,
Libcontainer以及Docker Container
在这里插入图片描述

Docker的组件
  • Docker Client 是用户界面,它支持用户与 Docker Daemon 之间通信
  • Docker Daemon Docker最核心的后台进程,运行于主机上,处理服务请求
  • Docker Index 是中央registry,支持拥有公有与私有访问权限的Docker容器镜像的备份
  • Docker Containers 负责应用程序的运行,包括操作系统、用户添加的文件以及元数据
  • Docker Images 是一个只读模板,用来运行Docker容器
  • DockerFile 是文件指令集,用来说明如何自动创建Docker镜像
Docker 基本概念

Docker 包括三个基本概念:
镜像
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
分层存储
镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,
由多层文件系统联合组成。
Union FS
联合文件系统(Union FS)是linux的存储技术,也是Docker镜像的存储方式, 它是分层的文件系统,将不同目录拉到同一个虚拟目录下,下图展示了Docker用Union FS 搭建的分层镜像:(比如最下层是操作系统的引导,上一层是Linux操作系统,再上一层是Tomcat,jdk,再上一层是应用代码)
这些层是只读的,加载完后这些文件会被看成是同一个目录,相当于只有一个文件系统。
在这里插入图片描述
我们可以通过docker info查看镜像的一些信息,可以看到存储驱动用的并不是Union FS 而是
overlay2,overlay也是一个联合文件系统
在这里插入图片描述
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。(比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。)

容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜
像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学Docker 时常常会混淆容器和虚拟机。
前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。
容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器
存储层的信息都会随容器删除而丢失。

仓库
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜
像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签
(Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们
可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。(以 Ubuntu 镜像为例,ubuntu是仓库的名字,其内包含有不同的版本标签,如,14.04,16.04。我们可以通过ubuntu:14.04,或者ubuntu:16.04来具体指定所需哪个版本的镜像。如果忽略了标签,比如ubuntu,那将视为ubuntu:latest。)
仓库名经常以三段式路径形式出现,比如 heima.com/nginx-proxy:tag ,前者往往意味着Docker
Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体Docker Registry 的软件或服务

2 .docker命令

2.1 进程相关命令

关于进程相关的命令

2.1.1 启动docker服务
systemctl start docker
  • 1
2.1.2 停止docker服务
systemctl stop docker
  • 1
2.1.3 重启docker服务
systemctl restart docker
  • 1
2.1.4 查看docker服务状态
systemctl status docker
  • 1
2.1.5 开机启动docker服务
systemctl enable docker
  • 1

在这里插入图片描述

2.2 Docker 镜像相关命令

2.2.1 查看镜像
  • 查看本地所有的镜像
docker images
docker images –q # 查看所用镜像的id
  • 1
  • 2

在这里插入图片描述
REPOSITORY:镜像名称

TAG:镜像标签

IMAGE ID:镜像ID

CREATED:镜像的创建日期

SIZE:镜像大小

2.2.2 搜索镜像
  • 从网络中查找需要的镜像
docker search 镜像名称
  • 1

NAME:镜像名称

DESCRIPTION:镜像描述

STARS:用户评价,反应一个镜像的受欢迎程度

OFFICIAL:是否官方

AUTOMATED:自动构建,表示该镜像由Docker Hub自动构建流程创建的

2.2.3 拉取镜像

从Docker仓库下载镜像到本地,镜像名称格式为 名称:版本号,如果版本号不指定则是最新的版本。 如果不知道镜像版本,可以去docker hub 搜索对应镜像查看。

docker pull 镜像名称
  • 1
2.2.4 删除镜像

删除本地镜像

docker rmi 镜像id # 删除指定本地镜像
docker rmi `docker images -q` # 删除所有本地镜像
  • 1
  • 2

关于docker更多命令, 大家可以菜鸟教程查看, 网址:

https://www.runoob.com/docker/docker-command-manual.html

2.3 容器相关的命令

2.3.1 查看容器
docker ps # 查看正在运行的容器
docker ps –a # 查看所有容器,包括正在运行和停止的容器
  • 1
  • 2
2.3.2 创建并启动容器
docker run 参数
  • 1

参数说明:

• -i:保持容器运行。通常与 -t 同时使用。加入it这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。

• -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。

• -d:以守护(后台)模式运行容器。创建一个容器在后台运行,需要使用docker exec 进入容器。退出后,容器不会关闭。

• -it 创建的容器一般称为交互式容器,-id 创建的容器一般称为守护式容器

• --name:为创建的容器命名。

1)交互式容器

交互式方式创建并启动容器,启动完成后,直接进入当前容器。使用exit命令退出容器。需要注意的是以此种方式 启动容器,如果退出容器,则容器会进入停止状态。

# 先拉取一个镜像;这一步不是每次启动容器都要做的,而是因为前面我们删除了镜像,无镜像可用所以才再拉取一个 
docker pull centos:7 

#创建并启动名称为 mycentos7 的交互式容器;下面指令中的镜像名称 centos:7 也可以使用镜像id 
docker run -it --name=mycentos7 centos:7 /bin/bash
  • 1
  • 2
  • 3
  • 4
  • 5

2)守护式容器

创建一个守护式容器;如果对于一个需要长期运行的容器来说,我们可以创建一个守护式容器。命令如下(容器名称 不能重复):

#创建并启动守护式容器
docker run -di --name=mycentos2 centos:7

#登录进入容器命令为:docker exec -it container_name (或者 container_id) /bin/bash(exit退出 时,容器不会停止)
docker exec -it mycentos2 /bin/bash
  • 1
  • 2
  • 3
  • 4
  • 5
2.3.3 进入容器
docker exec 参数 # 退出容器,容器不会关闭
eg: 
docker exec -it mycentos2 /bin/bash
  • 1
  • 2
  • 3
2.3.4 停止容器
docker stop 容器名称或者容器id
  • 1
2.3.5 启动容器
docker start 容器名称或者容器id
  • 1
2.3.6 删除容器
#删除指定容器
docker rm 容器名称或者容器id

# 删除所有容器:
docker rm `docker ps -a -q`

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意:如果容器是运行状态则删除失败,需要停止容器才能删除

2.3. 7 查看容器信息
docker inspect 容器名称或者容器id
  • 1

在这里插入图片描述

说明:容器之间在一个局域网内,linux宿主机器可以与容器进行通信;但是外部的物理机笔记本是不能与容器直接通信的,如果需要则需要通过宿主机器端口的代理。

3 . docker容器的数据卷

3.1 数据卷概念

思考

• Docker 容器删除后,在容器中产生的数据也会随之销毁
• Docker 容器和外部机器可以直接交换文件吗?
• 容器之间想要进行数据交互?

在这里插入图片描述
数据卷
“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某个目录“绑定(关联)”;

  • 数据卷是宿主机中的一个目录或文件
  • 当容器目录和数据卷目录绑定后,对方的修改会立即同步
  • 一个数据卷可以被多个容器同时挂载
  • 一个容器也可以被挂载多个数据卷
    在这里插入图片描述
    在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中
    Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式)

3.2 存储卷优化写入速度

Docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层
在这里插入图片描述
如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即**“写时复制(COW)”机 制**。
在这里插入图片描述
为了避免这种情况,构建Dockerfile的时候应该加入一个存储卷

3.3 Dockerfile增加存储卷

增加存储卷
编写Dockerfile增加存储卷,增加日志存储卷 /logs ,这会是一个匿名存储卷

FROM openjdk:8-jdk-alpine 
VOLUME /tmp /logs 
ADD learn-docker-storage-1.0-SNAPSHOT.jar app.jar 
EXPOSE 8003 
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  • 1
  • 2
  • 3
  • 4
  • 5

构建镜像
因为我们原来已经构建了镜像,这次使用版本号是 0.0.2

#构建镜像 
docker build -t learn-docker-storage:0.0.2 . 
# 查看镜像列表 
docker images
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
运行容器
通过run命令运行容器

# 运行容器 
docker run -d -p 8003:8003 learn-docker-storage:0.0.2 
# 查看运行中的容器 
docker ps 
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
查看存储卷
通过 docker volume ls 可以看到存储卷

docker volume ls
  • 1

在这里插入图片描述
查看容器信息
我们发现都是匿名的存储卷,如何来确定是哪个呢,可以通过 docker inspect 容器ID 来查看存储信息

[root@linux30 docker-learn]# docker inspect 2ff69575338d |grep Mounts -A 20
  • 1

在这里插入图片描述
通过这个命令可以看到数据卷的名称以及宿主机的存储路径,我们可以直接到宿主机打印日志

# 进入文件挂载目录 
[root@linux30 docker-learn]# ls 
/var/lib/docker/volumes/a343b517882f9e248c6f7e9f7e43deb27bb0207cae1f63d0f0b05689 be16a397/_data 
# 输出日志 
[root@linux30 docker-learn]# tail -f 
/var/lib/docker/volumes/a343b517882f9e248c6f7e9f7e43deb27bb0207cae1f63d0f0b05689 be16a397/_data/learn-docker-storage.log
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样就看到了我们的日志文件
验证存储卷
删除容器检查存储卷释放消失

# 查看运行的容器列表 
docker ps 
#删除容器 
[root@linux30 docker-learn]# docker rm -f 2ff69575338d 
#查看所有的容器列表(运行+停止) 
docker ps -a 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
我们看到容器已经被删除了,检查我们的存储卷

docker volume ls
  • 1

在这里插入图片描述
发现存储卷还存在,数据还是存在的,并且数据也存在

# 查看存储卷列表 
docker volume ls 
# 查看存储卷详情 
docker inspect 296ccc64d919e86bb8329bf6b08447c2ea6a118458d3fcb86d5c7c9a3177dfe0
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
重新运行镜像启动一个新的容器

# 运行容器 
[root@linux30 docker-learn]# docker run -d -p 8080:8080 81c753a43b3c 
# 查看运行中的容器 
docker ps
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
启动容器后查看存储卷列表

# 查看存储卷列表 
docker volume ls
  • 1
  • 2

在这里插入图片描述
我们发现又创建了两个存储卷,查看容器详情

[root@linux30 docker-learn]# docker inspect d8f2f27682dd|grep Mounts -A20
  • 1

在这里插入图片描述
我们发现新启动的容器新开了一个匿名存储卷

3.4 bind挂载共享存储

什么是bind
Bind mounts模式和Volumes非常相似,不同点在于Bind mounts模式是将宿主机上的任意文件或文件夹挂载到容器,而Volumes本质上是将Docker服务管理的一块区域(默认是/var/lib/docker/volumes下的文件夹)挂载到容器。
共享存储
经过上面的测试,我们发现每一个容器都是单独用一个存储卷,用于临时文件没有问题的,但是如果要让容器都用同一个存储路径怎么办呢,这个时候就用到了 bind挂载了,可以使用 -v 进行挂载刚才的存储卷。

# 级联创建文件夹 
mkdir -p /opt/docker/logs 
# 运行容器,指定挂载路径 
docker run -d -v /opt/docker/logs:/logs \ 
-p 8003:8003 --name learn-docker-storage \ 
learn-docker-storage:0.0.2 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里面 --name 是指定docker容器的名称,我们操作容器就可以使用名称进行操作了
在这里插入图片描述
然后使用 docker inspect 命令来检查容器详情

[root@linux30 logs]# docker inspect learn-docker-storage|grep Mounts -A20
  • 1

在这里插入图片描述
我们发现挂载日志的挂载方式已经变了,由原来的volume变为了bind,并且挂载路径变为了我们自己定义的路径,进入目录查看

# 进入目录并浏览目录文件 
[root@linux30 logs]# ll /opt/docker/logs 
# 打印日志详情 
[root@linux30 logs]# tail -f /opt/docker/logs/learn-docker-storage.log 
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
验证共享存储
我们也按照上面步骤验证下bind方式挂载的存储,先删除容器,检查日志文件是否存在

# 停止并删除容器 
docker rm -f learn-docker-storage 
# 查看容器已经被删除了 
docker ps -a 
# 进入日志挂载路径查看日志是否存在 
[root@linux30 logs]# ll /opt/docker/logs/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们发现容器被删除但是日志文件还存在本地
在这里插入图片描述
启动一个新的容器

# 运行容器,指定挂载路径 
docker run -d -v /opt/docker/logs:/logs \ 
-p 8003:8003 --name learn-docker-storage \ 
learn-docker-storage:0.0.2 
# 查看日志文件 
cat learn-docker-storage.log
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们发现新的容器的日志文件追加进来了
在这里插入图片描述

volume和bind的区别
对于多个容器需要共享访问同一数据目录,或者需要持久化容器内数据(如数据库)时,我们都是采用挂载目录形式(bind mounts),将宿主机的某一目录挂载到容器内的指定目录,这种方式能解决问题,但这种方式也一直有一些缺点

  • 容器在不同的服务器部署需要根据实际磁盘挂载目录修改路径
  • 不同操作系统的文件和目录权限会搞得你昏头转向

bind mount和volume其实都是利用宿主机的文件系统,不同之处在于volume是docker自身管理的目录中的子目录,所以不存在权限引发的挂载的问题,并且目录路径是docker自身管理的,所以也不需要在不同的服务器上指定不同的路径,你不需要关心路径。
在这里插入图片描述
清理volume挂载
volume挂载方式,会生成很多匿名的目录,我们可以找到对应的没有使用的volume进行删除

docker volume ls
  • 1

在这里插入图片描述
通过查看我们发现里面,有很多的volume,我们可以找到没有用的删除

docker volume rm volume_name
  • 1

在这里插入图片描述
还可以通过命令将没有引用的全部volume清除掉,但是这个命令很危险

docker volume prune
  • 1

在这里插入图片描述
这样就将我们服务器上无效的volume清除掉了

3.5 配置数据卷

创建启动容器时,使用 –v 参数 设置数据卷

docker run ... –v 宿主机目录(文件):容器内目录(文件) ...
  • 1

注意事项:

  1. 目录必须是绝对路径

  2. 如果目录不存在,会自动创建

  3. 一个容器可以挂载多个数据卷

  4. 一个数据卷也可以被多个容器挂载

  5. 两个容器可以挂载同一个容器

在宿主机中实现与容器目录的挂载:

在c1容器中的root目录下就可以看到data_container文件夹:如下图
在这里插入图片描述
同时我们我们回到宿主机中,可以在data文件夹下创建一个文件itcast.txt ,可以发现在容器中也会生成itcast.txt文件:如下图
在这里插入图片描述

  1. 数据卷的持久化:

​ 当我们把c1容器删除后,宿主机中的数据卷依然存在。 所以当我们重新创建一个容器的同时依然可以挂载宿主机中的data文件夹,对应data里的数据依然同步到容器中。

  1. 一个容器可以挂载多个数据卷

在这里插入图片描述
3. 多个容器可以挂载同一个数据卷
在这里插入图片描述
分别创建两个容器,两个容器都挂载宿主机中data目录,当 修改c3容器的data目录c4会实现同步。

从而实现两个容器之间的交互。

3.6 配置数据卷容器

多容器进行数据交换

  1. 多个容器挂载同一个数据卷

  2. 数据卷容器

在这里插入图片描述
步骤:

1.创建启动c3数据卷容器,使用 –v 参数 设置数据卷

docker run –it --name=c3 –v /volume centos:7 /bin/bash
  • 1
  1. 创建启动 c1 c2 容器,使用 –-volumes-from 参数 设置数据卷
docker run –it --name=c1 --volumes-from c3 centos:7 /bin/bash

docker run –it --name=c2 --volumes-from c3 centos:7 /bin/bash
  • 1
  • 2
  • 3

3.7 数据卷小结

  1. 数据卷概念
    •宿主机的一个目录或文件

  2. 数据卷作用
    • 容器数据持久化
    • 客户端和容器数据交换
    • 容器间数据交换

  3. 数据卷容器
    • 创建一个容器,挂载一个目录,让其他容器继承自该容器( --volume-from )。
    • 通过简单方式实现数据卷配置

4. 应用部署

一、部署MySQL

搜索mysql镜像
docker search mysql
  • 1

在这里插入图片描述
参数解释
搜索出来的有这么多镜像,怎么选择呢

  • NAME: 镜像仓库源的名称
  • DESCRIPTION: 镜像的描述
  • OFFICIAL: 是否 docker 官方发布
  • stars: 类似 Github 里面的 star,表示点赞、喜欢的意思。
  • AUTOMATED: 自动构建。
    根据参数,我们一般选择 官方发布的,并且stars多的。
拉取mysql镜像
docker pull mysql
  • 1

在这里插入图片描述
注意事项

  • 如果不写版本号默认拉取最新的版本号 latest 。
  • 拉取的时候是多个层一起拉取的,这样可让其他镜像复用分层
  • 如果拉取的镜像不写仓库地址默认就是 docker.io/library/

下载指定版本的镜像
我们上面下载的镜像不符合我们的预期,我们需要Mysql5.7的镜像
查找指定镜像
可以登录 https://hub.docker.com 地址搜索镜像
在这里插入图片描述
输入需要搜索的镜像名称,并选择对应镜像名称
在这里插入图片描述
选择 tag 标签,这个就是版本的信息
在这里插入图片描述
找到符合的版本 的mysql镜像,这里我们选择 5.7.35
在这里插入图片描述

下载指定版本镜像
刚才我们已经找到了 5.7.35 版本的Mysql的镜像,我们使用 docker pull 命令下载,镜像后面跟
的是tag也就是版本名称

docker pull mysql:5.7.35
  • 1

在这里插入图片描述

我们发现,我们的新拉取的mysql镜像共用了 部分分层
查看镜像
安装完镜像后,我们需要看一下我们的本地镜像,使用 docker images 可用查看本地镜像

docker images
  • 1

在这里插入图片描述

Mysql配置,启动,准备数据
# 创建MySQL配置的文件夹
mkdir -p /tmp/etc/mysql
# 编辑my.cnf配置文件
vi /tmp/etc/mysql/my.cnf
  • 1
  • 2
  • 3
  • 4

配置MySQL忽略大小写,在我们创建的MySQL配置文件挂载的目录的my.cnf文件加入如下内容

[mysqld] 
lower_case_table_names=1
  • 1
  • 2

创建MySQL数据目录
因为默认MySQL启动后他的文件是在容器中的,如果我们删除容器,数据也将会消失,我们需要
将数据挂载出来。

#创建mysql存储的目录
mkdir -p /tmp/data/mysql
  • 1
  • 2

启动MySql
使用 docker run 启动容器

docker run -d -p 3306:3306 -v /tmp/etc/mysql:/etc/mysql/mysql.conf.d/ -v /tmp/data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql mysql:5.7.34
  • 1

在这里插入图片描述
到这里MySQL已经后台运行了
参数解释

  • -d:是指容器后台运行,如果不加 -d ,当用户断开客户端时容器会结束运行
  • -p:将容器的3306端口映射到主机的3306端口,用来暴漏端口的
  • -v:这个命令是用来挂载目录的,将本地目录挂载到容器中,这样容器操作的就是本地目录
  • -e:这个命令是配置环境参数的,这里 MYSQL_ROOT_PASSWORD=123456 指的是用root用户运行mysql,可以登录Docker容器通过 ENV 命令查看
  • –name:这个命令是配置Mysql的容器名称,如果不配置,默认是随机生成的名字

检查MySQL运行状态
现在并不能确认MySQL的运行状态,我们需要去看下
查看容器运行状态
使用 docker ps 可以看到运行中的容器

docker ps
  • 1

在这里插入图片描述

查看MySQL运行日志
现在MySQL容器起来了,并不代表MySQL已经成功启动,我们需要使用 docker logs 命令查看
MySQL的日志

docker logs -f mysql
  • 1

在这里插入图片描述
客户端连接MySQL
因为我们已经暴漏端口了,可以使用客户端工具连接MySQL

在这里插入图片描述
检查配置的大小写参数是否生效

SHOW VARIABLES LIKE '%case_table%';
  • 1

在这里插入图片描述
查看容器挂载的配置文件
可以通过 docker exec -ti mysql /bin/bash 命令登录容器,检查挂载的配置文件情况

# 登录容器 
docker exec -ti mysql /bin/bash
  • 1
  • 2

在这里插入图片描述
我们可以看到我们修改的配置文件已经被挂载到了docker内部,这里面用到了exec命令,主要是
在deocker容器中运行命令,下面我们介绍下
命令格式
主要是在deocker容器中运行命令

docker exec [options] container command [arg...]
  • 1

命令参数
在这里插入图片描述

查看挂载的数据文件
可以看下挂载的数据文件是否存在

cd /tmp/data/mysql/ && ll
  • 1

在这里插入图片描述

Mysql准备数据

MySql需要导入一些数据用来操作,我们用MySQL官方提供的数据库来操作
下载并导入数据
下载MySQL测试数据库
测试数据官网 下载数据库文件
在这里插入图片描述
直接导入无法导入,需要编辑 employees.sql 文件的一些地方

  1. set storage_engine = InnoDB; 修改为: set default_storage_engine = InnoDB;
  2. select CONCAT('storage engine: ', @@storage_engine) as INFO; 修改为: select CONCAT('storage engine: ', @@default_storage_engine) as INFO;
..... 
set default_storage_engine = InnoDB; 
-- set storage_engine = MyISAM; 
-- set storage_engine = Falcon; 
-- set storage_engine = PBXT; 
-- set storage_engine = Maria; 
select CONCAT('storage engine: ',@@default_storage_engine) as INFO; 
..... 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

导入测试数据
下载解压后,在本地执行命令导入到mysql服务器

root@906e80348596:/var/lib/mysql# mysql -uroot -p < employees.sql 
Enter password: 
INFO 
CREATING DATABASE STRUCTURE 
INFO 
storage engine: InnoDB 
INFO 
LOADING departments 
INFO 
LOADING employees 
INFO 
LOADING dept_emp 
INFO 
LOADING dept_manager 
INFO 
LOADING titles 
INFO 
LOADING salaries 
root@906e80348596:/var/lib/mysql# 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
1)将employees_db目录下的sql文件上传到/opt/docker/data/mysql/挂载目录下, 
2)进入docker容器, 
[root@linux30 mysql]# docker exec -it mysql /bin/bash 
3)在/var/lib/mysql目录下执行导入命令 
root@24d27c3d7ae0:/var/lib/mysql# mysql -uroot -p123456 < employees.sql
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
客户端检查数据
在登陆客户端就能看到数据库以及表了

二、部署Tomcat

  1. 搜索tomcat镜像
docker search tomcat
  • 1
  1. 拉取tomcat镜像
docker pull tomcat
  • 1
  1. 创建容器,设置端口映射、目录映射
# 在/root目录下创建tomcat目录用于存储tomcat数据信息
mkdir ~/tomcat
cd ~/tomcat
  • 1
  • 2
  • 3
docker run -id --name=c_tomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat 
  • 1
  • 2
  • 3
  • 4
  • 参数说明:

    • **-p 8080:8080:**将容器的8080端口映射到主机的8080端口

      **-v $PWD:/usr/local/tomcat/webapps:**将主机中当前目录挂载到容器的webapps

  1. 使用外部机器访问tomcat
    在这里插入图片描述
    如果又创建了一个webapps,访问的时候记得加上webapps

三、部署Nginx

  1. 搜索nginx镜像
docker search nginx
  • 1
  1. 拉取nginx镜像
docker pull nginx
  • 1
  1. 创建容器,设置端口映射、目录映射
# 在/root目录下创建nginx目录用于存储nginx数据信息
mkdir ~/nginx
cd ~/nginx
mkdir conf
cd conf
# 在~/nginx/conf/下创建nginx.conf文件,粘贴下面内容
vim nginx.conf
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
docker run -id --name=c_nginx \
-p 80:80 \
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/html:/usr/share/nginx/html \
nginx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 参数说明:
    • -p 80:80:将容器的 80端口映射到宿主机的 80 端口。
    • -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:将主机当前目录下的 /conf/nginx.conf 挂载到容器的 :/etc/nginx/nginx.conf。配置目录
    • -v $PWD/logs:/var/log/nginx:将主机当前目录下的 logs 目录挂载到容器的/var/log/nginx。日志目录
  1. 使用外部机器访问nginx
    在这里插入图片描述

四、部署Redis

  1. 搜索redis镜像
docker search redis
  • 1
  1. 拉取redis镜像
docker pull redis:5.0
  • 1
  1. 创建容器,设置端口映射
docker run -id --name=c_redis -p 6379:6379 redis:5.0
  • 1
  1. 使用外部机器连接redis
./redis-cli.exe -h 192.168.149.135 -p 6379
  • 1

五、安装部署nacos

Nacos是阿里巴巴开源的一款支持服务注册与发现,配置管理以及微服务管理的组件。用来取代以
前常用的注册中心(zookeeper , eureka等等),以及配置中心(spring cloud config等等)。Nacos是集成了注册中心和配置中心的功能,做到了二合一。
直接运行服务
可以直接用docker 启动服务,镜像不存在会自动拉取

docker run -d -p 8848:8848 --name nacos --env MODE=standalone nacos/nacos-server
  • 1

在这里插入图片描述
运行容器后可以稍等下,等待nacos启动成功,受环境限制启动可能有些慢
登录页面测试
可以登录服务器测试一下
用户名:nacos 密码:nacos
在这里插入图片描述

六、部署微服务

场景介绍

我们使用Docker完成一个微服务的搭建过程
整体架构如下在这里插入图片描述
使用多个微服务进行项目部署测试
整体服务说明
我们总共涉及到三个微服务以及两个中间件
在这里插入图片描述
配置文件提取
因为我们在开发中需要频繁修改application.yml 文件,我们将配置项配置到 pom 文件中打包时自动打到配置文件,这样可以用一个 pom 文件控制多个不同的服务的配置文件项的修改
pom文件定义属性
我们需要在总 pom 文件定义全局配置,例如 nacos 、 mysql 等配置

<properties> 
    <mysql.addr>192.168.10.30:3306</mysql.addr> 
    <nacos.addr>192.168.10.30:8848</nacos.addr> 
</properties>
  • 1
  • 2
  • 3
  • 4

配置编译选项
在子项目的pom文件的 build 构建配置中使用 true 配置,这样就可以将我们的总pom中的配置编译进配置文件了

<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
</build>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

配置文件配置
在子项目的 application.yml 配置文件中注意使用 @xxx@ 占位符来配置编译占位配置,下面的配
置就使用了 @@ 占位符,编译后会将pom中的配置编译到配置文件中

server:
  port: @project.server.port@
spring:
  application:
    name: learn-docker-storage
    ######################### 数据源连接池的配置信息  #################
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://@mysql.addr@/employees?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123456
    initialSize: 10
    minIdle: 20
    maxActive: 100
    maxWait: 60000
  #### nacos 配置#######
  cloud:
    nacos:
      server-addr: @nacos.addr@
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.heima.module.po

logging:
  file:
    name: ./logs/${spring.application.name}.log
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

编译测试
配置完编译项目后,可以进入target目录下查看编译后的配置文件
在这里插入图片描述
我们看到maven已经帮我们将配置编译进了配置文件中了

微服务打包镜像

我们准备将一个微服务打包成Docker镜像,在各种服务器中进行运行,改为服务支持进行查询用
户信息
提前说明
因为我们刚开始进行学习Docker,先从单个微服务开始学习,我们就先部署 learn-docker- storage 服务,后面随着课程的深入再慢慢增加其他的微服务
在这里插入图片描述访问测试
在idea中运行 learn-docker-storage ,
在这里插入图片描述
我们配置的端口是8003,我们可以直接访问
http://localhost:8003/storage/employe/findByID/10001
在这里插入图片描述
打包上传微服务
将 learn-docker-storage 服务打包后上传到服务器
注意配置项
这里需要检查下maven配置的编译属性是否正确

<mysql.addr>192.168.10.30:3306</mysql.addr> <nacos.addr>192.168.10.30:8848</nacos.addr>
  • 1

我们发现是我们容器中启动的地址
上传打包后的微服务
将target目录中打包完成的微服务上传到服务器
在这里插入图片描述

创建DockerFile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
创建一个Dockerfile文件

vi Dockerfile
  • 1

具体内容如下

FROM openjdk:8-jdk-alpine 
VOLUME /tmp 
ADD learn-docker-storage-1.0-SNAPSHOT.jar app.jar 
EXPOSE 8003 
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  • 1
  • 2
  • 3
  • 4
  • 5

命令解释

  • FORM:定制的镜像都是基于 FROM 的镜像,这里的 openjdk 就是定制需要的基础镜像,后续操 作都是基于openjdk
  • VOLUME:挂载一个数据卷,这里因为没有名称,所以是一个默认的数据卷(后面详细解释)
  • ADD:添加一层镜像到当前镜像,这里就是添加learn-docker-storage-1.0-SNAPSHOT.jar镜像到
    当前层,并改名app.jar
  • EXPOSE:暴漏端口,因为我们的自己的端口是8003,所以我们暴漏8003
  • ENTRYPOINT:设定容器启动时第一个运行的命令及其参数,这里就是容器一启动就执行 java -jar /app.jar
打包镜像

写好DockerFile后就需要用 docker build 命令来构建我们的镜像了,这样就可以将我们的微服务
打包成一个镜像了
构建命令格式
构建一个镜像需要使用以下命令

docker bulid -t 仓库名/镜像名:tag .
  • 1

参数解释

  • -t: 镜像的名字及标签,一般命名规则是 仓库名/镜像名:tag,

仓库名:一般是私服或者dockerhub等地址,如果忽略默认就是dockerhub的地址docker.io.library/
镜像名称:就是我们的自己的服务名称,可以随意命名
tag:就是我们的版本号

  • .:这个 . 表示当前目录,这实际上是在指定上下文的目录是当前目录, docker build 命令会将

该目录下的内容打包交给 Docker 引擎以帮助构建镜像。
实战操作
一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下,如果该目录下没有所
需文件,那么应该把所需文件复制一份过来。
一般大家习惯性的会使用默认的文件名 Dockerfile ,以及会将其置于镜像构建上下文目录中。
当前目录的结构如下
在这里插入图片描述
构建镜像
进入Dockerfile的目录,通过如下命令构建镜像

docker build -t learn-docker-storage:0.0.1 .
  • 1

构建完成如果出现 Successfully 说明已经构建成功了
在这里插入图片描述
查看我们构建的镜像
使用 docker images 命令查看我们构建完成的镜像

docker images
  • 1

我们可以看到我们的镜像就在第一个位置
在这里插入图片描述
运行镜像
刚才已经打包完成了镜像,现在我们运行我们自己的镜像

# 运行容器 
docker run -d -p 8003:8003 learn-docker-storage:0.0.1 
# 查看运行中的容器 
docker ps 
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
参数最后的 learn-docker-storage:0.0.1 是镜像的名称,启动容器也可以使用镜像ID
参数解释

  • -d:后台运行
  • -p:映射端口,将宿主机的8080端口映射到docker内部的8080端口上

查看启动日志
使用 docker logs 容器ID 来查看启动日志

[root@linux30 docker-learn]# docker logs -f d8b384678684
  • 1

在这里插入图片描述尝试访问服务
通过 curl 命令来访问服务

curl http://192.168.10.30:8003/storage/employe/findByID/10001 | python -m json.tool
  • 1

在这里插入图片描述
我们发现服务调用成功了,我们基本实现了微服务改造为docker方式并运行
删除容器
要删除一个容器首先需要将一个容器停止掉
停止容器
我们要把刚才运行的容器停止掉,使用 docker stop 容器ID 停止一个容器

[root@linux30 docker-learn]# docker stop d8b384678684
  • 1

在这里插入图片描述停止容器后,我们再通过进程查看是看不到容器的,但是容器还是存在我们的服务中
查看全部容器
通过 docker ps 只能看到运行中的容器,但是我们停止的容器是看不到的,可以加上 -a 查看所有的容器

docker ps -a
  • 1

在这里插入图片描述
我们可以看到 加上 -a 参数可以看到刚才已经停止掉的容器
启动停止的容器
想要启动一个停止的容器可以使用 docker start 容器ID

[root@linux30 docker-learn]# docker start d8b384678684
  • 1

在这里插入图片描述
这样就把刚才已经停止的容器启动了
删除容器
已经停止的容器可以使用 docker rm 容器ID 删除容器,但是对于运行中的容器可以加上 -f 参数
强制删除

[root@linux30 docker-learn]# docker rm -f d8b384678684
  • 1

在这里插入图片描述
这样可以将一个运行的容器强制删除,而停止的容器可以通过 docker rm 删除

[root@linux30 docker-learn]# docker rm 7de77a6f9c22
  • 1

这个时候就把容器给删除掉了
在这里插入图片描述

5. 网络优化

Docker网络原理

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

Docker网络模式

在这里插入图片描述

host模式

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性好。

HostHost模式如下图所示
在这里插入图片描述

container模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以
通过 lo 网卡设备通信。

Container模式示意图
在这里插入图片描述

none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

None模式示意图
在这里插入图片描述

overlay模式

在这里插入图片描述
容器在两个跨主机进行通信的时候,是使用overlay network这个网络模式进行通信,如果使用host也可以实现跨主机进行通信,直接使用这个物理的ip地址就可以进行通信。overlay它会虚拟出一个网络比如10.0.9.3这个ip地址,在这个overlay网络模式里面,有一个类似于服务网关的地址,然后把这个包转发到物理服务器这个地址,最终通过路由和交换,到达另一个服务器的ip地址

bridge模式

当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用 iptables -t nat -vnL查看。
bridge模式如下图所示
在这里插入图片描述

我们的网络结构

下图是我们自己的网络结构,我们是通过宿主机访问Mysql容器的,刚才我们学过,默认Docker已经接入了一个名字叫 bridge 的桥接网络
在这里插入图片描述
我们可以让我们的网络直接接入桥接网络,例如下图
在这里插入图片描述

创建网络

查看网络列表
可以通过 docker network ls 命令查看网络列表

# 查看网络列表 
docker network ls
  • 1
  • 2

在这里插入图片描述
上面就是容器默认几种网络

创建一个桥接网络
默认容器启动会自动默认接入 bridge 的桥接网络,为了区分我们的服务也防止各种网络问题,我们创建一个专用网络,可以通过 docker network create 网络名称 来创建一个默认的桥接网络

# 创建一个桥接网络 
docker network create learn-docker-network 
# 查看网络列表 
docker network ls
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
服务接入网络
停止并删除原有容器
停止和删除我们的微服务以及mysql服务

# 删除当前运行中的容器 
[root@linux30 docker]# docker rm -f learn-docker-storage nacos mysql intelligent_cray
  • 1
  • 2

在这里插入图片描述
创建MySQL
因为我们的微服务依赖MySQL先启动MySQL并接入网络,因为MySQL不需要通过宿主机访问,所有也不需要映射端口了,–network 是配置接入哪一个网络

docker run -d \ 
-v /opt/docker/etc/mysql:/etc/mysql/mysql.conf.d/ \ 
-v /opt/docker/data/mysql:/var/lib/mysql \ 
-e MYSQL_ROOT_PASSWORD=123456 \ 
--name mysql --network=learn-docker-network \ 
mysql:5.7.35
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
这样我们就把我们的MySQL服务启动起来了并且加入了learn-docker-network的网络
创建Nacos
我们的nacos是需要暴漏端口的,因为我们需要外部能够看到nacos页面,但是我们也需要我们的nacos连接到当前网络

docker run -d -p 8848:8848 \ 
--network=learn-docker-network \ 
--name nacos --env MODE=standalone \ 
nacos/nacos-server 
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
查看网络详情
可以通过 docker network inspect 网络名称 可以查看当前的网络的详细信息

docker network inspect learn-docker-network|grep Containers -A 20
  • 1

在这里插入图片描述
修改微服务配置
因为需要使用自定义网络访问mysql容器以及nacos容器,需要修改微服务数据库连接地址,
docker 网络访问 可以通过IP或者通过服务名称都是可以的,这里我们通过服务名称访问,因为我们使用了maven打包的方式,我们只需要将pom文件修改就可以

<properties> 
    <mysql.addr>mysql:3306</mysql.addr> 
    <nacos.addr>nacos:8848</nacos.addr> 
</properties> 
  • 1
  • 2
  • 3
  • 4

修改完成后进行编译项目

这里将数据库连接地址改为mysql容器的服务名称 mysql ,nacos的连接地址变为了 nacos
重新打包服务
将打包的文件上传服务器后按照上面步骤同上面打包,打包版本为 0.0.3

docker build -t learn-docker-storage:0.0.3 .
  • 1

在这里插入图片描述
创建微服务
下面就按部就班的创建微服务就可以,只是注意需要加入网络,这里这个端口需要映射外网访问

docker run -d \ 
-v /opt/docker/logs:/logs \ 
-p 8003:8003 \ 
--name learn-docker-storage \ 
--network=learn-docker-network \ 
learn-docker-storage:0.0.3 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
测试微服务
到现在微服务已经启动,我们尝试访问以下

curl http://192.168.10.30:8003/storage/employe/findByID/10001 | python -m json.tool
  • 1

在这里插入图片描述
访问测试数据没有问题,到现在我们服务已经搭建完成,并且使用网络进行了优化

5. Docerfile

前面的课程中已经知道了,要获得镜像,可以从Docker仓库中进行下载。那如果我们想自己开发一个镜像,那该如 何做呢?答案是:Dockerfifile

Dockerfifile其实就是一个文本文件,由一系列命令和参数构成,Docker可以读取Dockerfifile文件并根据Dockerfifile文 件的描述来构建镜像。

5.1 Docker 镜像原理(了解)

思考:

  1. Docker 镜像本质是什么?
    是一个分层文件系统

  2. Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G? ?

    Centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层

  3. Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB? ?

由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的
tomcat镜像大小500多MB
在这里插入图片描述

在这里插入图片描述

5.2 镜像制作

在这里插入图片描述

5.2.1 容器转为镜像
  1. 使用docker commit命令可以将容器保存为镜像。

命令形式:docker commit 容器名称 镜像名称

eg:
docker commit 381827f60f70 itheima_tomcat:1.0
  • 1
  • 2
  1. 使用docker save命令可以将已有镜像保存为tar 文件。

命令形式:docker save –o tar文件名 镜像名

docker save -o itheima_tomcat:1.0.tar itheima_tomcat:1.0
  • 1
  1. 使用docker load命令可以根据tar文件恢复为docker镜像。

命令形式:docker load -i tar文件名

# 加载恢复镜像
docker load -i itheima_tomcat.tar 
# 在镜像恢复之后,基于该镜像再次创建启动容器 
docker run -di --name=new_tomcat -p 8080:8080 itheima_tomcat:1.0
  • 1
  • 2
  • 3
  • 4

注意:新的镜像制作后,原本容器中挂载的目录将失效, 索引一般在恢复镜像创建容器容器的时候需要重新挂载。

5.3 Dockerfile 概念

  • Dockerfile 是一个文本文件
  • 包含了一条条的指令
  • 每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像
  • 对于开发人员:可以为开发团队提供一个完全一致的开发环境
  • 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件
    构建一个新的镜像开始工作了
  • 对于运维人员:在部署时,可以实现应用的无缝移植

Dochub网址:https://hub.docker.com

在这里插入图片描述
关键字:

关键字作用备注
FROM指定父镜像指定dockerfile基于哪个image构建
MAINTAINER作者信息用来标明这个dockerfile谁写的
LABEL标签用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看
RUN执行命令执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN [“command” , “param1”,“param2”]
CMD容器启动命令提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD [“command” , “param1”,“param2”]
ENTRYPOINT入口一般在制作一些执行就关闭的容器中会使用
COPY复制文件build的时候复制文件到image中
ADD添加文件build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务
ENV环境变量指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value
ARG构建参数构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数
VOLUME定义外部可以挂载的数据卷指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME [“目录”]
EXPOSE暴露端口定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp
WORKDIR工作目录指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径
USER指定执行用户指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户
HEALTHCHECK健康检查指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制
ONBUILD触发器当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大
STOPSIGNAL发送信号量到宿主机该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。
SHELL指定执行脚本的shell指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell

5.4 Dockerfile 案例

需求1:

自定义centos7镜像。要求:

  1. 默认登录路径为 /usr
  2. 可以使用vim

实现步骤

① 定义父镜像:FROM centos:7

② 定义作者信息:MAINTAINER itheima itheima@itcast.cn

③ 执行安装vim命令: RUN yum install -y vim

④ 定义默认的工作目录:WORKDIR /usr

⑤ 定义容器启动执行的命令:CMD /bin/bash

⑥ 通过dockerfile构建镜像:docker bulid –f dockerfile文件路径 –t 镜像名称:版本

Dockerfile文件:
在这里插入图片描述
文件编写完成执行命令构建:

docker build -f ./centos_dockerfile -t itheima_centos:1 .
  • 1
需求2:

定义dockerfile,发布springboot项目

实现步骤

​ ① 定义父镜像:FROM java:8

​ ② 定义作者信息:MAINTAINER itheima itheima@itcast.cn

​ ③ 将jar包添加到容器: ADD springboot.jar app.jar

​ ④ 定义容器启动执行的命令:CMD java–jar app.jar

​ ⑤ 通过dockerfile构建镜像:docker bulid –f dockerfile文件路径 –t 镜像名称:版本

在这里插入图片描述
文件编写完成执行命令构建:

docker build -f ./springboot_dockerfile -t app .
  • 1

6. 服务编排

6.1 服务编排概念

微服务架构的应用系统中一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,维护的工作量会很大。

  • 要从Dockerfile build image 或者去dockerhub拉取image
  • 要创建多个container
  • 要管理这些container(启动停止删除)
  • 服务编排: 按照一定的业务规则批量管理容器

6.2 Docker Compose 概述

6.2.1 Docker Compose

Docker Compose是一个编排多容器分布式部署的工具,提供命令集管理容器化应用的完整开发周期,包括服务构建 ,启动和停止。使用步骤:

  1. 利用 Dockerfile 定义运行环境镜像

  2. 使用 docker-compose.yml 定义组成应用的各服务

  3. 运行 docker-compose up 启动应用
    在这里插入图片描述

6.2.2 Docker Compose 安装使用

一、安装Docker Compose
# Compose目前已经完全支持Linux、Mac OS和Windows,在我们安装Compose之前,需要先安装Docker。下面我 们以编译好的二进制包方式安装在Linux系统中。 
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 设置文件可执行权限 
chmod +x /usr/local/bin/docker-compose
# 查看版本信息 
docker-compose -version
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
二、卸载Docker Compose
# 二进制包方式安装的,删除二进制文件即可
rm /usr/local/bin/docker-compose
  • 1
  • 2
三、 使用docker compose编排nginx+springboot项目
  1. 创建docker-compose目录
mkdir ~/docker-compose
cd ~/docker-compose
  • 1
  • 2
  1. 编写 docker-compose.yml 文件
version: '3'
services:
  nginx:
   image: nginx
   ports:
    - 80:80
   links:
    - app
   volumes:
    - ./nginx/conf.d:/etc/nginx/conf.d
  app:
    image: app
    expose:
      - "8080"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 创建./nginx/conf.d目录
mkdir -p ./nginx/conf.d
  • 1
  1. 在./nginx/conf.d目录下 编写itheima.conf文件
server {
    listen 80;
    access_log off;

    location / {
        proxy_pass http://app:8080;
    }
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 在~/docker-compose 目录下 使用docker-compose 启动容器
docker-compose up
  • 1
  1. 测试访问
http://192.168.149.135/hello
  • 1

7. Docker 私有仓库

Docker官方的Docker hub(https://hub.docker.com)是一个用于管理公共镜像的仓库,我们可以从上面拉取镜像 到本地,也可以把我们自己的镜像推送上去。但是,有时候我们的服务器无法访问互联网,或者你不希望将自己的镜 像放到公网当中,那么我们就需要搭建自己的私有仓库来存储和管理自己的镜像。

搭建参考《docker 私有仓库.md》

8. Docker相关概念

docker容器虚拟化 与 传统虚拟机比较:
在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/512661
推荐阅读
相关标签
  

闽ICP备14008679号