Docker

  • 1. 初识docker
    • 1.1 Docker是什么
      • 了解Docker的前生LXC
      • LXC与docker的关系
      • Docker 的特点
    • 1.2 为什么使用Docker
      • Docker的优势
      • 缺点
      • Docker版本
      • Docker使用场景
    • 1.3 安装docker
      • 卸载旧版本
      • 安装Docker依赖环境
    • 多个版本安装docker
      • 启动 Docker
      • 开启Docker自动补全
    • 1.3 docker架构
      • Docker的组件
      • Docker 基本概念
  • 2 .docker命令
    • 2.1 进程相关命令
      • 2.1.1 启动docker服务
      • 2.1.2 停止docker服务
      • 2.1.3 重启docker服务
      • 2.1.4 查看docker服务状态
      • 2.1.5 开机启动docker服务
    • 2.2 Docker 镜像相关命令
      • 2.2.1 查看镜像
      • 2.2.2 搜索镜像
      • 2.2.3 拉取镜像
      • 2.2.4 删除镜像
    • 2.3 容器相关的命令
      • 2.3.1 查看容器
      • 2.3.2 创建并启动容器
      • 2.3.3 进入容器
      • 2.3.4 停止容器
      • 2.3.5 启动容器
      • 2.3.6 删除容器
      • 2.3. 7 查看容器信息
  • 3 . docker容器的数据卷
    • 3.1 数据卷概念
    • 3.2 存储卷优化写入速度
    • 3.3 Dockerfile增加存储卷
    • 3.4 bind挂载共享存储
    • 3.5 配置数据卷
    • 3.6 配置数据卷容器
    • 3.7 数据卷小结
  • 4. 应用部署
    • 一、部署MySQL
      • 搜索mysql镜像
      • 拉取mysql镜像
      • Mysql配置,启动,准备数据
      • Mysql准备数据
    • 二、部署Tomcat
    • 三、部署Nginx
    • 四、部署Redis
    • 五、安装部署nacos
    • 六、部署微服务
      • 微服务打包镜像
      • 创建DockerFile
      • 打包镜像
  • 5. 网络优化
    • Docker网络原理
    • Docker网络模式
      • host模式
      • container模式
      • none模式
      • overlay模式
      • bridge模式
    • 我们的网络结构
    • 创建网络
  • 5. Docerfile
    • 5.1 Docker 镜像原理(了解)
    • 5.2 镜像制作
      • 5.2.1 容器转为镜像
    • 5.3 Dockerfile 概念
    • 5.4 Dockerfile 案例
      • 需求1:
      • 需求2:
  • 6. 服务编排
  • 6.1 服务编排概念
  • 6.2 Docker Compose 概述
    • 6.2.1 Docker Compose
    • 6.2.2 Docker Compose 安装使用
      • 一、安装Docker Compose
      • 二、卸载Docker Compose
      • 三、 使用docker compose编排nginx+springboot项目
  • 7. Docker 私有仓库
  • 8. 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

安装Docker依赖环境

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

sudo yum install -y yum-utils \device-mapper-persistent-data \lvm2

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

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

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

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

如果提示您接受 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 

多个版本安装docker

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

启动 Docker

systemctl start docker

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

docker run hello-world

运行该代码后首先会从仓库拉取 hello-world 镜像,然后运行该镜像,运行后会输出一个 Hello from Docker!

开启Docker自动补全

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

yum install -y bash-completion

刷新文件

source /usr/share/bash-completion/completions/docker
source /usr/share/bash-completion/bash_completion

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

docker p

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

2.1.2 停止docker服务

systemctl stop docker

2.1.3 重启docker服务

systemctl restart docker

2.1.4 查看docker服务状态

systemctl status docker

2.1.5 开机启动docker服务

systemctl enable docker

2.2 Docker 镜像相关命令

2.2.1 查看镜像

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


REPOSITORY:镜像名称

TAG:镜像标签

IMAGE ID:镜像ID

CREATED:镜像的创建日期

SIZE:镜像大小

2.2.2 搜索镜像

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

NAME:镜像名称

DESCRIPTION:镜像描述

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

OFFICIAL:是否官方

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

2.2.3 拉取镜像

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

docker pull 镜像名称

2.2.4 删除镜像

删除本地镜像

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

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

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

2.3 容器相关的命令

2.3.1 查看容器

docker ps # 查看正在运行的容器
docker ps –a # 查看所有容器,包括正在运行和停止的容器

2.3.2 创建并启动容器

docker run 参数

参数说明:

• -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

2)守护式容器

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

