【步驟詳解】Docker一鍵部署微服務(wù)詳細(xì)教程

Docker部署微服務(wù)

場(chǎng)景介紹

我們使用Docker完成一個(gè)微服務(wù)的搭建過程

整體架構(gòu)如下
file

使用多個(gè)微服務(wù)進(jìn)行項(xiàng)目部署測(cè)試

整體服務(wù)說明

我們總共涉及到三個(gè)微服務(wù)以及兩個(gè)中間件

服務(wù)名稱 描述
mysql 數(shù)據(jù)庫(kù)服務(wù)
nacos 注冊(cè)中心
learn-docker-gateway 網(wǎng)關(guān)服務(wù)
learn-docker-web API接口服務(wù)
learn-docker-storage 存儲(chǔ)服務(wù)
配置文件提取

因?yàn)槲覀冊(cè)陂_發(fā)中需要頻繁修改application.yml文件我們將配置項(xiàng)配置到pom文件中打包時(shí)自動(dòng)打到配置文件,這樣可以用一個(gè)pom文件控制多個(gè)不同的服務(wù)的配置文件項(xiàng)的修改

pom文件定義屬性

我們需要在總pom文件定義全局配置,例如nacos、mysql等配置

<properties>
    <mysql.addr>192.168.64.153:3306</mysql.addr>
    <nacos.addr>192.168.64.153:8848</nacos.addr>
</properties>
配置編譯選項(xiàng)

在子項(xiàng)目的pom文件的build構(gòu)建配置中使用<filtering>true</filtering>配置,這樣就可以將我們的總pom中的配置編譯進(jìn)配置文件了

<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>
配置文件配置

在子項(xiàng)目的application.yml配置文件中注意使用@xxx@占位符來配置編譯占位配置,下面的配置就是用了@@占位符編譯后會(huì)將pom中的配置編譯到配置文件中

server:
  port: @project.server.prot@
spring:
  application:
    name: learn-docker-storage
    ######################### 數(shù)據(jù)源連接池的配置信息  #################
  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
編譯測(cè)試

配置完后編譯項(xiàng)目后,可以進(jìn)入target目錄下查看編譯后的配置文件

file

我們看到maven已經(jīng)幫我們將配置編譯進(jìn)了配置文件中了

安裝MySQL

MySQL簡(jiǎn)介
    MySQL 是世界上最受歡迎的開源數(shù)據(jù)庫(kù)。憑借其可靠性、易用性和性能,MySQL 已成為 Web 應(yīng)用程序的數(shù)據(jù)庫(kù)優(yōu)先選擇。
查找MySQL鏡像

我們可以使用 docker search 鏡像名稱,命令來搜索鏡像

docker search mysql
file
參數(shù)解釋

搜索出來的有這么多鏡像,怎么選擇呢

  • NAME: 鏡像倉(cāng)庫(kù)源的名稱

  • DESCRIPTION: 鏡像的描述

  • OFFICIAL: 是否 docker 官方發(fā)布

  • stars: 類似 Github 里面的 star,表示點(diǎn)贊、喜歡的意思。

  • AUTOMATED: 自動(dòng)構(gòu)建。

根據(jù)參數(shù),我們一般選擇 官方發(fā)布的,并且stars多的。

下載鏡像

可以使用docker pull 鏡像名稱來拉取鏡像,我們選擇了第一個(gè)Mysql的鏡像,我們把它給拉取下來

docker pull mysql
file
注意事項(xiàng)
  • 如果不寫版本號(hào)默認(rèn)拉取最新的版本好latest。
  • 拉取的時(shí)候是多個(gè)層一起拉取的,這樣可用讓其他鏡像復(fù)用分層
  • 如果拉取的鏡像不寫倉(cāng)庫(kù)地址默認(rèn)就是docker.io/library/
下載指定版本的鏡像

我們上面下載的鏡像不符合我們的預(yù)期,我們需要Mysql5.7的鏡像

查找指定鏡像

可以登錄 https://hub.docker.com 地址搜索鏡像

file

輸入需要搜索的鏡像名稱,并選擇對(duì)應(yīng)鏡像名稱

file

選擇tag標(biāo)簽,這個(gè)就是版本的信息

file

找到符合的版本 的mysql鏡像,這里我們選擇5.7.33

file
下載指定版本鏡像

剛才我們已經(jīng)找到了5.7.33版本的Mysql的鏡像,我們使用docker pull命令下載,鏡像后面跟的是tag也就是版本名稱

docker pull mysql:5.7.34
file

我們發(fā)現(xiàn),我們的新拉取的mysql鏡像共用了 部分分層

查看鏡像

安裝完鏡像后,我們需要看一下我們的本地鏡像,使用docker images 可用查看本地鏡像

docker images
file

這里有兩個(gè)鏡像,一個(gè)是最新版本的一個(gè)是我們剛才下載的5.7.33版本的

