跨境互联网 跨境互联网
首页
  • AI 工具

    • 绘图提示词工具 (opens new window)
    • ChatGPT 指令 (opens new window)
  • ChatGPT

    • ChatGP T介绍
    • ChatGPT API 中文开发手册
    • ChatGPT 中文调教指南
    • ChatGPT 开源项目
  • Midjourney

    • Midjourney 文档
  • Stable Diffusion

    • Stable Diffusion 文档
  • 其他

    • AIGC 热门文章
    • 账号合租 (opens new window)
    • 有趣的网站
  • Vue

    • Vue3前置
  • JAVA基础

    • Stream
    • Git
    • Maven
    • 常用第三方类库
    • 性能调优工具
    • UML系统建模
    • 领域驱动设计
    • 敏捷开发
    • Java 测试
    • 代码规范及工具
    • Groovy 编程
  • 并发编程&多线程

    • 并发编程
    • 高性能队列 Disruptor
    • 多线程并发在电商系统下的应用
  • 其他

    • 面试题
  • 消息中间中间件

    • Kafka
    • RabbitMQ
    • RocketMQ
  • 任务调度

    • Quartz
    • XXL-Job
    • Elastic-Job
  • 源码解析

    • Mybatis 高级使用
    • Mybatis 源码剖析
    • Mybatis-Plus
    • Spring Data JPA
    • Spring 高级使用
    • Spring 源码剖析
    • SpringBoot 高级使用
    • SpringBoot 源码剖析
    • Jdk 解析
    • Tomcat 架构设计&源码剖析
    • Tomcat Web应用服务器
    • Zookeeper 高级
    • Netty
  • 微服务框架

    • 分布式原理
    • 分布式集群架构场景化解决方案
    • Dubbo 高级使用
    • Dubbo 核心源码剖析
    • Spring Cloud Gateway
    • Nacos 实战应用
    • Sentinel 实战应用
    • Seata 分布式事务
  • 数据结构和算法的深入应用
  • 存储

    • 图和Neo4j
    • MongoDB
    • TiDB
    • MySQL 优化
    • MySQL 平滑扩容实战
    • MySQL 海量数据存储与优化
    • Elasticsearch
  • 缓存

    • Redis
    • Aerospike
    • Guava Cache
    • Tair
  • 文件存储

    • 阿里云 OSS 云存储
    • FastDF 文件存储
  • 基础

    • Linux 使用
    • Nginx 使用与配置
    • OpenResty 使用
    • LVS+Keepalived 高可用部署
    • Jekins
  • 容器技术

    • Docker
    • K8S
    • K8S
  • 01.全链路(APM)
  • 02.电商终极搜索解决方案
  • 03.电商亿级数据库设计
  • 04.大屏实时计算
  • 05.分库分表的深入实战
  • 06.多维系统下单点登录
  • 07.多服务之间分布式事务
  • 08.业务幂等性技术架构体系
  • 09.高并发下的12306优化
  • 10.每秒100W请求的秒杀架构体系
  • 11.集中化日志管理平台的应用
  • 12.数据中台配置中心
  • 13.每天千万级订单的生成背后痛点及技术突破
  • 14.红包雨的架构设计及源码实现
  • 人工智能

    • Python 笔记
    • Python 工具库
    • 人工智能(AI) 笔记
    • 人工智能(AI) 项目笔记
  • 大数据

    • Flink流处理框架
  • 加密区

    • 机器学习(ML) (opens new window)
    • 深度学习(DL) (opens new window)
    • 自然语言处理(NLP) (opens new window)
AI 导航 (opens new window)

Revin