#创建并启动守护式容器
docker run -di --name=mycentos2 centos:7#登录进入容器命令为:docker exec -it container_name (或者 container_id) /bin/bash(exit退出 时,容器不会停止)
docker exec -it mycentos2 /bin/bash

2.3.3 进入容器

docker exec 参数 # 退出容器,容器不会关闭
eg:
docker exec -it mycentos2 /bin/bash

2.3.4 停止容器

docker stop 容器名称或者容器id

2.3.5 启动容器

docker start 容器名称或者容器id

2.3.6 删除容器

#删除指定容器
docker rm 容器名称或者容器id# 删除所有容器:
docker rm `docker ps -a -q`

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

2.3. 7 查看容器信息

docker inspect 容器名称或者容器id

说明:容器之间在一个局域网内,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"]

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

#构建镜像
docker build -t learn-docker-storage:0.0.2 .
# 查看镜像列表
docker images


运行容器
通过run命令运行容器

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


查看存储卷
通过 docker volume ls 可以看到存储卷

docker volume ls


查看容器信息
我们发现都是匿名的存储卷,如何来确定是哪个呢,可以通过 docker inspect 容器ID 来查看存储信息

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


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

# 进入文件挂载目录
[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

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

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


我们看到容器已经被删除了,检查我们的存储卷

docker volume ls


发现存储卷还存在,数据还是存在的,并且数据也存在

# 查看存储卷列表
docker volume ls
# 查看存储卷详情
docker inspect 296ccc64d919e86bb8329bf6b08447c2ea6a118458d3fcb86d5c7c9a3177dfe0


重新运行镜像启动一个新的容器

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


启动容器后查看存储卷列表

# 查看存储卷列表
docker volume ls


我们发现又创建了两个存储卷,查看容器详情

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


我们发现新启动的容器新开了一个匿名存储卷

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

这里面 --name 是指定docker容器的名称,我们操作容器就可以使用名称进行操作了

然后使用 docker inspect 命令来检查容器详情

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


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

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


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

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

我们发现容器被删除但是日志文件还存在本地

启动一个新的容器

# 运行容器,指定挂载路径
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

我们发现新的容器的日志文件追加进来了

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

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

bind mount和volume其实都是利用宿主机的文件系统,不同之处在于volume是docker自身管理的目录中的子目录,所以不存在权限引发的挂载的问题,并且目录路径是docker自身管理的,所以也不需要在不同的服务器上指定不同的路径,你不需要关心路径。

清理volume挂载
volume挂载方式,会生成很多匿名的目录,我们可以找到对应的没有使用的volume进行删除

docker volume ls


通过查看我们发现里面,有很多的volume,我们可以找到没有用的删除

docker volume rm volume_name


还可以通过命令将没有引用的全部volume清除掉,但是这个命令很危险

docker volume prune


这样就将我们服务器上无效的volume清除掉了

3.5 配置数据卷

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

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

注意事项:

  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. 创建启动 c1 c2 容器,使用 –-volumes-from 参数 设置数据卷
docker run –it --name=c1 --volumes-from c3 centos:7 /bin/bashdocker run –it --name=c2 --volumes-from c3 centos:7 /bin/bash

3.7 数据卷小结

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

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

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

4. 应用部署

一、部署MySQL

搜索mysql镜像

docker search mysql


参数解释
搜索出来的有这么多镜像,怎么选择呢

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

拉取mysql镜像

docker pull mysql


注意事项

  • 如果不写版本号默认拉取最新的版本号 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

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

docker images

Mysql配置,启动,准备数据

# 创建MySQL配置的文件夹
mkdir -p /tmp/etc/mysql
# 编辑my.cnf配置文件
vi /tmp/etc/mysql/my.cnf

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

[mysqld]
lower_case_table_names=1

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

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

启动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


到这里MySQL已经后台运行了
参数解释

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

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

docker ps

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

docker logs -f mysql


客户端连接MySQL
因为我们已经暴漏端口了,可以使用客户端工具连接MySQL


检查配置的大小写参数是否生效

SHOW VARIABLES LIKE '%case_table%';


查看容器挂载的配置文件
可以通过 docker exec -ti mysql /bin/bash 命令登录容器,检查挂载的配置文件情况

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


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

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

命令参数

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

cd /tmp/data/mysql/ && ll

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;
.....

导入测试数据
下载解压后,在本地执行命令导入到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)将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


客户端检查数据
在登陆客户端就能看到数据库以及表了

二、部署Tomcat

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

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

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

  1. 使用外部机器访问tomcat

    如果又创建了一个webapps,访问的时候记得加上webapps