MySQL配置
配置MySQL忽略大小寫

創(chuàng)建MySQL掛載目錄,等會(huì)會(huì)解釋什么是掛載路徑

# 創(chuàng)建MySQL配置的文件夾
mkdir -p /tmp/etc/mysql
# 編輯my.cnf配置文件
vi /tmp/etc/mysql/my.cnf

配置MySQL忽略大小寫,在我們創(chuàng)建的MySQL配置文件掛載點(diǎn)的目錄的my.cnf文件加入如下內(nèi)容

[mysqld]
lower_case_table_names=1
創(chuàng)建MySQL數(shù)據(jù)目錄

因?yàn)槟J(rèn)MySQL啟動(dòng)后他的文件是在容器中的,如果我們刪除容器,數(shù)據(jù)也將會(huì)消失,我們需要將數(shù)據(jù)掛載出來。

#創(chuàng)建mysql存儲(chǔ)的目錄
mkdir -p /tmp/data/mysql
啟動(dòng)MySql

使用docker run啟動(dòng)容器

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
file

到這里MySQL已經(jīng)后臺(tái)運(yùn)行了

參數(shù)解釋
  • -d:是指容器后臺(tái)運(yùn)行,如果不加-d,當(dāng)用戶斷開客戶端時(shí)容器會(huì)結(jié)束運(yùn)行
  • -p:將容器的3306端口映射到主機(jī)的3306端口,用來暴漏端口的
  • -v:這個(gè)命令是用來掛載目錄的,將本地目錄掛載到容器中,這樣容器操作的就是本地目錄
  • -e:這個(gè)命令是配置環(huán)境參數(shù)的,這里MYSQL_ROOT_PASSWORD=root指的是用root用戶運(yùn)行mysql,可以登錄Docker容器通過ENV命令查看
  • --name:這個(gè)命令是配置Mysql的容器名稱的,如果不配置,默認(rèn)是隨機(jī)生成的名字
檢查MySQL運(yùn)行狀態(tài)

現(xiàn)在并不能確認(rèn)MySQL的運(yùn)行狀態(tài),我們需要去看下

查看容器運(yùn)行狀態(tài)

使用docker ps可以看到運(yùn)行中的容器

docker ps

執(zhí)行命令后,我們看到mysql的服務(wù)已經(jīng)起來了

file
查看MySQL運(yùn)行日志

現(xiàn)在MySQL容器起來了,并不代表MySQL已經(jīng)成功啟動(dòng),我們需要使用docker logs命令查看MySQL的日志

docker logs -f mysql

該命令可以查看容器日志-f是追蹤打印日志,可以看到MySQL已經(jīng)啟動(dòng)了

file
客戶端連接MySQL

因?yàn)槲覀円呀?jīng)暴漏端口了,可以使用客戶端工具連接MySQL

file

檢查配置的大小寫參數(shù)是否生效

SHOW VARIABLES LIKE '%case_table%';
file
查看容器掛載的配置文件

可以通過docker exec -ti mysql /bin/bash命令登錄容器,檢查掛載的配置文件情況

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

該命令含義是在mysql容器中以

file

我們可以看到我們修改的配置文件已經(jīng)被掛載到了docker內(nèi)部,這里面用到了exec命令,主要是在deocker容器中運(yùn)行命令,下面我們介紹下

命令格式

主要是在deocker容器中運(yùn)行命令

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

命令參數(shù)

名稱 簡(jiǎn)寫 描述
--detach -d 后臺(tái)運(yùn)行模式,在后臺(tái)執(zhí)行命令相關(guān)命令
--detach-keys 覆蓋容器后臺(tái)運(yùn)行的一些參數(shù)信息
--env -e 設(shè)置環(huán)境變量
--interactive -i 展示容器輸入信息STDIN
--privileged 為命令提供一些擴(kuò)展權(quán)限
--tty -t 命令行交互模式
--user -u 設(shè)置用戶名(format: <name|uid>[:<group|gid>])
--workdir -w 指定容器內(nèi)的目錄
查看掛載的數(shù)據(jù)文件

可以看下掛載的數(shù)據(jù)文件是否存在

cd /tmp/data/mysql/ && ll
file

我們看到數(shù)據(jù)文件已經(jīng)寫入了

MySQL準(zhǔn)備數(shù)據(jù)

MySql需要導(dǎo)入一些數(shù)據(jù)用來操作,我們用MySQL官方提供的數(shù)據(jù)庫(kù)來操作

下載并導(dǎo)入數(shù)據(jù)
下載MySQL測(cè)試數(shù)據(jù)庫(kù)

測(cè)試數(shù)據(jù)官網(wǎng) 下載數(shù)據(jù)庫(kù)文件

file

直接導(dǎo)入無法導(dǎo)入,需要編輯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;
.....
導(dǎo)入測(cè)試數(shù)據(jù)