首页
  • AI 工具

    • 绘图提示词工具 (opens new window)
    • ChatGPT 指令 (opens new window)
  • ChatGPT

    • ChatGP T介绍
    • ChatGPT API 中文开发手册
    • ChatGPT 中文调教指南
    • ChatGPT 开源项目
  • Midjourney

    • Midjourney 文档
  • Stable Diffusion

    • Stable Diffusion 文档
  • 其他

    • AIGC 热门文章
    • 账号合租 (opens new window)
    • 有趣的网站
  • Vue

    • Vue3前置
  • JAVA基础

    • Stream
    • Git
    • Maven
    • 常用第三方类库
    • 性能调优工具
    • UML系统建模
    • 领域驱动设计
    • 敏捷开发
    • Java 测试
    • 代码规范及工具
    • Groovy 编程
  • 并发编程&多线程

    • 并发编程
    • 高性能队列 Disruptor
    • 多线程并发在电商系统下的应用
  • 其他

    • 面试题
  • 消息中间中间件

    • Kafka
    • RabbitMQ
    • RocketMQ
  • 任务调度

    • Quartz
    • XXL-Job
    • Elastic-Job
  • 源码解析

    • Mybatis 高级使用
    • Mybatis 源码剖析
    • Mybatis-Plus
    • Spring Data JPA
    • Spring 高级使用
    • Spring 源码剖析
    • SpringBoot 高级使用
    • SpringBoot 源码剖析
    • Jdk 解析
    • Tomcat 架构设计&源码剖析
    • Tomcat Web应用服务器
    • Zookeeper 高级
    • Netty
  • 微服务框架

    • 分布式原理
    • 分布式集群架构场景化解决方案
    • Dubbo 高级使用
    • Dubbo 核心源码剖析
    • Spring Cloud Gateway
    • Nacos 实战应用
    • Sentinel 实战应用
    • Seata 分布式事务
  • 数据结构和算法的深入应用
  • 存储

    • 图和Neo4j
    • MongoDB
    • TiDB
    • MySQL 优化
    • MySQL 平滑扩容实战
    • MySQL 海量数据存储与优化
    • Elasticsearch
  • 缓存

    • Redis
    • Aerospike
    • Guava Cache
    • Tair
  • 文件存储

    • 阿里云 OSS 云存储
    • FastDF 文件存储
  • 基础

    • Linux 使用
    • Nginx 使用与配置
    • OpenResty 使用
    • LVS+Keepalived 高可用部署
    • Jekins
  • 容器技术

    • Docker
    • K8S
    • K8S
  • 01.全链路(APM)
  • 02.电商终极搜索解决方案
  • 03.电商亿级数据库设计
  • 04.大屏实时计算
  • 05.分库分表的深入实战
  • 06.多维系统下单点登录
  • 07.多服务之间分布式事务
  • 08.业务幂等性技术架构体系
  • 09.高并发下的12306优化
  • 10.每秒100W请求的秒杀架构体系
  • 11.集中化日志管理平台的应用
  • 12.数据中台配置中心
  • 13.每天千万级订单的生成背后痛点及技术突破
  • 14.红包雨的架构设计及源码实现
  • 人工智能

    • Python 笔记
    • Python 工具库
    • 人工智能(AI) 笔记
    • 人工智能(AI) 项目笔记
  • 大数据

    • Flink流处理框架
  • 加密区

    • 机器学习(ML) (opens new window)
    • 深度学习(DL) (opens new window)
    • 自然语言处理(NLP) (opens new window)
