Docker進階篇


查看docker教學視頻,請點擊 《狂神說java》: https://www.bilibili.com/video/BV1og4y1q7M4?p=1 記得投幣三連呀~~

容器數據卷

什么是容器數據卷

docker的理念回顧

將應用和環境打包成一個鏡像!

數據?如果數據都在容器中,那么我們容器刪除,數據就會丟失!需求:數據可以持久化

MySQL,容器刪除了,刪庫跑路!需求:MySQL數據可以存儲在本地!

容器之間可以有一個數據共享的技術!Docker容器中產生的數據,同步到本地!

這就是卷技術!目錄的掛載,將我們容器內的目錄,掛載到Linux上面!

總結一句話:容器的持久化和同步操作!容器間也是可以數據共享的!

使用數據卷

方式一:直接使用命令來掛載

docker run -it -v 主機目錄:容器目錄

# 測試
[root@localhost home]# docker run -it -v /home/ceshi:/home  centos  /bin/bash

# 啟動起來的時候,我們可以通過docker inspect 容器id 來查看掛載情況:(見下圖)

測試文件的同步

在容器內指定目錄下添加或修改一個文件,會同步到主機指定目錄下!反之,在主機目錄下做相關操作,也會同步到容器對應的目錄下!

再來測試!

1、停止容器

2、宿主機修改文件

3、啟動容器

4、容器內的數據依舊是同步的!

好處:我們以后修改只需要在本地修改即可,容器內會自動同步!

實戰:安裝MySQL

思考:MySQL的數據持久化的問題!

# 獲取鏡像
[root@localhost home]# docker pull mysql:5.7