下載解壓后,在本地執(zhí)行命令導(dǎo)入到mysql服務(wù)器

mysql -uroot -h192.168.64.152 -p < employees.sql
file
客戶端檢查數(shù)據(jù)

在登陸客戶端就能看到數(shù)據(jù)庫(kù)以及表了

file

安裝部署nacos

    Nacos是阿里巴巴開源的一款支持服務(wù)注冊(cè)與發(fā)現(xiàn),配置管理以及微服務(wù)管理的組件。用來取代以前常用的注冊(cè)中心(zookeeper , eureka等等),以及配置中心(spring cloud config等等)。Nacos是集成了注冊(cè)中心和配置中心的功能,做到了二合一。
直接運(yùn)行服務(wù)

可以直接用docker 啟動(dòng)服務(wù),鏡像不存在會(huì)自動(dòng)拉取

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

運(yùn)行容器后可以稍等下,等待nacos啟動(dòng)成功,受環(huán)境限制啟動(dòng)可能有些慢

登錄頁(yè)面測(cè)試

可以登錄服務(wù)器測(cè)試以下

用戶名:nacos 密碼:nacos

file

微服務(wù)打包鏡像

我們準(zhǔn)備將一個(gè)微服務(wù)打包成Docker鏡像,在各種服務(wù)器中進(jìn)行運(yùn)行,改為服務(wù)支持進(jìn)行查詢用戶信息

提前說明

因?yàn)槲覀儎傞_始進(jìn)行學(xué)習(xí)Docker,先從單個(gè)微服務(wù)開始學(xué)習(xí),我們就先部署learn-docker-storage服務(wù),后面隨著課程的深入在慢慢增加其他的微服務(wù)

file
訪問測(cè)試

在idea中運(yùn)行learn-docker-storage,

file

我們配置的端口是8003,我們可以直接訪問http://localhost:8003/storage/employe/findByID/10001

file
打包上傳微服務(wù)

learn-docker-storage服務(wù)打包后上傳到服務(wù)器

注意配置項(xiàng)

這里需要檢查下maven配置的編譯屬性是否正確

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

我們發(fā)現(xiàn)是我們?nèi)萜髦袉?dòng)的地址

上傳打包后的微服務(wù)

將target目錄中打包完成的微服務(wù)上傳到服務(wù)器

file
創(chuàng)建DockerFile

Dockerfile 是一個(gè)用來構(gòu)建鏡像的文本文件,文本內(nèi)容包含了一條條構(gòu)建鏡像所需的指令和說明。

創(chuàng)建一個(gè)Dockerfile文件

vi Dockerfile

具體內(nèi)容如下

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 就是定制需要的基礎(chǔ)鏡像,后續(xù)操作都是基于openjdk

  • VOLUME:掛載一個(gè)數(shù)據(jù)卷,這里因?yàn)闆]有名稱,所以是一個(gè)默認(rèn)的數(shù)據(jù)卷(后面詳細(xì)解釋)

  • ADD:添加一層鏡像到當(dāng)前鏡像,這里就是添加SpringBootTest鏡像到當(dāng)前層,并改名app.jar

  • EXPOSE:暴漏端口,因?yàn)槲覀兊淖约旱亩丝谑?080,所以我們暴漏8080

  • ENTRYPOINT:設(shè)定容器啟動(dòng)時(shí)第一個(gè)運(yùn)行的命令及其參數(shù),這里就是容器以啟動(dòng)就執(zhí)行 java -jar /app.jar

打包鏡像

寫好DockerFile后就需要用docker build命令來構(gòu)建我們的鏡像了,這樣就可以將我們的微服務(wù)打包成一個(gè)鏡像了

構(gòu)建命令格式

構(gòu)建一個(gè)鏡像需要使用以下命令

docker bulid -t 倉(cāng)庫(kù)名/鏡像名:tag .

參數(shù)解釋

  • -t: 鏡像的名字及標(biāo)簽,一般命名規(guī)則是 倉(cāng)庫(kù)名/鏡像名:tag,
    • 倉(cāng)庫(kù)名:一般是私服或者dockerhub等地址,如果忽略默認(rèn)就是dockerhub的地址docker.io.library/
    • 鏡像名稱:就是我們的自己的服務(wù)名稱,可以隨意命名
    • tag:就是我們的版本號(hào)
  • .:這個(gè) . 表示當(dāng)前目錄,這實(shí)際上是在指定上下文的目錄是當(dāng)前目錄,docker build 命令會(huì)將該目錄下的內(nèi)容打包交給 Docker 引擎以幫助構(gòu)建鏡像。
實(shí)戰(zhàn)操作
     一般來說,應(yīng)該會(huì)將 `Dockerfile` 置于一個(gè)空目錄下,或者項(xiàng)目根目錄下,如果該目錄下沒有所需文件,那么應(yīng)該把所需文件復(fù)制一份過來。

     一般大家習(xí)慣性的會(huì)使用默認(rèn)的文件名 `Dockerfile`,以及會(huì)將其置于鏡像構(gòu)建上下文目錄中。