AI 导航 (opens new window)
  • Docker

    • 基础使用-Docker是什么
    • 基础使用-为什么使用Docker
    • 基础使用-Docker安装
    • 基础使用-Docker架构
    • 基础使用-Docker部署微服务
      • 1 场景介绍
        • 1.1 整体架构如下
        • 1.2 整体服务说明
        • 1.3 配置文件提取
        • 1.3.1 pom文件定义属性
        • 1.3.2 配置编译选项
        • 1.3.3 配置文件配置
        • 1.3.4 编译测试
      • 2 安装MySQL
        • 2.1 MySQL简介
        • 2.2 查找MySQL镜像
        • 2.2.1 参数解释
        • 2.3 下载镜像
        • 2.3.1 注意事项
        • 2.4 下载指定版本的镜像
        • 2.4.1 查找指定镜像
        • 2.4.2 下载指定版本镜像
        • 2.5 查看镜像
        • 2.6 MySQL配置
        • 2.6.1 配置MySQL忽略大小写
        • 2.6.2 创建MySQL数据目录
        • 2.7 启动MySql
        • 2.7.1 参数解释
        • 2.8 检查MySQL运行状态
        • 2.8.1 查看容器运行状态
        • 2.8.2 查看MySQL运行日志
        • 2.8.3 客户端连接MySQL
        • 2.8.4 查看容器挂载的配置文件
        • 2.8.5 查看挂载的数据文件
      • 3 MySQL准备数据
        • 3.1 下载并导入数据
        • 3.1.1 下载MySQL测试数据库
        • 3.1.2 导入测试数据
        • 3.1.3 客户端检查数据
      • 4 安装部署nacos
        • 4.1 直接运行服务
        • 4.2 登录页面测试
      • 5 微服务打包镜像
        • 5.1 提前说明
        • 5.1.1 访问测试
        • 5.2 打包上传微服务
        • 5.2.1 注意配置项
        • 5.2.2 上传打包后的微服务
        • 5.3 创建DockerFile
        • 5.3.1 命令解释
        • 5.4 打包镜像
        • 5.4.1 构建命令格式
        • 5.4.2 实战操作
        • 5.4.3 构建镜像
        • 5.4.4 查看我们构建的镜像
        • 5.5 运行镜像
        • 5.5.1 参数解释
        • 5.5.2 查看启动日志
        • 5.5.3 尝试访问服务
        • 5.6 删除容器
        • 5.6.1 停止容器
        • 5.6.2 查看全部容器
        • 5.6.3 启动停止的容器
        • 5.6.4 删除容器
      • 6 日志挂载优化
        • 6.1 存储卷优化
        • 6.1.1 什么是存储卷
        • 6.1.2 存储卷优化写入速度
        • 6.2 Dockerfile增加存储卷
        • 6.2.1 增加存储卷
        • 6.2.2 构建镜像
        • 6.2.3 运行容器
        • 6.2.4 查看存储卷
        • 6.2.5 查看容器信息
        • 6.2.6 验证存储卷
        • 6.3 bind挂载共享存储
        • 6.3.1 什么是bind
        • 6.3.2 共享存储
        • 6.3.3 验证共享存储
        • 6.4 volume和bind的区别
        • 6.5 清理volume挂载
      • 7 网络优化
        • 7.1 Docker网络原理
        • 7.2 Docker网络模式
        • 7.2.1 host模式
        • 7.2.2 container模式
        • 7.2.3 none模式
        • 7.2.4 overlay模式
        • 7.2.5 bridge模式
        • 7.3 我们的网络结构
        • 7.4 创建网络
        • 7.4.1 查看网络列表
        • 7.4.2 创建一个桥接网络
        • 7.5 服务接入网络
        • 7.5.1 停止并删除原有容器
        • 7.5.2 创建MySQL
        • 7.5.3 创建Nacos
        • 7.5.4 查看网络详情
        • 7.5.5 修改微服务配置
        • 7.5.6 重新打包服务
        • 7.5.7 创建微服务
        • 7.5.8 测试微服务
    • 集群管理-微服务Docker打包
    • 集群管理-微服务Docker打包
    • 集群管理-任务编排工具
    • 集群管理-docker-compose容器编排
    • 集群管理-Swarm集群编排
    • 集群管理-Docker Stack管理服务
    • 集群管理-portainer使用
    • 补充-Docker
    • 资料
  • k8s

  • k8s

  • Docker容器
  • Docker
Revin
2023-06-19
目录

基础使用-Docker部署微服务

# 1 场景介绍

我们使用Docker完成一个微服务的搭建过程

# 1.1 整体架构如下

image-20210330164125008

使用多个微服务进行项目部署测试

# 1.2 整体服务说明

我们总共涉及到三个微服务以及两个中间件

服务名称 描述
mysql 数据库服务
nacos 注册中心
learn-docker-gateway 网关服务
learn-docker-web API接口服务
learn-docker-storage 存储服务

# 1.3 配置文件提取

因为我们在开发中需要频繁修改application.yml文件我们将配置项配置到pom文件中打包时自动打到配置文件,这样可以用一个pom文件控制多个不同的服务的配置文件项的修改

# 1.3.1 pom文件定义属性

我们需要在总pom文件定义全局配置,例如nacos、mysql等配置

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