三、部署Nginx

  1. 搜索nginx镜像
docker search nginx
  1. 拉取nginx镜像
docker pull nginx
  1. 创建容器,设置端口映射、目录映射
# 在/root目录下创建nginx目录用于存储nginx数据信息
mkdir ~/nginx
cd ~/nginx
mkdir conf
cd conf
# 在~/nginx/conf/下创建nginx.conf文件,粘贴下面内容
vim nginx.conf
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;
}
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
  • 参数说明:

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

五、安装部署nacos

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

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


运行容器后可以稍等下,等待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>

配置编译选项
在子项目的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>

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

server:port: @project.server.port@
spring:application:name: learn-docker-storage######################### 数据源连接池的配置信息  #################datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://@mysql.addr@/employees?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: 123456initialSize: 10minIdle: 20maxActive: 100maxWait: 60000#### nacos 配置#######cloud:nacos:server-addr: @nacos.addr@
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.heima.module.pologging:file:name: ./logs/${spring.application.name}.log

编译测试
配置完编译项目后,可以进入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>

我们发现是我们容器中启动的地址
上传打包后的微服务
将target目录中打包完成的微服务上传到服务器

创建DockerFile

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

vi Dockerfile

具体内容如下

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"]

命令解释

  • 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 .

参数解释

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

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

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

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

构建镜像
进入Dockerfile的目录,通过如下命令构建镜像

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

构建完成如果出现 Successfully 说明已经构建成功了

查看我们构建的镜像
使用 docker images 命令查看我们构建完成的镜像

docker images

我们可以看到我们的镜像就在第一个位置

运行镜像
刚才已经打包完成了镜像,现在我们运行我们自己的镜像

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


参数最后的 learn-docker-storage:0.0.1 是镜像的名称,启动容器也可以使用镜像ID
参数解释

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

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

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

尝试访问服务
通过 curl 命令来访问服务

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


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

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

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

docker ps -a


我们可以看到 加上 -a 参数可以看到刚才已经停止掉的容器
启动停止的容器
想要启动一个停止的容器可以使用 docker start 容器ID

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


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

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


这样可以将一个运行的容器强制删除,而停止的容器可以通过 docker rm 删除

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

这个时候就把容器给删除掉了

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


上面就是容器默认几种网络

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

# 创建一个桥接网络
docker network create learn-docker-network
# 查看网络列表
docker network ls


服务接入网络
停止并删除原有容器
停止和删除我们的微服务以及mysql服务

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


创建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


这样我们就把我们的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


查看网络详情
可以通过 docker network inspect 网络名称 可以查看当前的网络的详细信息

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


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

<properties> <mysql.addr>mysql:3306</mysql.addr> <nacos.addr>nacos:8848</nacos.addr>
</properties>

修改完成后进行编译项目

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

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


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

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


测试微服务
到现在微服务已经启动,我们尝试访问以下

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


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

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. 使用docker save命令可以将已有镜像保存为tar 文件。

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

docker save -o itheima_tomcat:1.0.tar itheima_tomcat:1.0
  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

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

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 .

需求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 .

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

二、卸载Docker Compose

# 二进制包方式安装的,删除二进制文件即可
rm /usr/local/bin/docker-compose

三、 使用docker compose编排nginx+springboot项目

  1. 创建docker-compose目录
mkdir ~/docker-compose
cd ~/docker-compose
  1. 编写 docker-compose.yml 文件
version: '3'
services:nginx:image: nginxports:- 80:80links:- appvolumes:- ./nginx/conf.d:/etc/nginx/conf.dapp:image: appexpose:- "8080"
  1. 创建./nginx/conf.d目录
mkdir -p ./nginx/conf.d
  1. 在./nginx/conf.d目录下 编写itheima.conf文件