當(dāng)前目錄的結(jié)構(gòu)如下

file
構(gòu)建鏡像

進(jìn)入Dockerfile的目錄,通過如下命令構(gòu)建鏡像

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

構(gòu)建完成如果出現(xiàn)Successfully說明已經(jīng)構(gòu)建成功了,

file
查看我們構(gòu)建的鏡像

使用docker images命令查看我們構(gòu)建完成的鏡像

docker images

我們可以看到我們的鏡像就在第一個(gè)位置

file
運(yùn)行鏡像

剛才已經(jīng)打包完成了鏡像,現(xiàn)在我們運(yùn)行我們自己的鏡像

# 運(yùn)行容器
docker run -d -p 8003:8003 learn-docker-storage:0.0.1
# 查看運(yùn)行中的容器
docker ps
file

參數(shù)最后的learn-docker-storage:0.0.1是鏡像的名稱,如果啟動(dòng)容器可以使用鏡像名稱或者鏡像ID

參數(shù)解釋
  • -d:后臺(tái)運(yùn)行

  • -p:映射端口,將宿主機(jī)的8080端口映射到docker內(nèi)部的8080端口上

查看啟動(dòng)日志

使用docker logs 容器ID來查看啟動(dòng)日志

docker logs -f 74c239792266
file
嘗試訪問服務(wù)

通過curl 命令來訪問服務(wù)

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

我們發(fā)現(xiàn)服務(wù)調(diào)用成功了,我們基本實(shí)現(xiàn)了微服務(wù)改造為docker方式并運(yùn)行

刪除容器

要?jiǎng)h除一個(gè)容器首先需要將一個(gè)容器停止掉

停止容器

我們要把剛才運(yùn)行的容器停止掉,使用docker stop 容器ID 停止一個(gè)容器

docker stop 3752f7088a04
file

停止容器后,我們?cè)谕ㄟ^進(jìn)程查看是看不到容器的,但是容器還是存在我們的服務(wù)中的

查看全部容器

通過docker ps 只能看到運(yùn)行中的容器,但是我們停止的容器是看不到的,可以加上-a 查看所有的容器

docker ps -a
file

我們可以看到 加上-a參數(shù)可以看到剛才已經(jīng)停止掉的容器

啟動(dòng)停止的容器

想要啟動(dòng)一個(gè)停止的容器可以使用docker start 容器ID

docker start 3752f7088a04
file

這樣就把剛才已經(jīng)停止的容器啟動(dòng)了

刪除容器

已經(jīng)停止的容器可以使用docker rm 容器ID刪除容器,但是對(duì)于運(yùn)行中的容器可以加上-f參數(shù)強(qiáng)制刪除

docker rm -f 3752f7088a04
file

這樣可以將一個(gè)運(yùn)行的容器強(qiáng)制刪除,如果停止的容器可以通過通過docker rm刪除

docker rm 3752f7088a04

這個(gè)時(shí)候就把容器給刪除掉了

日志掛載優(yōu)化

存儲(chǔ)卷優(yōu)化
什么是存儲(chǔ)卷

“卷”是容器上的一個(gè)或多個(gè)“目錄”,此類目錄可繞過聯(lián)合文件系統(tǒng)與宿主機(jī)上的某個(gè)目錄“綁定(關(guān)聯(lián))”;

file
    在Docker中,要想實(shí)現(xiàn)數(shù)據(jù)的持久化(所謂Docker的數(shù)據(jù)持久化即**數(shù)據(jù)不隨著Container的結(jié)束而結(jié)束**),需要將數(shù)據(jù)從宿主機(jī)掛載到容器中。

    Docker管理宿主機(jī)文件系統(tǒng)的一部分,默認(rèn)位于 /var/lib/docker/volumes 目錄中;(**最常用的方式**)
存儲(chǔ)卷優(yōu)化寫入速度

Docker鏡像由多個(gè)只讀層疊加而成,啟動(dòng)容器時(shí),docker會(huì)加載只讀鏡像層并在鏡像棧頂部加一個(gè)讀寫層;

file
    如果運(yùn)行中的容器修改了現(xiàn)有的一個(gè)已經(jīng)存在的文件,那該文件將會(huì)從讀寫層下面的只讀層復(fù)制到讀寫層,該文件版本仍然存在,只是已經(jīng)被讀寫層中該文件的副本所隱藏,此即“**寫時(shí)復(fù)制(COW)”機(jī)制**。
file

為了避免這種情況,構(gòu)建Dockerfile的時(shí)候應(yīng)該加入一個(gè)存儲(chǔ)卷

Dockerfile增加存儲(chǔ)卷
增加存儲(chǔ)卷