# 1.3.2 配置编译选项

在子项目的pom文件的build构建配置中使用<filtering>true</filtering>配置,这样就可以将我们的总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

# 1.3.3 配置文件配置

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

server:
  port: @project.server.prot@
spring:
  application:
    name: learn-docker-storage
    ######################### 数据源连接池的配置信息  #################
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://@db.addr@/employees?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: root
    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.p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 1.3.4 编译测试

配置完后编译项目后,可以进入target目录下查看编译后的配置文件

image-20210330172541492

我们看到maven已经帮我们将配置编译进了配置文件中了

# 2 安装MySQL

# 2.1 MySQL简介

MySQL 是世界上最受欢迎的开源数据库。凭借其可靠性、易用性和性能,MySQL 已成为 Web 应用程序的数据库优先选择。

# 2.2 查找MySQL镜像

我们可以使用 docker search 镜像名称,命令来搜索镜像

docker search mysql
1

image-20210322094230468

# 2.2.1 参数解释

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

  • NAME: 镜像仓库源的名称
  • DESCRIPTION: 镜像的描述
  • OFFICIAL: 是否 docker 官方发布
  • stars: 类似 Github 里面的 star,表示点赞、喜欢的意思。
  • AUTOMATED: 自动构建。

根据参数,我们一般选择 官方发布的,并且stars多的。

# 2.3 下载镜像

可以使用docker pull 镜像名称来拉取镜像,我们选择了第一个Mysql的镜像,我们把它给拉取下来

docker pull mysql
1

image-20210322095808249

# 2.3.1 注意事项

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

# 2.4 下载指定版本的镜像

我们上面下载的镜像不符合我们的预期,我们需要Mysql5.7的镜像

# 2.4.1 查找指定镜像

可以登录 https://hub.docker.com (opens new window) 地址搜索镜像

image-20210322101448076

输入需要搜索的镜像名称,并选择对应镜像名称

image-20210322101448076

选择tag标签,这个就是版本的信息

image-20210322102401667

找到符合的版本 的mysql镜像,这里我们选择5.7.33

image-20210322101841214

# 2.4.2 下载指定版本镜像

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

docker pull mysql:5.7.34
1

image-20210322103000272

我们发现,我们的新拉取的mysql镜像共用了 部分分层

# 2.5 查看镜像

安装完镜像后,我们需要看一下我们的本地镜像,使用docker images 可用查看本地镜像

docker images
1

image-20210322103214738

这里有两个镜像,一个是最新版本的一个是我们刚才下载的5.7.33版本的

# 2.6 MySQL配置

# 2.6.1 配置MySQL忽略大小写

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

# 2.6.2 创建MySQL数据目录

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

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

# 2.7 启动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.38
1

image-20210322111155401

到这里MySQL已经后台运行了

# 2.7.1 参数解释

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

# 2.8 检查MySQL运行状态

现在并不能确认MySQL的运行状态,我们需要去看下

# 2.8.1 查看容器运行状态

使用docker ps可以看到运行中的容器

docker ps
1

执行命令后,我们看到mysql的服务已经起来了

image-20210322111405105

# 2.8.2 查看MySQL运行日志

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

docker logs -f mysql
1

该命令可以查看容器日志-f是追踪打印日志,可以看到MySQL已经启动了

image-20210322111805490

# 2.8.3 客户端连接MySQL

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

image-20210322112915938

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

SHOW VARIABLES LIKE '%case_table%';
1

image-20210322141429097

# 2.8.4 查看容器挂载的配置文件

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

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

该命令含义是在mysql容器中以

image-20210322141833742

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

命令格式

主要是在deocker容器中运行命令

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

命令参数

名称 简写 描述
--detach -d 后台运行模式,在后台执行命令相关命令
--detach-keys 覆盖容器后台运行的一些参数信息
--env -e 设置环境变量
--interactive -i 展示容器输入信息STDIN
--privileged 为命令提供一些扩展权限
--tty -t 命令行交互模式
--user -u 设置用户名(format: <name|uid>[:<group|gid>])
--workdir -w 指定容器内的目录

