容器數(shù)據(jù)卷
1. 什么是容器數(shù)據(jù)卷
docker的理念回顧
將應(yīng)用和環(huán)境打包成一個鏡像!
數(shù)據(jù)奥吩?如果數(shù)據(jù)都在容器中哼蛆,那么我們?nèi)萜鲃h除,數(shù)據(jù)就會丟失霞赫!需求:數(shù)據(jù)可以持久化
MySQL腮介,容器刪了,刪庫跑路端衰!需求:MySQL數(shù)據(jù)可以存儲在本地
容器之間可以有一個數(shù)據(jù)共享的技術(shù)叠洗!Docker容器中產(chǎn)生的數(shù)據(jù),同步到本地靴迫!
這就是卷技術(shù)惕味!目錄的掛載,將我們?nèi)萜鲀?nèi)的目錄玉锌,掛載到Linux上面名挥!
總結(jié)一句話:容器的持久化和同步操作!容器間也是可以數(shù)據(jù)共享的主守!
2. 使用數(shù)據(jù)卷
方式一:直接使用命令來掛載 -v
docker run -it -v 主機目錄:容器內(nèi)目錄
# 測試
[root@iz2zeakqdima07k787wct3z ~]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 啟動起來之后我們可以通過 docker inspect 容器id
測試文件的同步
再來測試禀倔!
- 停止容器
- 宿主機上修改文件
- 啟動容器
- 容器內(nèi)的數(shù)據(jù)依舊是同步的
好處:我們以后修改只需要在本地修改即可,容器內(nèi)會自動同步
3. 實戰(zhàn):安裝MySQL
思考:MySQL數(shù)據(jù)持久化的問題参淫!
# 獲取鏡像
[root@iz2zeakqdima07k787wct3z ~]# docker pull mysql:5.7
# 運行容器救湖,需要做數(shù)據(jù)掛載! # 安裝啟動MySQL涎才,需要配置密碼鞋既,這是注意點!
# 官方測試耍铜,docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 啟動我們的
-d 后臺運行
-p 端口映射
-v 卷掛載
-e 環(huán)境配置
--name 容器名字
[root@iz2zeakqdima07k787wct3z ~]# 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-連接到服務(wù)器的3310 --- 3310和容器內(nèi)的 3306 映射,這個時候我們就可以連接上了
# 在本地測試創(chuàng)建一個數(shù)據(jù)庫棕兼,查看一下我們映射的路徑是否OK陡舅!
假設(shè)我們將容器刪除,發(fā)現(xiàn)伴挚,我們掛載到本地的數(shù)據(jù)卷依舊沒有丟失靶衍,這就實現(xiàn)了容器數(shù)據(jù)持久化功能灾炭!
4. 具名和匿名掛載
# 匿名掛載
-v 容器內(nèi)路徑
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的 volume 的情況
[root@iz2zeakqdima07k787wct3z ~]# docker volume ls
local o213u0123jr019901hr3893rp23ju98123u08ujfd0812ju30821ue
# 這里發(fā)現(xiàn),這種就是匿名掛載颅眶,我們在 -v 只寫了容器內(nèi)的路徑蜈出,沒有寫容器外的路徑!
# 具名掛載
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
879e2a05282d6f5245ecddaebdb57d4d8210704d45f9ecf7e57ca249b07f6e8d
[root@iz2zeakqdima07k787wct3z ~]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx
# 通過 -v 卷名:容器內(nèi)路徑
# 查看一下這個卷
所有的docker容器內(nèi)的卷帚呼,沒有指定目錄的情況下都是在/var/lib/docker/volumes/XXXX/_data
我們通過具名掛載可以方便的找到我們的一個卷掏缎,大多數(shù)情況在使用的具名掛載
# 如何確定是具名掛載還是匿名掛載,還是指定路徑掛載
-v 容器內(nèi)路徑 #匿名掛載
-v 卷名:容器內(nèi)路徑 # 具名掛載
-v /宿主機路徑:容器內(nèi)路徑 # 指定路徑掛載
拓展:
# 通過 -v 容器內(nèi)路徑煤杀,ro rw 改變讀寫權(quán)限
ro readonly # 只讀
rw readwrite # 可讀可寫
# 一旦設(shè)置了容器權(quán)限眷蜈,容器對我們掛載出來的內(nèi)容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就說明這個路徑只能通過宿主機來操作沈自,容器內(nèi)部是無法操作的酌儒!
5. 初識Dockerfile
Dockerfile 就是用來構(gòu)建 docker 鏡像的構(gòu)建文件!命令腳本枯途!先體驗一下忌怎!
# 創(chuàng)建一個dockerfile文件,名字可以隨機 建議 Dockerfile
[root@iz2zeakqdima07k787wct3z home]# mkdir docker-test-volume
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi docker-test-volume mysql rgh.java test.java www
[root@iz2zeakqdima07k787wct3z home]# cd docker-test-volume/
[root@iz2zeakqdima07k787wct3z docker-test-volume]# vim dockerfile1
# 文件中的內(nèi)容 指令(大寫) 參數(shù)
FROM centos
VOLUME ["volum01","volum02"]
CMD echo "----end----"
CMD /bin/bash
# 這里的每個指令酪夷,就是鏡像的一層
這個卷和外部一定有一個同步的目錄榴啸!
查看一下卷掛載的路徑
測試一下剛才的文件是否同步出去了!
這種方式我們未來使用的非常多晚岭,因為我們通常會構(gòu)建自己的鏡像鸥印!
假設(shè)構(gòu)建鏡像時候沒有掛載卷,要手動鏡像掛載 -v 卷名:容器內(nèi)路徑坦报!
6. 數(shù)據(jù)容器卷
多個mysql同步數(shù)據(jù)库说!
# 啟動3個容器,通過我們剛才自己寫的鏡像啟動
[root@iz2zeakqdima07k787wct3z /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rgh/centos 1.0 f6a19068fc9c About an hour ago 215MB
tomcat02 1.0 7d44ce4e447c 4 hours ago 652MB
centos latest 831691599b88 8 days ago 215MB
tomcat 9.0 2eb5a120304e 2 weeks ago 647MB
tomcat latest 2eb5a120304e 2 weeks ago 647MB
nginx latest 2622e6cca7eb 2 weeks ago 132MB
mysql 5.7 9cfcce23593a 2 weeks ago 448MB
portainer/portainer latest cd645f5a4769 3 weeks ago 79.1MB
elasticsearch 7.6.2 f29a1ee41030 3 months ago 791MB
[root@iz2zeakqdima07k787wct3z /]# docker run -it --name docker01 rgh/centos:1.0
# Ctrl + p + q
[root@iz2zeakqdima07k787wct3z /]# docker run -it --name docker02 --volumes-from docker01 rgh/centos:1.0
# 測試,可以刪除docker01,查看一下docker02和docker03是否還可以訪問這個文件
# 測試依舊可以訪問
多個mysql實現(xiàn)數(shù)據(jù)共享
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-form mysql01 mysql:5.7
# 這個時候可以實現(xiàn)兩個容器數(shù)據(jù)同步
結(jié)論:
容器之間配置信息的傳遞,數(shù)據(jù)卷容器的生命周期一直持續(xù)到?jīng)]有容器使用為止邦蜜。
但是一旦你持久化到了本地,這個時候啰挪,本地的數(shù)據(jù)是不會刪除的!
DockerFile
dockerfile 是用來構(gòu)建docker鏡像的文件嘲叔!命令參數(shù)腳本脐供!
構(gòu)建步驟:
- 編寫一個 dockerfile 文件
- docker build 構(gòu)建成為一個鏡像
- docker run 運行鏡像
- docker push 發(fā)布鏡像(DockerHub、阿里云鏡像倉庫=韫颉)
很多官方鏡像都是基礎(chǔ)包,很多功能都沒有酌壕,我們通常會自己搭建自己的鏡像掏愁!
官方既然可以制作鏡像歇由,那我們也可以!
1. DockerFile構(gòu)建過程
基礎(chǔ)知識
- 每個保留關(guān)鍵字(指令)都必須是大寫字母
- 執(zhí)行從上到下順序執(zhí)行
-
#
表示注釋 - 每個指令都會創(chuàng)建提交一個新的鏡像層果港,并提交
dockerfile是面向開發(fā)的沦泌,我們以后要發(fā)布項目,做鏡像辛掠,就需要編寫dockerfile文件谢谦,這個文件十分簡單!
Docker鏡像逐漸成為了企業(yè)交付的標準萝衩,必須掌握回挽!
DockerFile:構(gòu)建文件,定義了一切的步驟猩谊,源代碼
DockerImages:通過DockerFile構(gòu)建生成的鏡像千劈,最終發(fā)布和運行的產(chǎn)品!
Docker容器:容器就是鏡像運行起來提供服務(wù)的
2. DockerFile的指令
FROM # 基礎(chǔ)鏡像牌捷,一切從這里開始構(gòu)建
MAINTAINER # 鏡像是誰寫的墙牌,姓名+郵箱
RUN # 鏡像構(gòu)建的時候需要運行的命令
ADD # 步驟,tomcat鏡像暗甥,這個tomcat壓縮包喜滨!添加內(nèi)容
WORKDIR # 鏡像的工作目錄
VOLUME # 掛載的目錄
EXPOST # 暴露端口配置
CMD # 指定這個容器啟動的時候要運行的命令,只有最后一個會生效撤防,可被替代
ENTRYPOINT # 指定這個容器啟動的時候要運行的命令虽风,可以追加命令
ONBUILD # 當構(gòu)建一個被繼承的 DockerFile 這個時候就會運行 ONBUILD 的指令。觸發(fā)指令即碗。
COPY # 類似ADD焰情,將我們的文件拷貝到鏡像中
ENV # 構(gòu)建的時候設(shè)置環(huán)境變量
3. 實戰(zhàn)測試
Docker Hub 中 99% 鏡像都是從這個基礎(chǔ)鏡像過來的 FROM scratch ,然后配置需要的軟件和配置來進行的構(gòu)建
創(chuàng)建一個自己的centos
# 創(chuàng)建文件夾
[root@iz2zeakqdima07k787wct3z home]# mkdir dockerfile
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi dockerfile docker-test-volume mysql rgh.java test.java www
[root@iz2zeakqdima07k787wct3z home]# cd dockerfile/
[root@iz2zeakqdima07k787wct3z dockerfile]# ls
# 1. 編寫dockerfile的文件
[root@iz2zeakqdima07k787wct3z dockerfile]# vim mydockerfile-centos
[root@iz2zeakqdima07k787wct3z dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER rgh<386045673@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
[root@iz2zeakqdima07k787wct3z dockerfile]#
# 2. 通過這個文件構(gòu)建鏡像
# 命令 docker build -f dockerfile文件路徑 -t 鏡像名:[tag]
[root@iz2zeakqdima07k787wct3z dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
Successfully built 662e5307e229
Successfully tagged mycentos:0.1
# 3. 測試運行
對比:之前的原生的centos
我們增加之后的鏡像
我們可以列出本地鏡像的變更歷史
我們平時拿到一個鏡像,可以研究一下它是怎么做的了剥懒?
CMD 和 ENTRYPOINT區(qū)別
CMD # 指定這個容器啟動的時候要運行的命令内舟,只有最后一個會生效,可被替代
ENTRYPOINT # 指定這個容器啟動的時候要運行的命令初橘,可以追加命令
測試cmd
# 編寫 dockerfile 文件
[root@iz2zeakqdima07k787wct3z dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
# 構(gòu)建鏡像
[root@iz2zeakqdima07k787wct3z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 831691599b88
Step 2/2 : CMD ["ls","-a"]
---> Running in 599c30194db4
Removing intermediate container 599c30194db4
---> 21002a840f44
Successfully built 21002a840f44
Successfully tagged cmdtest:latest
# run 運行验游,發(fā)現(xiàn)我們的 ls -a 命令生效了
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 21002a840f44
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
# 想追加一個命令 -l ls -al
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 21002a840f44 -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.
# cmd的情況下 -l 替換了 CMD ["ls","-a"] 命令,-l 不是命令所以報錯
測試ENTRYPOINT
[root@iz2zeakqdima07k787wct3z dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos
CMD ["ls","-a"]
[root@iz2zeakqdima07k787wct3z dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 831691599b88
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 82d1ebd7d27d
Removing intermediate container 82d1ebd7d27d
---> 6b36f25bbfb0
Successfully built 6b36f25bbfb0
Successfully tagged entrypoint-test:latest
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 6b36f25bbfb0
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
# 我們的追加命令保檐,是直接拼接在我們的 ENTRYPOINT 命令的后面耕蝉!
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 6b36f25bbfb0 -l
total 56
drwxr-xr-x 1 root root 4096 Jun 26 07:01 .
drwxr-xr-x 1 root root 4096 Jun 26 07:01 ..
-rwxr-xr-x 1 root root 0 Jun 26 07:01 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 Jun 26 07:01 dev
drwxr-xr-x 1 root root 4096 Jun 26 07:01 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
[root@iz2zeakqdima07k787wct3z dockerfile]#
DockerFile中很多命令都十分的相似,我們需要了解它們的區(qū)別夜只,我們最好的學習就是對比他們?nèi)缓鬁y試效果
4. 實戰(zhàn):Tomcat鏡像
-
準備鏡像文件 tomcat壓縮包垒在,jdk壓縮包
-
編寫dockerfile文件,官方命名
Dockerfile
扔亥,build會自動尋找這個文件场躯,就不需要 -f 指定了谈为!FROM centos MAINTAINER rgh<386045673@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u152-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-8.5.24.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_152 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.24 ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.24 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-8.5.24/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.24/bin/logs/catalina.out
-
構(gòu)建鏡像
# docker build -t diytomcat . [root@iz2zeakqdima07k787wct3z tomcat]# docker run -d -p 9090:8080 --name rghtomcat -v /home/rgh/build/tomcat/test:/usl/local/apache-tomcat-8.5.24/webapps/test -v /home/rgh/build/tomcat/tomcatlogs/:/usl/local/apache-tomcat-8.5.24/logs diytomcat
啟動鏡像
訪問測試
-
發(fā)布項目(由于做了卷掛載,我們直接在本地編寫項目就可以發(fā)布)
<?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>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello,RGH</title> </head> <body> Hello World!<br/> <% System.out.println("----my test web logs-----"); %> </body> </html>
發(fā)現(xiàn):項目部署成功踢关,可以直接訪問OK伞鲫!
我們以后開發(fā)的步驟:需要掌握Dokcerfile的編寫!我們之后的一切都是使用docker鏡像來發(fā)布運行签舞!
5. 發(fā)布自己的鏡像
DockerHub
地址 https://hub.docker.com/ 注冊自己的賬號
確定這個賬號可以登陸
-
在我們服務(wù)器上提交自己的鏡像
[root@iz2zeakqdima07k787wct3z 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 [root@iz2zeakqdima07k787wct3z tomcat]# docker login -u ruanguohui 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
-
登陸完畢后就可以提交鏡像了秕脓,就是一步 docker push
[root@iz2zeakqdima07k787wct3z tomcat]# docker push diytomcat The push refers to repository [docker.io/library/diytomcat] c385be13b942: Preparing e348f8d69a0a: Preparing e048a134c37e: Preparing 579df485af18: Preparing eb29745b8228: Preparing denied: requested access to the resource is denied # 拒絕 # push 遇到的問題? [root@iz2zeakqdima07k787wct3z tomcat]# docker push ruanguohui/diytomcat:2.0 The push refers to repository [docker.io/ruanguohui/diytomcat] An image does not exist locally with the tag: ruanguohui/diytomcat # 解決儒搭,增加一個tag [root@iz2zeakqdima07k787wct3z tomcat]# docker tag c0794e0071c6 ruanguohui/tomcat:1.0 # docker push 上去即可吠架!自己發(fā)布的鏡像盡量帶上版本號 [root@iz2zeakqdima07k787wct3z tomcat]# docker push ruanguohui/tomcat:1.0
提交的時候也是按照鏡像的層級來進行提交的。
阿里云鏡像服務(wù)器上
登陸阿里云
找到容器鏡像服務(wù)
-
創(chuàng)建命名空間
-
創(chuàng)建容器鏡像
-
瀏覽阿里云
docker push registry.cn-beijing.aliyuncs.com/test-ruanguohui/ruanguohui-demo:[鏡像版本號]
小結(jié)
Docker網(wǎng)絡(luò)
1. 理解Docker0
清空所有環(huán)境
# 清空所有容器
docker rm -f $(docker ps -aq)
# 清空所有鏡像
docker rmi -f $(docker images -aq)
測試
三個網(wǎng)絡(luò)
# 問題:docker 是如何處理容器網(wǎng)絡(luò)訪問的师妙?
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat01 tomcat
# 查看容器的內(nèi)部網(wǎng)絡(luò)地址 ip addr ,發(fā)現(xiàn)容器啟動的時候會得到一個 eth0@if87 ip地址诵肛,docker分配的
# exec:執(zhí)行 -it:交互模式執(zhí)行
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
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
86: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 思考,linux 能不能 ping 同容器內(nèi)部
[root@iz2zeakqdima07k787wct3z ~]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.110 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.090 ms
# linux 可以ping通docker容器內(nèi)部
原理
-
我們每啟動一個docker容器默穴,docker就會給docker容器分配一個ip怔檩,我們只要安裝了docker,就會有一個網(wǎng)卡docker0橋接模式蓄诽,使用的技術(shù)是 veth-pair 技術(shù)薛训!
-
再啟動一個容器測試,發(fā)現(xiàn)又多了一對網(wǎng)卡仑氛!
# 我們發(fā)現(xiàn)這個容器帶來網(wǎng)卡乙埃,都是一對對的
# veth-pair 就是一對的虛擬設(shè)備接口,他們都是成對出現(xiàn)的锯岖,一端連著協(xié)議介袜,一端彼此相連
# 正因為有這個特性,evth-pair充當一個橋梁出吹,連接各種虛擬網(wǎng)絡(luò)設(shè)備的
# Openstac遇伞,Docker容器之間的連接,OVS的連接捶牢,都是使用 veth-pair 技術(shù)
-
我們來測試下 tomcat01和tomcat02 是否可以ping通
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping 172.18.0.2 # 結(jié)論:容器和容器之間是可以互相ping通的
結(jié)論:tomcat01 和 tomcat02是公用的一個路由器鸠珠,docker0。
所有的容器在不指定網(wǎng)絡(luò)的情況下秋麸,都是docker0路由的渐排,docker會給我們的容器分配一個默認的可用IP
小結(jié)
Docker使用的是Linux的橋接,宿主機中是一個Docker容器的網(wǎng)橋 docker0
Docker 中的所有的網(wǎng)絡(luò)接口都是虛擬的灸蟆。虛擬的轉(zhuǎn)發(fā)效率高Q背堋(內(nèi)網(wǎng)傳遞文件)
只要容器刪除,對應(yīng)網(wǎng)橋一對就沒了!
2. --link
思考一個場景可缚,我們編寫了一個微服務(wù)孽水,database url=ip:,項目不重啟城看,數(shù)據(jù)庫IP換掉了,我們希望可以處理這個問題杏慰,可以通過名字來訪問容器测柠?
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何解決呢?
# 通過--link 就可以解決網(wǎng)絡(luò)連通問題
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
4e824c3691317b00c0e752e21226430973de0f7b99c4ebc2c11b1d538042a573
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.142 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.094 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=3 ttl=64 time=0.106 ms
# 反向可以ping通嗎缘滥?
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
探究:inspect!
# 查看 hosts 配置轰胁,在這里原理發(fā)現(xiàn)!
[root@iz2zeakqdima07k787wct3z ~]# 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.18.0.3 tomcat02 dd58d47f44b0
172.18.0.4 4e824c369131
本質(zhì)探究:--link 就是我們在hosts配置中增加了一個 172.18.0.3 tomcat02 dd58d47f44b0
我們現(xiàn)在玩Docker 已經(jīng)不建議使用 --link了朝扼!
自定義網(wǎng)絡(luò)赃阀!不適用docker0!
自定義網(wǎng)絡(luò)擎颖!不適用docker0榛斯!
docker0問題:他不支持容器名連接訪問!
3. 自定義網(wǎng)絡(luò)
查看所有的docker網(wǎng)絡(luò)
網(wǎng)絡(luò)模式:
bridge:橋接 docker (默認搂捧,自己創(chuàng)建也使用bridge 模式)
none:不配置網(wǎng)絡(luò)
host:和宿主機共享網(wǎng)絡(luò)
container:容器網(wǎng)絡(luò)連通M运住(用的少!局限很大)
測試:
[root@iz2zeakqdima07k787wct3z ~]# docker rm -f $(docker ps -aq)
# 我們直接啟動的命令 --net bridge允跑,而這個就是我們的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 tomcat --net bridge tomcat
# docker0特點王凑,默認,域名不能訪問聋丝,--link可以打通連接索烹!
# 我們可以自定義一個網(wǎng)絡(luò)!
# --driver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
[root@iz2zeakqdima07k787wct3z ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
97ffb25e7d237cf835799ded68e898f14df0238edad893ff94f1c36ba301ee6c
[root@iz2zeakqdima07k787wct3z ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
fa839e57d074 bridge bridge local
365c15486a05 host host local
97ffb25e7d23 mynet bridge local
fb1e21f22d8a none null local
[root@iz2zeakqdima07k787wct3z ~]#
我們自己的網(wǎng)絡(luò)就創(chuàng)建好了
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
f2f53454947289774201b5c5e7ca37e87f5192757033522a061888596992677c
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
6bf0fdad1c734216e68b698af62e91c5f2db2c8afb9d42a0de7efdf321fd7612
[root@iz2zeakqdima07k787wct3z ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "97ffb25e7d237cf835799ded68e898f14df0238edad893ff94f1c36ba301ee6c",
"Created": "2020-06-27T17:43:51.170257885+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": {
"6bf0fdad1c734216e68b698af62e91c5f2db2c8afb9d42a0de7efdf321fd7612": {
"Name": "tomcat-net-02",
"EndpointID": "5b4ff32db373b566847e69286e441f0efa2f54324b5c5be39c70957aad26ad8e",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"f2f53454947289774201b5c5e7ca37e87f5192757033522a061888596992677c": {
"Name": "tomcat-net-01",
"EndpointID": "c60878eff346f9e01f81354393534dde67141510a7ea49d2351c0a4f3bec525c",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 再次測試ping連接
[root@iz2zeakqdima07k787wct3z ~]# 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.126 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.100 ms
^C
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.100/0.113/0.126/0.013 ms
# 現(xiàn)在不使用--link也可以ping名字了弱睦!
[root@iz2zeakqdima07k787wct3z ~]# 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.082 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.118 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.096 ms
我們自定義的網(wǎng)絡(luò)docker都幫我們維護好了對應(yīng)的關(guān)系百姓,推薦我們平時這樣使用網(wǎng)絡(luò)!
好處:
redis - 不同的集群使用不同的網(wǎng)絡(luò)每篷,保證集群是安全和健康的
mysql - 不同的集群使用不同的網(wǎng)絡(luò)瓣戚,保證集群是安全和健康的
網(wǎng)絡(luò)連通
# 測試打通 tomcat01 - mynet
[root@iz2zeakqdima07k787wct3z ~]# docker network connect mynet tomcat01
# 連通之后就是將 tomcat01 放到了 mynet 網(wǎng)絡(luò)下
# 一個容器兩個IP地址
# 阿里云服務(wù)器,公網(wǎng)IP焦读,私網(wǎng)IP
# 01 連通
[root@iz2zeakqdima07k787wct3z ~]# 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.120 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.100 ms
# 02 是依舊打不通的
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
結(jié)論:假設(shè)要跨網(wǎng)絡(luò)操作別人子库,就需要使用 docker network connect
連通!
4. 實戰(zhàn):部署Redis集群
[root@iz2zeakqdima07k787wct3z ~]# docker rm -f $(docker ps -aq)
[root@iz2zeakqdima07k787wct3z ~]# docker network create redis --subnet 172.38.0.0/16
0b04ad3dc26d3d3951c7a210b2a49e1c27b57faf69a122e3bea65b6e20a4da5e
[root@iz2zeakqdima07k787wct3z ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
fa839e57d074 bridge bridge local
365c15486a05 host host local
97ffb25e7d23 mynet bridge local
fb1e21f22d8a none null local
0b04ad3dc26d redis bridge local
[root@iz2zeakqdima07k787wct3z ~]# docker network inspect redis
[
{
"Name": "redis",
"Id": "0b04ad3dc26d3d3951c7a210b2a49e1c27b57faf69a122e3bea65b6e20a4da5e",
"Created": "2020-06-29T10:38:10.140768409+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.38.0.0/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
# 通過腳本創(chuàng)建六個Redis配置
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
docker run -p 6371:6379 -p 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
# 創(chuàng)建集群
[root@iz2zeakqdima07k787wct3z conf]# docker exec -it redis-1 /bin/sh
/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: de7260f699404b3ba4f3ccd3203d304ce2062085 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 6e90db525d03538a646de43a943437cbd1319931 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 3c1b3a9ef855d3267ab8b6f68bdda515da1b2556 172.38.0.14:6379
replicates 6e90db525d03538a646de43a943437cbd1319931
S: e2ada3facb95d3b86f02a1a696990ae7ef8059f5 172.38.0.15:6379
replicates de7260f699404b3ba4f3ccd3203d304ce2062085
S: 136a386bb4690f2d7949d2fc6dfacd748029567e 172.38.0.16:6379
replicates 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609
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: de7260f699404b3ba4f3ccd3203d304ce2062085 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: e2ada3facb95d3b86f02a1a696990ae7ef8059f5 172.38.0.15:6379
slots: (0 slots) slave
replicates de7260f699404b3ba4f3ccd3203d304ce2062085
M: 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 6e90db525d03538a646de43a943437cbd1319931 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 136a386bb4690f2d7949d2fc6dfacd748029567e 172.38.0.16:6379
slots: (0 slots) slave
replicates 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609
S: 3c1b3a9ef855d3267ab8b6f68bdda515da1b2556 172.38.0.14:6379
slots: (0 slots) slave
replicates 6e90db525d03538a646de43a943437cbd1319931
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# redis-cli 單擊 -c 集群
/data # redis-cli -c
# cluster info 查看集群信息
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:139
cluster_stats_messages_pong_sent:145
cluster_stats_messages_sent:284
cluster_stats_messages_ping_received:140
cluster_stats_messages_pong_received:139
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:284
127.0.0.1:6379>
Docker搭建Redis集群完成
我們使用了docker之后矗晃,所有的技術(shù)都會慢慢的變的簡單起來仑嗅!
SpringBoot微服務(wù)打包Docker鏡像
構(gòu)架SpringBoot項目
打包應(yīng)用
-
編寫dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
構(gòu)建鏡像
發(fā)布運行!
[root@iz2zeakqdima07k787wct3z ~]# cd /home
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi dockerfile docker-test-volume mysql rgh rgh.java test.java www
[root@iz2zeakqdima07k787wct3z home]# mkdir idea
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi dockerfile docker-test-volume idea mysql rgh rgh.java test.java www
[root@iz2zeakqdima07k787wct3z home]# cd idea/
[root@iz2zeakqdima07k787wct3z idea]# ls
demo-0.0.1-SNAPSHOT.jar Dockerfile
[root@iz2zeakqdima07k787wct3z idea]# docker build -t rgh666 .
Sending build context to Docker daemon 16.5MB
Step 1/5 : FROM java:8
8: Pulling from library/java
5040bd298390: Pull complete
fce5728aad85: Pull complete
76610ec20bf5: Pull complete
60170fec2151: Pull complete
e98f73de8f0d: Pull complete
11f7af24ed9c: Pull complete
49e2d6393f32: Pull complete
bb9cdec9c7f3: Pull complete
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:8
---> d23bdf5b1b1b
Step 2/5 : COPY *.jar /app.jar
---> 14ced70e2b66
Step 3/5 : CMD ["--server.port=8080"]
---> Running in 76e95c24c32c
Removing intermediate container 76e95c24c32c
---> 53155ec64b62
Step 4/5 : EXPOSE 8080
---> Running in 01f0e326df36
Removing intermediate container 01f0e326df36
---> 769f12470d42
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
---> Running in 5e64fa2ea56e
Removing intermediate container 5e64fa2ea56e
---> 5da2e4111e93
Successfully built 5da2e4111e93
Successfully tagged rgh666:latest
[root@iz2zeakqdima07k787wct3z idea]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rgh666 latest 5da2e4111e93 13 seconds ago 660MB
tomcat latest 2eb5a120304e 2 weeks ago 647MB
redis 5.0.9-alpine3.11 3661c84ee9d0 2 months ago 29.8MB
java 8 d23bdf5b1b1b 3 years ago 643MB
[root@iz2zeakqdima07k787wct3z idea]# docker run -d -P --name rgh-springboot-web rgh666
bccf17124951508c309a8c85505e072492cea5fa726f23f7154c01fc33706825
[root@iz2zeakqdima07k787wct3z idea]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bccf17124951 rgh666 "java -jar /app.jar …" 11 seconds ago Up 11 seconds 0.0.0.0:32778->8080/tcp rgh-springboot-web
[root@iz2zeakqdima07k787wct3z idea]# curl localhost:32778
{"timestamp":"2020-06-29T07:02:55.100+00:00","status":404,"error":"Not Found","message":"","path":"/"}[root@iz2zeakqdima07k787wct3z idea]# curl localhost:32778/hello
hello,ruanguohui[root@iz2zeakqdima07k787wct3z idea]#
以后我們使用了docker之后,給別人交付的就是一個鏡像即可仓技!