編寫Dockerfile增加存儲(chǔ)卷,增加日志存儲(chǔ)卷/logs,這會(huì)是一個(gè)匿名存儲(chǔ)卷

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"]
構(gòu)建鏡像

因?yàn)槲覀冊(cè)瓉硪呀?jīng)構(gòu)建了鏡像,這次使用版本號(hào)是 0.0.2

#構(gòu)建鏡像
docker build -t learn-docker-storage:0.0.2 .
# 查看鏡像列表
docker images
file
運(yùn)行容器

通過run命令運(yùn)行容器

# 運(yùn)行容器
docker run -d -p 8003:8003 learn-docker-storage:0.0.2
# 查看運(yùn)行中的容器
docker ps
file
查看存儲(chǔ)卷

通過docker volume ls可以看到存儲(chǔ)卷

docker volume ls
file
查看容器信息

我們發(fā)現(xiàn)都是匿名的存儲(chǔ)卷,如何來確定都是那個(gè)呢,可以通過docker inspect 容器ID來查看存儲(chǔ)新鮮

 docker inspect 2041965c3e87|grep Mounts -A20
file

通過這個(gè)命令可以看到數(shù)據(jù)卷的名稱以及宿主機(jī)的存儲(chǔ)路徑,我們可以直接到宿主機(jī)打印日志

 # 進(jìn)入文件掛載目錄
cd /var/lib/docker/volumes/d35de1b7e4631908b05635db4c1f114ab3aafbdf25a9843c068696e66a779c75/_data
# 輸出日志
tail -f learn-docker-storage.log
file

這樣就看到了我們的日志文件

驗(yàn)證存儲(chǔ)卷

刪除容器檢查存儲(chǔ)卷釋放消失

# 查看運(yùn)行的容器列表
docker ps
#刪除容器
docker rm -f 2041965c3e87
#查看所有的容器列表(運(yùn)行+停止)
docker ps -a
file

我們看到容器已經(jīng)被刪除了,檢查我們的存儲(chǔ)卷

docker volume ls
file

發(fā)現(xiàn)存儲(chǔ)卷還存在,數(shù)據(jù)還是存在的,并且數(shù)據(jù)也存在

# 查看存儲(chǔ)卷列表
docker volume ls
# 查看存儲(chǔ)卷詳情
docker inspect 296ccc64d919e86bb8329bf6b08447c2ea6a118458d3fcb86d5c7c9a3177dfe0
file

重新運(yùn)行鏡像啟動(dòng)一個(gè)新的容器

# 運(yùn)行容器
docker run -d -p 8080:8080 e1222496c69f
# 查看運(yùn)行中的容器
docker ps
file

啟動(dòng)容器后查看存儲(chǔ)卷列表

# 查看存儲(chǔ)卷列表
docker volume ls
file

我們發(fā)現(xiàn)有創(chuàng)建了兩個(gè)存儲(chǔ)卷,查看容器詳情

 docker inspect 2041965c3e87|grep Mounts -A20
file

我們發(fā)現(xiàn)新啟動(dòng)的容器新開了一個(gè)匿名存儲(chǔ)卷

bind掛載共享存儲(chǔ)
什么是bind
    Bind mounts模式和Volumes非常相似,不同點(diǎn)在于Bind mounts模式是將宿主機(jī)上的任意文件或文件夾掛載到容器,而Volumes本質(zhì)上是將Docker服務(wù)管理的一塊區(qū)域(默認(rèn)是/var/lib/docker/volumes下的文件夾)掛載到容器。
共享存儲(chǔ)

經(jīng)過上面的測(cè)試,我們發(fā)現(xiàn)每一個(gè)容器都是單獨(dú)用一個(gè)存儲(chǔ)卷,用于臨時(shí)文件沒有問題的,但是如果要讓容器都用同一個(gè)存儲(chǔ)路徑怎么辦呢,這個(gè)時(shí)候就用到了 bind掛載了,可以使用-v進(jìn)行掛載掛載剛才的存儲(chǔ)卷。

# 級(jí)聯(lián)創(chuàng)建文件夾
mkdir -p /tmp/data/logs
# 運(yùn)行容器,指定掛載路徑 
docker run -d -v /tmp/data/logs:/logs \
-p 8003:8003 --name learn-docker-storage \
learn-docker-storage:0.0.2

這里面--name是指定docker容器的名稱,我們操作容器就可以使用名稱進(jìn)行操作了

file

然后使用docker inspect命令來檢查容器詳情

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

我們發(fā)現(xiàn)掛載日志的掛載方式已經(jīng)變了,由原來的volume變?yōu)榱薭ind,并且掛載路徑變?yōu)榱宋覀冏约憾x的路徑,進(jìn)入目錄查看

# 進(jìn)入目錄并瀏覽目錄文件
cd /tmp/data/logs/&&ll
# 打印日志詳情
tail -f learn-docker-storage.log
file
驗(yàn)證共享存儲(chǔ)

我們也按照上面步驟驗(yàn)證下bind方式掛載的存儲(chǔ),先刪除容器,檢查日志文件是否存在

# 停止并刪除容器
docker rm -f learn-docker-storage
# 查看容器已經(jīng)被刪除了
docker ps -a
# 進(jìn)入日志掛載路徑查看日志是否村咋
cd /tmp/data/logs/&&ll

我們發(fā)現(xiàn)容器被刪除但是日志文件還存在本地

file

啟動(dòng)一個(gè)新的容器

# 運(yùn)行容器,指定掛載路徑 
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

我們發(fā)現(xiàn)新的容器的日志文件追加進(jìn)來了

file

我們發(fā)現(xiàn)日志已經(jīng)追加,我們讓不同的容器掛載同一個(gè)目錄了

volume和bind的區(qū)別

對(duì)于多個(gè)容器需要共享訪問同一數(shù)據(jù)目錄,或者需要持久化容器內(nèi)數(shù)據(jù)(如數(shù)據(jù)庫(kù))時(shí),我們都是采用掛載目錄形式(bind mounts),將宿主機(jī)的某一目錄掛載到容器內(nèi)的指定目錄,這種方式能解決問題,但這種方式也一直有一些缺點(diǎn)

  • 容器在不同的服務(wù)器部署需要根據(jù)實(shí)際磁盤掛載目錄修改路徑
  • 不同操作系統(tǒng)的文件和目錄權(quán)限會(huì)搞得你昏頭轉(zhuǎn)向,火冒三丈 ?
    bind mount和volume其實(shí)都是利用宿主機(jī)的文件系統(tǒng),不同之處在于volume是docker自身管理的目錄中的子目錄,所以不存在權(quán)限引發(fā)的掛載的問題,并且目錄路徑是docker自身管理的,所以也不需要在不同的服務(wù)器上指定不同的路徑,你不需要關(guān)心路徑。
file
清理volume掛載

volume掛載方式,會(huì)生成很多匿名的目錄,我們可以找到對(duì)應(yīng)的沒有使用的volume進(jìn)行刪除

docker volume ls
file

通過查看我們發(fā)現(xiàn)里面,有很多的volume,我們可以找到?jīng)]有用的刪除

 docker volume rm volume_name
file

還可以通過命令將沒有引用的全部volume清除掉,但是這個(gè)命令很危險(xiǎn)

docker volume prune
file

這樣就將我們服務(wù)器上無效的volume清除掉了

網(wǎng)絡(luò)優(yōu)化

Docker網(wǎng)絡(luò)原理
    Docker使用Linux橋接,在宿主機(jī)虛擬一個(gè)Docker容器網(wǎng)橋(docker0),Docker啟動(dòng)一個(gè)容器時(shí)會(huì)根據(jù)Docker網(wǎng)橋的網(wǎng)段分配給容器一個(gè)IP地址,稱為Container-IP,同時(shí)Docker網(wǎng)橋是每個(gè)容器的默認(rèn)網(wǎng)關(guān)。因?yàn)樵谕凰拗鳈C(jī)內(nèi)的容器都接入同一個(gè)網(wǎng)橋,這樣容器之間就能夠通過容器的Container-IP直接通信。

    Docker網(wǎng)橋是宿主機(jī)虛擬出來的,并不是真實(shí)存在的網(wǎng)絡(luò)設(shè)備,外部網(wǎng)絡(luò)是無法尋址到的,這也意味著外部網(wǎng)絡(luò)無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過映射容器端口到宿主主機(jī)(端口映射),即docker run創(chuàng)建容器時(shí)候通過 -p 或 -P 參數(shù)來啟用,訪問容器的時(shí)候就通過[宿主機(jī)IP]:[容器端口]訪問容器。
Docker網(wǎng)絡(luò)模式
Docker網(wǎng)絡(luò)模式 配置 說明
host模式 –net=host 容器和宿主機(jī)共享Network namespace。
container模式 –net=container:NAME_or_ID 容器和另外一個(gè)容器共享Network namespace。 kubernetes中的pod就是多個(gè)容器共享一個(gè)Network namespace。
none模式 –net=none 容器有獨(dú)立的Network namespace,但并沒有對(duì)其進(jìn)行任何網(wǎng)絡(luò)設(shè)置,如分配veth pair 和網(wǎng)橋連接,配置IP等。
overlay模式 -- driver overlay Docker跨主機(jī)通信模式,使用分布式計(jì)算機(jī)架構(gòu)后需要使用overlay網(wǎng)絡(luò)模式
bridge模式 –net=bridge (默認(rèn)為該模式)
host模式
    如果啟動(dòng)容器的時(shí)候使用host模式,那么這個(gè)容器將不會(huì)獲得一個(gè)獨(dú)立的Network Namespace,而是和宿主機(jī)共用一個(gè)Network Namespace。容器將不會(huì)虛擬出自己的網(wǎng)卡,配置自己的IP等,而是使用宿主機(jī)的IP和端口。但是,容器的其他方面,如文件系統(tǒng)、進(jìn)程列表等還是和宿主機(jī)隔離的。

    使用host模式的容器可以直接使用宿主機(jī)的IP地址與外界通信,容器內(nèi)部的服務(wù)端口也可以使用宿主機(jī)的端口,不需要進(jìn)行NAT,host最大的優(yōu)勢(shì)就是網(wǎng)絡(luò)性能比較好,但是docker host上已經(jīng)使用的端口就不能再用了,網(wǎng)絡(luò)的隔離性不好。

Host模式如下圖所示

file
container模式
    這個(gè)模式指定新創(chuàng)建的容器和已經(jīng)存在的一個(gè)容器共享一個(gè) Network Namespace,而不是和宿主機(jī)共享。新創(chuàng)建的容器不會(huì)創(chuàng)建自己的網(wǎng)卡,配置自己的 IP,而是和一個(gè)指定的容器共享 IP、端口范圍等。同樣,兩個(gè)容器除了網(wǎng)絡(luò)方面,其他的如文件系統(tǒng)、進(jìn)程列表等還是隔離的。兩個(gè)容器的進(jìn)程可以通過 lo 網(wǎng)卡設(shè)備通信。

Container模式示意圖

none模式
    使用none模式,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進(jìn)行任何網(wǎng)絡(luò)配置。也就是說,這個(gè)Docker容器沒有網(wǎng)卡、IP、路由等信息。需要我們自己為Docker容器添加網(wǎng)卡、配置IP等。

    這種網(wǎng)絡(luò)模式下容器只有l(wèi)o回環(huán)網(wǎng)絡(luò),沒有其他網(wǎng)卡。none模式可以在容器創(chuàng)建時(shí)通過--network=none來指定。這種類型的網(wǎng)絡(luò)沒有辦法聯(lián)網(wǎng),封閉的網(wǎng)絡(luò)能很好的保證容器的安全性。

None模式示意圖

overlay模式
    容器在兩個(gè)跨主機(jī)進(jìn)行通信的時(shí)候,是使用overlay network這個(gè)網(wǎng)絡(luò)模式進(jìn)行通信,如果使用host也可以實(shí)現(xiàn)跨主機(jī)進(jìn)行通信,直接使用這個(gè)物理的ip地址就可以進(jìn)行通信。overlay它會(huì)虛擬出一個(gè)網(wǎng)絡(luò)比如10.0.9.3這個(gè)ip地址,在這個(gè)overlay網(wǎng)絡(luò)模式里面,有一個(gè)類似于服務(wù)網(wǎng)關(guān)的地址,然后把這個(gè)包轉(zhuǎn)發(fā)到物理服務(wù)器這個(gè)地址,最終通過路由和交換,到達(dá)另一個(gè)服務(wù)器的ip地址。
bridge模式
    當(dāng)Docker進(jìn)程啟動(dòng)時(shí),會(huì)在主機(jī)上創(chuàng)建一個(gè)名為docker0的虛擬網(wǎng)橋,此主機(jī)上啟動(dòng)的Docker容器會(huì)連接到這個(gè)虛擬網(wǎng)橋上。虛擬網(wǎng)橋的工作方式和物理交換機(jī)類似,這樣主機(jī)上的所有容器就通過交換機(jī)連在了一個(gè)二層網(wǎng)絡(luò)中。

    從docker0子網(wǎng)中分配一個(gè)IP給容器使用,并設(shè)置docker0的IP地址為容器的默認(rèn)網(wǎng)關(guān)。在主機(jī)上創(chuàng)建一對(duì)虛擬網(wǎng)卡veth pair設(shè)備,Docker將veth pair設(shè)備的一端放在新創(chuàng)建的容器中,并命名為eth0(容器的網(wǎng)卡),另一端放在主機(jī)中,以vethxxx這樣類似的名字命名,并將這個(gè)網(wǎng)絡(luò)設(shè)備加入到docker0網(wǎng)橋中??梢酝ㄟ^brctl show命令查看。

    bridge模式是docker的默認(rèn)網(wǎng)絡(luò)模式,不寫--net參數(shù),就是bridge模式。使用docker run -p時(shí),docker實(shí)際是在iptables做了DNAT規(guī)則,實(shí)現(xiàn)端口轉(zhuǎn)發(fā)功能。可以使用iptables -t nat -vnL查看。

bridge模式如下圖所示

file
我們的網(wǎng)絡(luò)結(jié)構(gòu)