# 2.8.5 查看挂载的数据文件

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

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

image-20210322144628077

我们看到数据文件已经写入了

# 3 MySQL准备数据

MySql需要导入一些数据用来操作,我们用MySQL官方提供的数据库来操作

# 3.1 下载并导入数据

# 3.1.1 下载MySQL测试数据库

到测试数据官网 (opens new window) 下载数据库文件

image-20210322150224653

直接导入无法导入,需要编辑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
9
10

# 3.1.2 导入测试数据

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

mysql -uroot -h192.168.64.152 -p < employees.sql
1

image-20210322155527043

# 3.1.3 客户端检查数据

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

image-20210322162711652

# 4 安装部署nacos

Nacos是阿里巴巴开源的一款支持服务注册与发现,配置管理以及微服务管理的组件。用来取代以前常用的注册中心(zookeeper , eureka等等),以及配置中心(spring cloud config等等),Nacos是集成了注册中心和配置中心的功能,做到了二合一。

# 4.1 直接运行服务

可以直接用docker 启动服务,镜像不存在会自动拉取

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

image-20210326163324351

运行容器后可以稍等下,等待nacos启动成功,受环境限制启动可能有些慢

# 4.2 登录页面测试

可以登录服务器测试以下

用户名:nacos 密码:nacos

image-20210326163506678

# 5 微服务打包镜像

我们准备将一个微服务打包成Docker镜像,在各种服务器中进行运行,改为服务支持进行查询用户信息

# 5.1 提前说明

因为我们刚开始进行学习Docker,先从单个微服务开始学习,我们就先部署learn-docker-storage服务,后面随着深入在慢慢增加其他的微服务

image-20210330170615713

# 5.1.1 访问测试

在idea中运行learn-docker-storage

image-20210330170523717

我们配置的端口是8003,我们可以直接访问http://localhost:8003/storage/employe/findByID/10001

image-20210330170441026

# 5.2 打包上传微服务

将learn-docker-storage服务打包后上传到服务器

# 5.2.1 注意配置项

这里需要检查下maven配置的编译属性是否正确

<mysql.addr>192.168.64.153:3306</mysql.addr>
<nacos.addr>192.168.64.153:8848</nacos.addr>
1
2

我们发现是我们容器中启动的地址

# 5.2.2 上传打包后的微服务

将target目录中打包完成的微服务上传到服务器

image-20210330173257396

# 5.3 创建DockerFile

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

创建一个Dockerfile文件

vi Dockerfile
1

具体内容如下

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

# 5.3.1 命令解释

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

# 5.4 打包镜像

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

# 5.4.1 构建命令格式

构建一个镜像需要使用以下命令

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

参数解释

  • -t: 镜像的名字及标签,一般命名规则是 仓库名/镜像名:tag,
    • 仓库名:一般是私服或者dockerhub等地址,如果忽略默认就是dockerhub的地址docker.io.library/
    • 镜像名称:就是我们的自己的服务名称,可以随意命名
    • tag:就是我们的版本号
  • .:这个 . 表示当前目录,这实际上是在指定上下文的目录是当前目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。

# 5.4.2 实战操作

一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下,如果该目录下没有所需文件,那么应该把所需文件复制一份过来。

一般大家习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中。

当前目录的结构如下

image-20210330174342022

# 5.4.3 构建镜像

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

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

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

image-20210330175642586

# 5.4.4 查看我们构建的镜像

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

docker images
1

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

image-20210330175848501

# 5.5 运行镜像

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

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

image-20210330182757765

参数最后的learn-docker-storage:0.0.1是镜像的名称,如果启动容器可以使用镜像名称或者镜像ID

# 5.5.1 参数解释

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

# 5.5.2 查看启动日志

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

docker logs -f 74c239792266
1

image-20210330182528508

# 5.5.3 尝试访问服务

通过curl 命令来访问服务

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

image-20210330182857662

我们发现服务调用成功了,我们基本实现了微服务改造为docker方式并运行

# 5.6 删除容器

要删除一个容器首先需要将一个容器停止掉

# 5.6.1 停止容器

我们要把刚才运行的容器停止掉,使用docker stop 容器ID 停止一个容器