server {listen 80;access_log off;location / {proxy_pass http://app:8080;}}
  1. 在~/docker-compose 目录下 使用docker-compose 启动容器
docker-compose up
  1. 测试访问
http://192.168.149.135/hello

7. Docker 私有仓库

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

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

8. Docker相关概念

docker容器虚拟化 与 传统虚拟机比较:

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

  1. Docker容器的数据卷备份与恢复

    1.Docker容器的数据卷备份与恢复 数据卷的备份与恢复 -备份- 注:   -v指定数据卷时,如果数据卷不存在则自动创建. 1.使用nginx基础镜像新启动一个名为nginx的容器,-v指定数据卷 ...

  2. docker学习5--docker数据卷(volume)

    https://blog.csdn.net/dream_broken/article/details/52314993 1.什么是数据卷volume 为了了解什么是Docker Volume,首先我们 ...

  3. docker中的数据卷

    目录 1. 为什么使用数据卷 2. 数据卷基本操作 2.1 创建数据卷 2.2 查看数据卷 2.3 查看数据卷详细信息 2.4 数据卷删除 3. 数据卷的使用 3.1 先创建数据卷再挂载 3.2 直接 ...

  4. Linux中的Docker容器的数据卷

    一.数据卷的概念 1.数据卷是宿主机中的一个目录或者文件 2.当容器目录和数据卷目录绑定后,对方的修改会立即同步 3.一个数据卷可以被多个容器同时挂载 4.一个容器也可以挂载多个数据卷 二.数据卷的作 ...

  5. Docker(二):Docker常用命令之镜像的创建:Dockerfile 与 commit

    相关阅读: Docker(一):Docker的安装与常用命令 Docker(二):Docker常用命令之镜像的创建:Dockerfile 与 commit Docker(三):Docker镜像导入与导 ...

  6. PaddleOCR——Docker环境下基于HubServing模式部署Restful API服务(CPU版本)

    Docker环境下基于HubServing模式部署Restful API服务(CPU版本) 在日常项目应用中,相信大家一般都会希望能通过Docker技术,把PaddleOCR服务打包成一个镜像,以便在 ...

  7. 浅谈Docker:DockerLinux安装,镜像管理命令,镜像制作命令,容器管理命令,数据卷,DockerFile,Docker-compose

    什么是Docker? Docker 概念 • Docker 是一个开源的应用容器引擎 • 诞生于 2013 年初,基于 Go 语言实现, dotCloud 公司出品(后改名为Docker Inc) • ...

  8. docker之容器数据卷

    目录 1.使用volume添加数据卷 2.dockerFile添加数据卷 3.数据卷容器 4.dockerFile解析 4.1dockerfile解析过程 4.2 dockerfile保留关键字 介绍 ...

  9. Docker学习之数据卷操作:Day4

    数据卷基本操作 数据卷定义 数据卷(volume)是一个虚拟目录,指向宿主机文件系统中的某个目录文件. 图解 操作命令语法 docker volume [COMMAND] docker volume命 ...

最新文章

  1. 千万级并发下的 推送系统建设策略解析(一)
  2. 机器人动力学简化模型(Euler-Lagrange equation)
  3. Django Mysql SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
  4. exec 和 call 用法详解
  5. 计算机考到贴吧的试题,2014年全国计算机二级VB上机考试试题七
  6. ubuntu 18.04 vi里面方向键变成abcd 处理办法
  7. Docker学习总结(21)——Docke网络bridge详解
  8. 机器学习实战(九)K-means(K-均值)
  9. http.client.ResponseNotReady: Request-sent
  10. JMeter测试实例
  11. kubernetes 简介:调度器和调度算法((Affinity/Anti-Affinity, Taints and Tolerations, 自定义调度器 )
  12. python人狗大战游戏_6.5 人狗大战.py
  13. Android设置屏幕亮度的两种方式
  14. Sqlmap中文手册
  15. 卸载wps后安装office图标异常的问题
  16. 苹果x和xs买哪个好_苹果12和12pro哪个值得买_苹果12和12pro哪个好
  17. python实现对遥感影像经纬度获取并实现海陆分离
  18. 压网线教程图解(做水晶头)
  19. APP 的开发费用标准是什么?
  20. 【ELM预测】基于粒子群算法PSO优化极限学习机预测含Matlab源码

热门文章

  1. 实现父类一个动物的类, 包括成员变量名字年龄皮毛颜色,带参数构造函数,动物类有一个方法,move,打印动物是可以动的 1.《实现一个子类老鼠的类,继承动物类,老鼠类继承父类成员变量,老鼠还有个自己的属
  2. 艾永亮:超级产品战略实现企业超级增长,五个案例给出最佳答案!
  3. HNUST 辅导上机(模拟)
  4. 川崎机器人here指令_川崎机器人常用编程大法解析——川崎机器人
  5. 上海豪宅现排队买房 半夜12点还在签约
  6. Python|tkinter+matplotlib实现给老铁的生日礼物
  7. 无线运动耳机品牌排行榜前十名,目前最火爆的六款运动耳机推荐
  8. Java 仿QQ空间评论 后台代码实现 一张表
  9. C语言 —— pta寻找孪生素数 (20 分)
  10. C语言编程题:寻找孪生素数(附代码)