下圖是我們自己的網(wǎng)絡(luò)結(jié)構(gòu),我們是通過宿主機(jī)訪問Mysql容器的,剛才我們學(xué)過,默認(rèn)Docker已經(jīng)接入了一個(gè)名字叫bridge的橋接網(wǎng)絡(luò)

file

我們可以讓我們的網(wǎng)絡(luò)直接接入橋接網(wǎng)絡(luò),例如下圖

file
創(chuàng)建網(wǎng)絡(luò)
查看網(wǎng)絡(luò)列表

可以通過docker network ls命令查看網(wǎng)絡(luò)列表

# 查看網(wǎng)絡(luò)列表
docker network ls
file

上面就是容器默認(rèn)幾種網(wǎng)絡(luò)

創(chuàng)建一個(gè)橋接網(wǎng)絡(luò)

默認(rèn)容器啟動(dòng)會(huì)自動(dòng)默認(rèn)接入bridge的橋接網(wǎng)絡(luò),為了區(qū)分我們的服務(wù)也防止各種網(wǎng)絡(luò)問題,我們創(chuàng)建一個(gè)專用網(wǎng)絡(luò),可以通過docker network create 網(wǎng)絡(luò)名稱來創(chuàng)建一個(gè)默認(rèn)的橋接網(wǎng)絡(luò)

# 創(chuàng)建一個(gè)橋接網(wǎng)絡(luò)
docker network create learn-docker-network
# 查看網(wǎng)絡(luò)列表
docker network ls
file
服務(wù)接入網(wǎng)絡(luò)
停止并刪除原有容器

停止和刪除我們的微服務(wù)以及mysql服務(wù)

# 刪除當(dāng)前運(yùn)行中的容器
docker rm -f learn-docker-storage nacos mysql
file
創(chuàng)建MySQL

因?yàn)槲覀兊奈⒎?wù)依賴MySQL先啟動(dòng)MySQL并接入網(wǎng)絡(luò),因?yàn)镸ySQL不需要通過宿主機(jī)訪問,所有也不需要映射端口了,--network 是配置接入哪一個(gè)網(wǎng)絡(luò)

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.34
file

這樣我們就把我們的MySQL服務(wù)啟動(dòng)起來了并且加入了learn-docker-network的網(wǎng)絡(luò)

創(chuàng)建Nacos

我們的nacos是需要暴漏端口的,因?yàn)槲覀冃枰獠磕軌蚩吹絥acos頁(yè)面,但是我們也需要我們的nacos連接到當(dāng)前網(wǎng)絡(luò)

docker run -d -p 8848:8848 \
--network=learn-docker-network \
--name nacos --env MODE=standalone \
nacos/nacos-server
file
查看網(wǎng)絡(luò)詳情

可以通過docker network inspect 網(wǎng)絡(luò)名稱可以查看當(dāng)前的網(wǎng)絡(luò)的詳細(xì)信息

docker network inspect learn-docker-network|grep Containers -A 20
file
修改微服務(wù)配置

因?yàn)樾枰褂米远x網(wǎng)絡(luò)訪問mysql容器以及nacos容器,需要修改微服務(wù)數(shù)據(jù)庫(kù)連接地址,

    docker 網(wǎng)絡(luò)訪問 可以通過IP或者通過服務(wù)名稱都是可以的,這里我們通過**服務(wù)名稱訪問**,因?yàn)槲覀兪褂昧薽aven打包的方式,我們只需要將pom文件修改就可以
<properties>
    <mysql.addr>mysql:3306</mysql.addr>
    <nacos.addr>nacos:8848</nacos.addr>
</properties>

修改完成后進(jìn)行編譯項(xiàng)目

file

這里將數(shù)據(jù)庫(kù)連接地址改為mysql容器的服務(wù)名稱mysql,nacos的連接地址變?yōu)榱?code>nacos

重新打包服務(wù)

將打包的文件上傳服務(wù)器后按照上面步驟同上面打包,打包版本為 0.0.3

docker build -t learn-docker-storage:0.0.3 .
file
創(chuàng)建微服務(wù)

下面就按部就班的創(chuàng)建微服務(wù)就可以,只是注意需要加入網(wǎng)絡(luò),這里這個(gè)端口需要映射外網(wǎng)訪問

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
file
測(cè)試微服務(wù)

到現(xiàn)在微服務(wù)已經(jīng)啟動(dòng),我們嘗試訪問以下

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

訪問測(cè)試數(shù)據(jù)沒有問題,到現(xiàn)在我們服務(wù)已經(jīng)搭建完成,并且使用網(wǎng)絡(luò)進(jìn)行了優(yōu)化

本文由育博學(xué)谷狂野架構(gòu)師發(fā)布
如果本文對(duì)您有幫助,歡迎關(guān)注和點(diǎn)贊;如果您有任何建議也可留言評(píng)論或私信,您的支持是我堅(jiān)持創(chuàng)作的動(dòng)力
轉(zhuǎn)載請(qǐng)注明出處!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容