docker stop 3752f7088a04
1

image-20210330183450741

停止容器后,我们在通过进程查看是看不到容器的,但是容器还是存在我们的服务中的

# 5.6.2 查看全部容器

通过docker ps 只能看到运行中的容器,但是我们停止的容器是看不到的,可以加上-a 查看所有的容器

docker ps -a
1

image-20210330184014772

我们可以看到 加上-a参数可以看到刚才已经停止掉的容器

# 5.6.3 启动停止的容器

想要启动一个停止的容器可以使用docker start 容器ID

docker start 3752f7088a04
1

image-20210330184223509

这样就把刚才已经停止的容器启动了

# 5.6.4 删除容器

已经停止的容器可以使用docker rm 容器ID删除容器,但是对于运行中的容器可以加上-f参数强制删除

docker rm -f 3752f7088a04
1

image-20210330184601440

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

docker rm 3752f7088a04
1

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

# 6 日志挂载优化

# 6.1 存储卷优化

# 6.1.1 什么是存储卷

“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某个目录“绑定(关联)”;

查看源图像

在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。

Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式)

# 6.1.2 存储卷优化写入速度

Docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层;

img

如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制。

img

为了避免这种情况,构建Dockerfile的时候应该加入一个存储卷

# 6.2 Dockerfile增加存储卷

# 6.2.1 增加存储卷

编写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

# 6.2.2 构建镜像

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

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

image-20210330183149198

# 6.2.3 运行容器

通过run命令运行容器

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

image-20210330184729478

# 6.2.4 查看存储卷

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

docker volume ls
1

image-20210330184859927

# 6.2.5 查看容器信息

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

 docker inspect 2041965c3e87|grep Mounts -A20
1

image-20210323144606732

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

 # 进入文件挂载目录
cd /var/lib/docker/volumes/d35de1b7e4631908b05635db4c1f114ab3aafbdf25a9843c068696e66a779c75/_data
# 输出日志
tail -f learn-docker-storage.log
1
2
3
4

image-20210331092039292

这样就看到了我们的日志文件

# 6.2.6 验证存储卷

删除容器检查存储卷释放消失

# 查看运行的容器列表
docker ps
#删除容器
docker rm -f 2041965c3e87
#查看所有的容器列表(运行+停止)
docker ps -a
1
2
3
4
5
6

image-20210323144943455

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

docker volume ls
1

image-20210323145205811

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

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

image-20210323145336316

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

# 运行容器
docker run -d -p 8080:8080 e1222496c69f
# 查看运行中的容器
docker ps
1
2
3
4

image-20210323145609342

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

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

image-20210323145713442

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

 docker inspect 2041965c3e87|grep Mounts -A20
1

image-20210323145825700

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

# 6.3 bind挂载共享存储

# 6.3.1 什么是bind

Bind mounts模式和Volumes非常相似,不同点在于Bind mounts模式是将宿主机上的任意文件或文件夹挂载到容器,而Volumes本质上是将Docker服务管理的一块区域(默认是/var/lib/docker/volumes下的文件夹)挂载到容器。

# 6.3.2 共享存储

经过上面的测试,我们发现每一个容器都是单独用一个存储卷,用于临时文件没有问题的,但是如果要让容器都用同一个存储路径怎么办呢,这个时候就用到了 bind挂载了,可以使用-v进行挂载挂载刚才的存储卷。

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

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

image-20210331092709632

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

docker inspect learn-docker-storage|grep Mounts -A20
1

image-20210331092755572

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

# 进入目录并浏览目录文件
cd /tmp/data/logs/&&ll
# 打印日志详情
tail -f learn-docker-storage.log
1
2
3
4

image-20210331092934752

# 6.3.3 验证共享存储

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

# 停止并删除容器
docker rm -f learn-docker-storage
# 查看容器已经被删除了
docker ps -a
# 进入日志挂载路径查看日志是否存在
cd /tmp/data/logs/&&ll
1
2
3
4
5
6

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

image-20210331093135450

启动一个新的容器

# 运行容器,指定挂载路径 
docker run -d -v /tmp/data/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

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

image-20210331093506124

我们发现日志已经追加,我们让不同的容器挂载同一个目录了

# 6.4 volume和bind的区别

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

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

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

img

# 6.5 清理volume挂载

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

docker volume ls
1

image-20210323154013322

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

 docker volume rm volume_name
1

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

docker volume prune
1

image-20210323154533881

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

# 7 网络优化

# 7.1 Docker网络原理

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关,因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器,如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

# 7.2 Docker网络模式

Docker网络模式 配置 说明
host模式 –net=host 容器和宿主机共享Network namespace。
container模式 –net=container:NAME_or_ID 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
none模式 –net=none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
overlay模式 -- driver overlay Docker跨主机通信模式,使用分布式计算机架构后需要使用overlay网络模式
bridge模式 –net=bridge (默认为该模式)

# 7.2.1 host模式

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。

容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口,但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

Host模式如下图所示

img

# 7.2.2 container模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享

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

Container模式示意图

Container模式

# 7.2.3 none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置,也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。

这种网络模式下容器只有lo回环网络,没有其他网卡,none模式可以在容器创建时通过--network=none来指定,这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

None模式示意图

None模式

# 7.2.4 overlay模式

img

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

# 7.2.5 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模式如下图所示

img

# 7.3 我们的网络结构

下图是我们自己的网络结构,我们是通过宿主机访问Mysql容器的,刚才我们学过,默认Docker已经接入了一个名字叫bridge的桥接网络

image-20210323160238241

我们可以让我们的网络直接接入桥接网络,例如下图

image-20210323161046989

# 7.4 创建网络

# 7.4.1 查看网络列表

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

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

image-20210323161325109

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

# 7.4.2 创建一个桥接网络

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

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

image-20210331094444582

# 7.5 服务接入网络

# 7.5.1 停止并删除原有容器

停止和删除我们的微服务以及mysql服务

# 删除当前运行中的容器
docker rm -f learn-docker-storage nacos mysql
1
2

image-20210331094550003

# 7.5.2 创建MySQL

因为我们的微服务依赖MySQL先启动MySQL并接入网络,因为MySQL不需要通过宿主机访问,所有也不需要映射端口了,--network 是配置接入哪一个网络

docker run -d \
-v /tmp/etc/mysql:/etc/mysql/mysql.conf.d/ \
-v /tmp/data/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
--name mysql --network=learn-docker-network \
mysql:5.7.38
1
2
3
4
5
6

image-20210331094658659

这样我们就把我们的MySQL服务启动起来了并且加入了learn-docker-network的网络

# 7.5.3 创建Nacos

我们的nacos是需要暴漏端口的,因为我们需要外部能够看到nacos页面,但是我们也需要我们的nacos连接到当前网络

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

image-20210331095039839

# 7.5.4 查看网络详情

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

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

image-20210331095150147

# 7.5.5 修改微服务配置

因为需要使用自定义网络访问mysql容器以及nacos容器,需要修改微服务数据库连接地址,

docker 网络访问 可以通过IP或者通过服务名称都是可以的,这里我们通过服务名称访问,因为我们使用了maven打包的方式,我们只需要将pom文件修改就可以

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

修改完成后进行编译项目

image-20210331100501932

这里将数据库连接地址改为mysql容器的服务名称mysql,nacos的连接地址变为了nacos

# 7.5.6 重新打包服务

将打包的文件上传服务器后按照上面步骤同上面打包,打包版本为 0.0.3

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

image-20210331100826741

# 7.5.7 创建微服务

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

docker run -d \
-v /tmp/data/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

image-20210331101107903

# 7.5.8 测试微服务

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

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

image-20210331101217511

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

上次更新: 2025/04/03, 11:07:08
基础使用-Docker架构
集群管理-微服务Docker打包

← 基础使用-Docker架构 集群管理-微服务Docker打包→

最近更新
01
tailwindcss
03-26
02
PaddleSpeech
02-18
03
whisper
02-18
更多文章>
Theme by Vdoing | Copyright © 2019-2025 跨境互联网 | 豫ICP备14016603号-5 | 豫公网安备41090002410995号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式