# 運行容器,需要做數據掛載! # 安裝mysql,需要配置密碼,這是要注意的點!
# 官方測試:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 啟動我們的MySQL容器
-d	后台運行
-p	端口映射
-v	卷掛載
-e  環境配置
--name  容器名字
[root@localhost home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

# 啟動成功之后,我們在本地使用sqlyog 連接測試一下
# sqlyog —— 連接到服務器的3310 —— 3310和容器內的3306映射,這個時候我們就可以連接上了!

# 本地測試創建一個數據庫,查看一下我們的映射的路徑是否ok!

假設我們將容器刪除

發現,我們掛載到本地的數據卷依舊沒有丟失,這就實現了容器數據持久化功能!

具名和匿名掛載

# 匿名掛載
-v 容器內路徑
docker run -d -P --name nginx01 -v /etc/nginx nginx


# 查看所有卷的情況
[root@localhost data]# docker volume ls
DRIVER              VOLUME NAME
local               2dd0379216c9ee4441ed56f8ce53461c19abe78b8cfd024ac5fbe07c3b8f09ba

# 這里發現,這種就是匿名掛載,我們在 -v 后只寫了容器內的路徑,沒有寫容器外的路徑!

# 具名掛載
[root@localhost home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
5ba5708389bf71b2156fdbcedc50a62b16ac27adb2a3dfac42c52e9da5ace79f
[root@localhost home]# docker volume ls
DRIVER              VOLUME NAME
local               juming-nginx

# 通過 -v 卷名:容器內路徑
# 查看一下這個卷  # 先找到卷所在路徑 docker volume inspect 卷名,如下圖:

所有的docker容器內的卷,沒有指定目錄的情況下都是在/var/lib/docker/volumes/xxxx/_data下!
我們通過具名掛載可以方便的找到我們的一個卷,大多數情況使用 具名掛載

# 如何確定是具名掛載還是匿名掛載,還是指定路徑掛載!
-v	容器內路徑		       # 匿名掛載
-v	卷名:容器內路徑	 	 # 具名掛載
-v	/宿主機路徑:容器內路徑   # 指定路徑掛載!

拓展:

# 通過 -v 容器內路徑:ro 或 rw   改變讀寫權限
ro	 #readonly 只讀
rw	 #readwrite 可讀可寫

# 一旦創建容器時設置了容器權限,容器對我們掛載出來的內容就有限定了!
docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx

# 默認是 rw
# ro 只要看到ro就說明這個路徑只能通過宿主機來操作,容器內部是無法操作!

初始Dockerfile

Dockerfile 就是用來構建 docker鏡像的構建文件!命令腳本! 先體驗一下!

通過這個腳本可以生成鏡像,鏡像是一層一層的,腳本是一個個的命令,每個命令都是最終鏡像的一層!

# 創建一個dockerfile文件,名字可以隨機,建議 dockerfile

[root@localhost docker-test-volume]# vim dockerfile
# 文件中的內容:指令(大寫) 參數
FROM centos

VOLUME ["volume01","volume02"]

CMD echo"----end----"

CMD /bin/bash

# 這里的每個命令,就是鏡像的一層!

注意:我們這里的 dockerfile 是我們編寫的文件名哦!

這兩個卷和外部一定有兩個同步的目錄!

查看一下卷掛載在主機上的路徑

docker inspect 容器id

測試一下剛才的文件是否同步出去了!

這種方式我們未來使用十分的多,因為我們通常會構建自己的鏡像!

假設構建鏡像的時候沒有掛在卷,要手動鏡像掛載即可: (參考上文具名和匿名掛載)

-v 卷名:容器內路徑 

數據卷容器

多個mysql同步數據!

在docker03下創建docker03文件后,進入docker01發現也依舊會同步過來:

# 測試1:刪除docker01后,docker02和docker03是否還可以訪問原來docker01下創建的的文件?
# 測試1的結果為:依舊可以訪問!!!

# 測試2:刪除docker01后,docker02和docker03之間是否可以相互同步文件?
# 測試2的結果為:docket02和docker03之間一九可以完成同步!!! 見下圖:

多個mysql實現數據共享

➜  ~ docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
➜  ~ docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7
# 這個時候,可以實現兩個容器數據同步!

結論:

容器之間的配置信息的傳遞,數據卷容器的生命周期一直持續到沒有容器使用為止。

但是一旦你持久化到了本地,這個時候,本地的數據是不會刪除的!


DockerFile

DockerFile介紹

dockerfile是用來構建docker鏡像的文件!命令參數腳本!

構建步驟:

1、 編寫一個dockerfile文件

2、 docker build 構建稱為一個鏡像

3、 docker run運行鏡像

4、 docker push發布鏡像(DockerHub 、阿里雲倉庫)

查看官方是怎么做的!

很多官方鏡像都是基礎包,很多功能沒有,我們通常會自己搭建自己的鏡像!

官方既然可以制作鏡像,那我們也可以!

DockerFile構建過程

基礎知識:

1、每個保留關鍵字(指令)都是必須是大寫字母

2、執行從上到下順序

3、# 表示注釋

4、每一個指令都會創建提交一個新的鏡像曾,並提交!

Dockerfile是面向開發的,我們以后要發布項目,做鏡像,就需要編寫dockerfile文件,這個文件十分簡單!

Docker鏡像逐漸成企業交付的標准,必須要掌握!

DockerFile:構建文件,定義了一切的步驟,源代碼

DockerImages:通過DockerFile構建生成的鏡像,最終發布和運行產品。

Docker容器:容器就是鏡像運行起來提供服務。

DockerFile的指令

FROM			# 基礎鏡像,一切從這里開始構建
MAINTAINER		# 鏡像是誰寫的,姓名+郵箱
RUN				# 鏡像構建的時候需要運行的命令
ADD				# 步驟:tomcat鏡像,這個tomcat壓縮包! 添加內容
WORKDIR			# 鏡像的工作目錄
VOLUME			# 掛載的目錄
EXPOSE          # 暴露端口配置,跟 -p 是一個道理
CMD				# 指定這個容器啟動時要執行的命令,只有最后一個命令會生效,可悲替代
ENTRYPOINT		# 指定這個容器啟動的時候要執行的命令,可以追加命令
ONBUILD			# 當構建一個被繼承DockerFile 這個時候就會運行ONBUILD的指令。觸發指令
COPY			# 類似ADD,將我們文件拷貝到鏡像中
ENV				# 構建的時候設置環境變量,跟 -e 是一個意思

# CMD 和 ENTRYPOINT 的區別說明:(后面也會介紹)
# 若CMD 和 ENTRYPOINT 后跟的都是 ls -a 這個命令,當docker run 一個容器時,添加了 -l 選項,則CMD里的ls -a 命令就會被替換成-l;而ENTRYPOINT中的 ls -a會追加-l變成 ls -a -l  

實戰測試

Docker Hub中99%鏡像都是從這個基礎鏡像過來的( FROM scratch ),然后配置需要的軟件和配置來構建。

創建一個自己的 centos

# 1、編寫DockerFile文件,內容如下:
[root@localhost dockerfile]# cat mydockerfile-centos
FROM centos						
MAINTAINER ztx<123456@qq.com> 

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash

# 2、通過這個文件構建鏡像
# 命令docker build -f dockerfile文件路徑 -t 鏡像名:[tag] .
[root@localhost dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
....
Successfully built c987078b06cb
Successfully tagged mycentos:0.1

# 3、測試運行

對比:

之前的原生的centos

我們增加之后的鏡像

注:net-tools 包含一系列程序,構成了 Linux 網絡的基礎。

我們可以列出本地鏡像的變更歷史:

我們平時拿到一個鏡像,可以研究一下它是怎么做的!

CMD 和 ENTRYPOINT 的區別

測試CMD

# 編寫dockerfile文件
$ vim dockerfile-test-cmd
FROM centos
CMD ["ls","-a"]
# 構建鏡像
$ docker build  -f dockerfile-test-cmd -t cmd-test:0.1 .
# 運行鏡像
$ docker run cmd-test:0.1
.
..
.dockerenv
bin
dev

# 想追加一個命令  -l 成為ls -al
$ docker run cmd-test:0.1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\":
 executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled 
# cmd的情況下 -l 替換了CMD["ls","-l"]。 -l  不是命令,所以報錯

測試ENTRYPOINT

# 編寫dockerfile文件
$ vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
$ docker run entrypoint-test:0.1
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found ...
# 我們的命令,是直接拼接在我們的ENTRYPOINT命令后面的
$ docker run entrypoint-test:0.1 -l
total 56
drwxr-xr-x   1 root root 4096 May 16 06:32 .
drwxr-xr-x   1 root root 4096 May 16 06:32 ..
-rwxr-xr-x   1 root root    0 May 16 06:32 .dockerenv
lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root  340 May 16 06:32 dev
drwxr-xr-x   1 root root 4096 May 16 06:32 etc
drwxr-xr-x   2 root root 4096 May 11  2019 home
lrwxrwxrwx   1 root root    7 May 11  2019 lib -> usr/lib
lrwxrwxrwx   1 root root    9 May 11  2019 lib64 -> usr/lib64 ....

Dockerfile中很多命令都十分的相似,我們需要了解它們的區別,我們最好的學習就是對比他們然后測試效果!

實戰:Tomcat鏡像

1、准備鏡像文件tomcat壓縮包,jdk壓縮包!

2、編寫Dockerfile文件,官方命名: Dockerfile ,build會自動尋找這個文件,就不要 -f 指定了!

FROM centos
MAINTAINER kuangshen<123456@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u161-linux-x64.tar.gz    /usr/local/
ADD apache-tomcat-8.0.53.tar.gz   /usr/local

RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH


ENV JAVA_HOME /usr/local/jdk1.8.0_161
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.0.53
ENV CATALINA_BASH /usr/local/apache-tomcat-8.0.53
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-8.0.53/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.0.53/bin/logs/catalina.out

3、構建鏡像

# docker build -t diytomcat .     diytomcat是定義的鏡像名

4、啟動鏡像,創建容器

# docker run -d -p 9090:8080 --name kuangshentomcat02 -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-8.0.53/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-8.0.53/logs diytomcat

5、訪問測試

6、發布項目(由於做了卷掛載,我們就可以直接在本地發布項目了)

在/home/kuangshen/build/tomcat/test目錄下創建WEB-INF目錄,在里面創建web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

</web-app>

在回到test目錄,添加一個index.jsp頁面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello kuangshen</title>vim
</head>
<body>
Hello World!<br/>
<%
System.out.println("---my test web logs---");
%>
</body>
</html>

發現:test項目部署成功,可以直接訪問!

注意:這時進入/home/kuangshen/build/tomcat/tomcatlogs/目錄下就可以看到日志信息了:

[root@localhost tomcatlogs]# cat catalina.out 

之前一直訪問失敗是web.xml配置有問題,最后也是查看該日志提示,才得以解決!!!

我們以后開發的步驟:需要掌握Dockerfile的編寫!我們之后的一切都是使用docker鏡像來發布運行!

發布自己的鏡像

Docker Hub

1、地址 https://hub.docker.com/

2、確定這個賬號可以登錄

3、在我們服務器上提交自己的鏡像

[root@localhost tomcat]# docker login --help

Usage:	docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username

# 登錄dockerhub
[root@localhost tomcat]# docker login -u ztx115
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

4、登錄完畢后就可以提交鏡像了,就是一步 docker push

# push自己的鏡像到服務器上!
[root@localhost tomcat]# docker push diytomcat
The push refers to repository [docker.io/library/diytomcat]
c5593011cd68: Preparing 
d3ce40b8178e: Preparing 
02084c67dcc9: Preparing 
2b7c1c6c89c5: Preparing 
0683de282177: Preparing 
denied: requested access to the resource is denied  # 拒絕

# push鏡像的問題?
# 解決:增加一個tag         docker tag  指定鏡像的id   dockerhub的用戶名/鏡像重命名:[tag]
[root@localhost tomcat]# docker tag bb64ab96b432 ztx115/tomcat:1.0

注意:鏡像的重命名前一定要加當前的dockerhub的用戶名,否則將會push失敗!!!!(如:把ztx115改成ztx, push一定失敗!)

# docekr push上去即可!  自己平時發布的鏡像盡量帶上版本號
[root@localhost tomcat]# docker push ztx115/tomcat:1.0
The push refers to repository [docker.io/ztx115/tomcat]
c5593011cd68: Pushed 
d3ce40b8178e: Pushed 
02084c67dcc9: Pushed 
2b7c1c6c89c5: Pushed 
0683de282177: Pushed 
1.0: digest: sha256:b6733deccf85ad66c6f4302215dd9ea63e1579817f15a099b5858785708ed408 size: 1372

發現,提交時也是按照鏡像的層級來進行提交的!

發布到阿里雲鏡像服務上(狂神視頻截圖)

1、登錄阿里雲

2、找到容器鏡像服務

3、創建命名空間

4、創建容器鏡像倉庫

5、瀏覽阿里雲

使用阿里雲容器鏡像的參考官方指南即可!!!(即上圖)

小結


Docker網絡

理解Docker0

清空所有環境

測試

# 問題: docker是如何處理容器網絡訪問的?

# [root@localhost /]# docker run -d -P --name tomcat01 tomcat

# 查看容器的內部網絡地址   ip addr,  發現容器啟動的時候會得到一個 eth0@if43 ip地址,docker分配的!
[root@localhost /]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
42: eth0@if43: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# 思考:linux能不能ping通docker容器內部!
[root@localhost /]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.476 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.099 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.105 ms
...
# linux 可以ping通docker容器內部

原理

1、我們每啟動一個docker容器,docker就會給docker容器分配一個ip,我們只要裝了docker,就會有一個docker01網卡。

橋接模式,使用的技術是veth-pair技術!

再次測試 ip addr,發現多了一對網卡 :

2、再啟動一個容器測試,發現又多了一對網卡!!!

# 我們發現這個容器帶來網卡,都是一對對的
# veth-pair 就是一對的虛擬設備接口,他們都是成對出現的,一段連着協議,一段彼此相連
# 正因為有這個特性,veth-pair 充當一個橋梁,連接各種虛擬網絡設備
# OpenStack,Docker容器之間的連接,OVS的連接都是使用veth-pair技術

3、我們來測試下tomcat01和tomcat02是否可以ping通!

[root@localhost /]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.556 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.096 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.111 ms
...

# 結論:容器與容器之間是可以相互ping通的!!!

繪制一個網絡模型圖:

結論:tomcat01 和 tomcat02 是公用一個路由器,即 docker0 !

所有的容器不指定網絡的情況下,都是經 docker0 路由的,docker 會給我們的容器分配一個默認的可用ip

小結

Docker使用的是Linux的橋接技術,宿主機是一個Docker容器的網橋 docker0

注意:Docker中所有網絡接口都是虛擬的,虛擬的轉發效率高!(內網傳遞文件)

只要容器一刪除,對應的一對網橋就沒有!

思考一個場景:我們編寫了一個微服務,database url = ip ,項目不重啟,數據庫ip換掉了,我們希望可以處理這個問題,可以通過名字來訪問容器?

# tomcat02 想通過直接ping 容器名(即"tomcat01")來ping通,而不是ip,發現失敗了!
[root@localhost /]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 如何解決這個問題呢?
# 通過--link 就可以解決這個網絡聯通問題了!!!      發現新建的tomcat03可以ping通tomcat02
[root@localhost /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
87a0e5f5e6da34a7f043ff6210b57f92f40b24d0d4558462e7746b2e19902721
[root@localhost /]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.132 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.116 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.116 ms

# 反向能ping通嗎?       發現tomcat02不能oing通tomcat03
[root@localhost /]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

探究:inspect !!!

其實這個tomcat03就是在本地配置了到tomcat02的映射:

# 查看hosts 配置,在這里發現原理!  
[root@localhost /]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat02 95303c12f6d9    # 就像windows中的 host 文件一樣,做了地址綁定
172.17.0.4	87a0e5f5e6da

本質探究:--link 就是我們在hosts 配置中增加了一個 172.17.0.3 tomcat02 95303c12f6d9 (三條信息都是tomcat02 的)

我們現在玩Docker已經不建議使用 --link 了!!!

自定義網絡,不使用docker0!

docker0問題:不支持容器名連接訪問!

自定義網絡

查看所有的docker網絡

網絡模式

bridge :橋接 (docker默認,自己創建也使用bridge模式!)

none :不配置網絡

host :和宿主機共享網絡

container :容器網絡連通,容器直接互聯!(用的少!局限很大!)

測試

# 我們之前直接啟動的命令 (默認是使用--net bridge,可省),這個bridge就是我們的docker0 
docker run -d -P --name tomcat01 tomcat   
docker run -d -P --name tomcat01 --net bridge tomcat
# 上面兩句等價

# docker0(即bridge)默認不支持域名訪問 ! --link可以打通連接,即支持域名訪問!

# 我們可以自定義一個網絡!
# --driver bridge    		網絡模式定義為 :橋接
# --subnet 192.168.0.0/16	定義子網 ,范圍為:192.168.0.2 ~ 192.168.255.255
# --gateway 192.168.0.1		子網網關設為: 192.168.0.1 
[root@localhost /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
7ee3adf259c8c3d86fce6fd2c2c9f85df94e6e57c2dce5449e69a5b024efc28c
[root@localhost /]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
461bf576946c        bridge              bridge              local
c501704cf28e        host                host                local
7ee3adf259c8        mynet               bridge              local  	#自定義的網絡
9354fbcc160f        none                null                local

自己的網絡就創建好了:

[root@localhost /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
b168a37d31fcdc2ff172fd969e4de6de731adf53a2960eeae3dd9c24e14fac67
[root@localhost /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
c07d634e17152ca27e318c6fcf6c02e937e6d5e7a1631676a39166049a44c03c
[root@localhost /]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "7ee3adf259c8c3d86fce6fd2c2c9f85df94e6e57c2dce5449e69a5b024efc28c",
        "Created": "2020-06-14T01:03:53.767960765+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "b168a37d31fcdc2ff172fd969e4de6de731adf53a2960eeae3dd9c24e14fac67": {
                "Name": "tomcat-net-01",
                "EndpointID": "f0af1c33fc5d47031650d07d5bc769e0333da0989f73f4503140151d0e13f789",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "c07d634e17152ca27e318c6fcf6c02e937e6d5e7a1631676a39166049a44c03c": {
                "Name": "tomcat-net-02",
                "EndpointID": "ba114b9bd5f3b75983097aa82f71678653619733efc1835db857b3862e744fbc",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]


# 再次測試 ping 連接
[root@localhost /]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.199 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.121 ms
^C
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.121/0.160/0.199/0.039 ms

# 現在不使用 --link,也可以ping 名字了!!!!!!
[root@localhost /]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.145 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.117 ms
^C
--- tomcat-net-02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.117/0.131/0.145/0.014 ms

我們在使用自定義的網絡時,docker都已經幫我們維護好了對應關系,推薦我們平時這樣使用網絡!!!

好處:

redis——不同的集群使用不同的網絡,保證了集群的安全和健康

mysql——不同的集群使用不同的網絡,保證了集群的安全和健康

網絡連通

# 測試打通 tomcat01 — mynet
[root@localhost /]# docker network connect mynet tomcat01

# 連通之后就是將 tomcat01 放到了 mynet 網絡下! (見下圖)
# 這就產生了 一個容器有兩個ip地址 ! 參考阿里雲的公有ip和私有ip
[root@localhost /]# docker network inspect mynet

# tomcat01 連通ok
[root@localhost /]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.124 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.162 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.107 ms
^C
--- tomcat-net-01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.107/0.131/0.162/0.023 ms

# tomcat02 是依舊打不通的
[root@localhost /]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

結論:假設要跨網絡操作別人,就需要使用docker network connect 連通。。。

實戰:部署Redis集群

啟動6個redis容器,上面三個是主,下面三個是備!

使用shell腳本啟動!

# 創建redis集群網絡
docker network create redis --subnet 172.38.0.0/16

# 通過腳本創建六個redis配置
[root@localhost /]# for port in $(seq 1 6);\
> do \
> mkdir -p /mydata/redis/node-${port}/conf
> touch /mydata/redis/node-${port}/conf/redis.conf
> cat <<EOF>>/mydata/redis/node-${port}/conf/redis.conf
> port 6379
> bind 0.0.0.0
> cluster-enabled yes
> cluster-config-file nodes.conf
> cluster-node-timeout 5000
> cluster-announce-ip 172.38.0.1${port}
> cluster-announce-port 6379
> cluster-announce-bus-port 16379
> appendonly yes
> EOF
> done

# 查看創建的六個redis
[root@localhost /]# cd /mydata/
[root@localhost mydata]# \ls
redis
[root@localhost mydata]# cd redis/
[root@localhost redis]# ls
node-1  node-2  node-3  node-4  node-5  node-6

# 查看redis-1的配置信息
[root@localhost redis]# cd node-1
[root@localhost node-1]# ls
conf
[root@localhost node-1]# cd conf/
[root@localhost conf]# ls
redis.conf
[root@localhost conf]# cat redis.conf 
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.11
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

[root@localhost conf]# docker exec -it redis-1 /bin/sh
/data # ls
appendonly.aof  nodes.conf
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: c5551e2a30c220fc9de9df2e34692f20f3382b32 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: d12ebd8c9e12dbbe22e7b9b18f0f143bdc14e94b 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 825146ce6ab80fbb46ec43fcfec1c6e2dac55157 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 9f810c0e15ac99af68e114a0ee4e32c4c7067e2b 172.38.0.14:6379
   replicates 825146ce6ab80fbb46ec43fcfec1c6e2dac55157
S: e370225bf57d6ef6d54ad8e3d5d745a52b382d1a 172.38.0.15:6379
   replicates c5551e2a30c220fc9de9df2e34692f20f3382b32
S: 79428c1d018dd29cf191678658008cbe5100b714 172.38.0.16:6379
   replicates d12ebd8c9e12dbbe22e7b9b18f0f143bdc14e94b
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: c5551e2a30c220fc9de9df2e34692f20f3382b32 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 79428c1d018dd29cf191678658008cbe5100b714 172.38.0.16:6379
   slots: (0 slots) slave
   replicates d12ebd8c9e12dbbe22e7b9b18f0f143bdc14e94b
M: d12ebd8c9e12dbbe22e7b9b18f0f143bdc14e94b 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: e370225bf57d6ef6d54ad8e3d5d745a52b382d1a 172.38.0.15:6379
   slots: (0 slots) slave
   replicates c5551e2a30c220fc9de9df2e34692f20f3382b32
S: 9f810c0e15ac99af68e114a0ee4e32c4c7067e2b 172.38.0.14:6379
   slots: (0 slots) slave
   replicates 825146ce6ab80fbb46ec43fcfec1c6e2dac55157
M: 825146ce6ab80fbb46ec43fcfec1c6e2dac55157 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

docker搭建redis集群完成!

我們使用docker之后,所有的技術都會慢慢變得簡單起來!


Springboot微服務打包Docker鏡像

1、構建springboot項目,打包應用

2、編寫Dockerfile,連同項目的jar包一並上傳指定目錄下

3、構建鏡像

4、創建項目容器,發布運行!!!


以后我們使用了Docker之后,給別人交付就是一個鏡像即可!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM