Docker!Docker!Docker!

Docker

感謝秦老師,視頻跳轉連接 https://www.bilibili.com/video/BV1og4y1q7M4

Docker概述

Docker爲什麼會出現?

一款產品:開發–上線 兩套環境 ->應用環境,應用配置.

開發 ---- 運維 問題:我在我的電腦上可以運行! 版本更新導致服務不可用,對於運維來說考驗十分大

開發即運維!

環境配置十分麻煩,每個機器都要部署環境(集羣Redis,ES,Hadoop…) 費時費力

發佈一個項目 (jar + (Redis MySQL jdk ES)) ,項目能不能帶上環境安裝打包?

之前在服務器配置一個應用的環境Redis MySQL jdk ES Hadoop , 配置超麻煩,不能跨平臺

Windows開發,發佈到Linux上.

傳統:開發打包成jar ,運維來做環境部署.

現在:開發打包部署上線,一套流程做完.

比如一個安卓應用 java – apk – 發佈 (應用商店) --張三使用apk – 安裝即可用

java – jar (環境) – 打包項目帶上環境 (鏡像) --(Docker倉庫:商店) — 下載我們發佈的鏡像 – 直接運行即可

image-20200514192044633

Docker的思想來自於集裝箱

JRE – 多個應用 (端口衝突) – 原來都是交叉的

隔離:Docker核心思想–>打包裝箱. 每個箱子是互相隔離的

Docker給以上的問題,提出瞭解決方案.

image-20200514194258833

虛擬機技術缺點:

1, 資源佔用十分多

2, 冗餘步驟多

3, 啓動很慢

Docker的歷史

Docker能幹嘛

容器化技術

容器化技術並不是模擬一個完整的操作系統

image-20200514194539165

比較Docker和虛擬機技術的不同:

  • 傳統虛擬機,虛擬出一條硬件,運行一個 完整的操作系統,然後在這個系統上安裝和運行軟件
  • 容器內的應用直接運行在宿主機的內容, 容器是沒有自己的內核的,也沒有虛擬我們的硬件,所以就輕便了
  • 每個容器間是相互隔離的,每個容器內部都有一個屬於自己的文件系統,互不影響
DevOps(開發,運維)
應用更快速的交付和部署

傳統:一堆幫助文檔,安裝程序

Docker:打包鏡像發佈測試,一鍵運行

更便捷的升級和擴縮容

使用了Docker之後,我們部署應用就和搭積木一樣

項目打包爲一個鏡像,水平擴展服務器A,服務器B

更簡單的系統運維繫統

在容器化之後,我們的開發,測試環境都是高度一致的.

更高效的計算資源利用

1核2g的服務器 可以同時運行幾十個tomcat?!!!

Docker是內核級別的虛擬化,可以在一個物理機上運行很多的容器實例

服務器的性能可以被壓榨到極致!

Docker安裝

Docker的基本組成

image-20200514195821182

鏡像(image):

docker鏡像就好比是一個模板,可以通過這個模板來創建容器服務,tomcat鏡像–>run—>tomcat01容器(提供服務器).通過這個鏡像可以創建多個容器(最終服務運行或者項目運行就是在容器中的).

容器(container):

Docker利用容器技術,獨立運行一個或者-個組應用 ,通過鏡像來創建的。啓動,停止,刪除,基本命令!
目前就可以把這個容器理解爲就是一個簡易的linux系統.

倉庫(repository):

倉庫就是存放鏡像的地方.

倉庫分爲公有倉庫和私有倉庫.

Docker Hub(默認是國外的)

像阿里雲之類的大型企業都有容器服務器(配置鏡像加速)

安裝Docker

環境準備
  1. 需要會一點點的Linux基礎
  2. CentOS 7
  3. 我們使用Xshell連接遠程服務器進行操作

環境查看

# 系統版本
[root@iZm5eicbmpex37r3ecz3h7Z ~]# cat /etc/os-release
NAME="Aliyun Linux"
VERSION="2.1903 LTS (Hunting Beagle)"
ID="alinux"
ID_LIKE="rhel fedora centos"
VERSION_ID="2.1903"
PRETTY_NAME="Aliyun Linux 2.1903 LTS (Hunting Beagle)"
ANSI_COLOR="0;31"
HOME_URL="https://www.aliyun.com/"

安裝

幫助文檔 https://docs.docker.com/engine/install/centos/

# 1.卸載舊版本
$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
# 2.需要的安裝包
$ sudo yum install -y yum-utils

# 3.設置鏡像倉庫
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo		# 默認是國外的!很慢!
    
$ sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 阿里雲鏡像 快

# 更新yum軟件包索引
yum makecache fast

# 4.安裝docker	docker-ce 社區版 ee 企業版
$ sudo yum install docker-ce docker-ce-cli containerd.io

# 5.啓動docker
$ sudo systemctl start docker

# 6.使用docker version查看是否安裝成功

image-20200515161455869

# 7.使用hello owrld測試
$ sudo docker run hello-world

image-20200515161828923

# 判斷images是否下載成功
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        4 months ago        13.3kB

瞭解:卸載docker

# 卸載依賴
$ sudo yum remove docker-ce docker-ce-cli containerd.io
# 刪除資源
$ sudo rm -rf /var/lib/docker
# /var/lib/docker docker的默認工作路徑

阿里雲鏡像加速

登錄阿里雲找到容器服務

image-20200515162605225

找到鏡像加速地址

image-20200515162706176

配置使用

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://pdprqq44.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

回顧HelloWorld流程

image-20200515161828923

run的運行流程圖

image-20200515163153456

底層原理

Docker是怎麼工作的?

Docker是一個Client -Server結構的系統, Docker的守護進程運行在主機上。通過Socket從客戶端訪問.

DockerServer接收到Docker-Client的信息,就會執行這條命令.

image-20200514202932565

Docker爲什麼比VM快?

  1. Docker有比虛擬機更少的抽象層

  2. Docker利用的是宿主機的內核,vm是需要Guest OS.

  3. image-20200514203124767

    所以說,新建一個容器的時候,docker不需要像虛擬機一樣重新加載一個操作系統內核,避免引導.虛擬機是加載Guest OS,分鐘級別的,而Docker是利用宿主機的操作系統,省略了這個複雜的過程,秒級!

    image-20200514203411873

    學習完畢所有的命令,再回過頭來看這段理論就會很清晰.

Docker命令

幫助命令

docker version # 顯示docker版本信息
docker info    # 顯示docker的的系統信息,包括鏡像和容器的數量
docker 命令 --help # 幫助命令

幫助文檔的地址: https://docs.docker.com/reference/

鏡像命令

docker images 查看所有本機上的鏡像

REPOSITORY  鏡像的倉庫源
TAG			鏡像的標籤
IMAGE ID	鏡像的id
CREATED		鏡像的創建時間
SIZE		鏡像的大小

-a,  --all		# 列出所有鏡像
-q,  --quiet	# 列出所有鏡像id,一般-ap連用

docker search搜索鏡像

[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker search mysql
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   9500                [OK]                
mariadb                           MariaDB is a community-developed fork of MyS…   3444                [OK]                
mysql/mysql-server                Optimized MySQL Server Docker images. Create…   696                                     [OK]
centos/mysql-57-centos7           MySQL 5.7 SQL database server                   75                                      
mysql/mysql-cluster               Experimental MySQL Cluster Docker images. Cr…   69                                      
centurylink/mysql                 Image containing mysql. Optimized to be link…   61     
# 可選項 通過收藏過濾
--filter=stars=3000	搜索出來的鏡像就是STARS大於3000的 
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker search mysql --filter=stars=3000 
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql               MySQL is a widely used, open-source relation…   9500                [OK]                
mariadb             MariaDB is a community-developed fork of MyS…   3444                [OK] 

docker pull下載鏡像

# 下載鏡像 docker pull 鏡像名[:tag]
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker pull mysql
Using default tag: latest	# 如果不寫tag.默認就是latest
latest: Pulling from library/mysql	# 分層下載. docker image核心 聯合文件系統
5b54d594fba7: Pull complete 
07e7d6a8a868: Pull complete 
abd946892310: Pull complete 
dd8f4d07efa5: Pull complete 
076d396a6205: Pull complete 
cf6b2b93048f: Pull complete 
530904b4a8b7: Pull complete 
fb1e55059a95: Pull complete 
4bd29a0dcde8: Pull complete 
b94a001c6ec7: Pull complete 
cb77cbeb422b: Pull complete 
2a35cdbd42cc: Pull complete 
Digest: sha256:dc255ca50a42b3589197000b1f9bab2b4e010158d1a9f56c3db6ee145506f625 # 簽名
Status: Downloaded newer image for mysql:latest	
docker.io/library/mysql:latest 	# 真實地址

# 等價
docker pull mysql
docker pull docker.io/library/mysql:latest

# 指定版本下載
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
5b54d594fba7: Already exists 	# 聯合文件系統特性,已存在的直接複用
07e7d6a8a868: Already exists 
abd946892310: Already exists 
dd8f4d07efa5: Already exists 
076d396a6205: Already exists 
cf6b2b93048f: Already exists 
530904b4a8b7: Already exists 
a37958cbebcf: Pull complete 
04960017f638: Pull complete 
e1285def0d2a: Pull complete 
670cb3a9678e: Pull complete 
Digest: sha256:e4d39b85118358ffef6adc5e8c7d00e49d20b25597e6ffdc994696f10e3dc8e2
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

image-20200515164756415

docker rmi刪除鏡像

[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker rmi -f 鏡像id  # 刪除指定的鏡像
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker rmi -f 鏡像id 鏡像id 鏡像id 	# 刪除多個容器
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker rmi -f $(docker images -aq)  # 刪除全部鏡像

(增刪改查)

容器命令

說明:我們有了鏡像纔可以創建容器,linux,下載一個centos鏡像來測試學習

docker pull centos

新建容器並啓動

docker run [可選參數] image
# 參數說明
--name="Name" 	容器名字 tomcat01 tomcat02 用來區分同期
-d				後臺方式運行(nohup)
-it				使用交互方式運行,進入容器查看內容
-p				指定容器的端口  -p 8080:8080
	-p ip:主機端口:容器端口
	-p 主機端口:容器端口 (常用)
	-p 容器端口
	容器端口
-P				隨即指定端口

# 測試, 啓動並進入容器
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker run -it centos /bin/bash
[root@ba30042453f7 /]# 
[root@ba30042453f7 /]# ls   # 查看容器內的centos,基礎版本,很多命令都是不完善的
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 從容器中退回主機
[root@ba30042453f7 /]# exit
exit
[root@iZm5eicbmpex37r3ecz3h7Z ~]# ls
tgz

列出所有運行的容器

docker ps
	# 列出當前正在運行的容器
-a	# 列出當前正在運行的容器+歷史運行過的容器
-n=? # 顯示最近創建的容器
-q	# 只顯示容器的編號
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
ba30042453f7        centos              "/bin/bash"         3 minutes ago       Exited (0) About a minute ago                       wonderful_hawking
f6ea189c0505        bf756fb1ae65        "/hello"            47 minutes ago      Exited (0) 47 minutes ago                           zen_bassi
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker ps -aq
ba30042453f7
f6ea189c0505

退出容器

exit 	# 直接停止容器並退出
Ctrl + p + q # 容器不停止退出

刪除容器

docker rm 容器id  				# 刪除指定的容器,不能刪除正在運行的容器
docker rm -f $(docker ps -aq)	 # 遞歸刪除所有的容器
docker ps -aq|xargs docker rm 	 # 刪除所有的容器

啓動和停止容器的操作

docker start 容器id		# 啓動容器
docker restart 容器id		# 重啓容器
docker stop 容器id		# 停止容器
docker kill 容器id		# 強制停止容器

常用其他命令

後臺啓動容器

docker run -d 鏡像名	# 後臺啓動
# 問題: docker ps,發現centos靜止了

# 常見的坑:docker容器使用後臺運行,就必須要有一個前臺進程,docker發現沒有應用,就會自動停止
# nginx,容器啓動後,發現自己沒有提供服務,就會立刻停止,就是沒有程序了

查看日誌命令

docker logs -f -t --tail  10 容器id

# 顯示日誌
-tf 			# 顯示日誌
--tail number 	# 要顯示的日誌條數

查看容器中進程信息ps

docker top 容器id

查看容器元數據

docker inspect 容器id  # 查看容器信息

進入當前正在運行的容器

# 通常容器都是使用後臺方式運行的,需要進入容器,修改一些配置

# 命令
docker exec -it 容器id bashShell

# 方式二
docker attach 容器id
正在執行的代碼....

# docker exec			# 進入容器後開啓一個新的終端,可以在裏面操作(常用)
# docker attach			# 進入容器正在執行的終端,不會啓動新的進程

從容器內拷貝文件到主機上

docker attach 容器id		# 進入容器
docker cp 容器id:/文件路徑	/目標主機路徑 	# 拷貝文件到主機
# 拷貝是一個手動過程,未來我們使用	-v	卷的技術,可以實現

小結

image-20200514214205990

attach 	Attach to a running container						#當前sheil卜attach住按指定您行謊你
build	Build an image from a Dockerfile					#通過Dockerfile定製鏡像
commit	Create a new image from a container changes			#提交當前容器爲新的鏡像
cp	Copy files/folders from the containers filesystem to the host path	#從容器中拷貝指定文件或者目錄到宿主機中
create	Create a new container								#創建一個新的容器,同run,但不啓動容器
diff	Inspect changes on a containers filesystem			#查看docker容器變化
events	Get real time events from the server				#從docker 服務獲取容器實時事件
exec	Run a command in an existing container 				#在已存在的容器上運行命令
export	Stream the contents of a container as a tar archive	#導出容器的內容流作爲一個tar歸檔文件[對應import ]
history	Show the history of an image						#展示一個鏡像形成歷史
images	List images											#列出系統當前鏡像
import	Create a new filesystem image from the contents of a tarball #從tar包中的內容創建一個新的文件系統映僧[對應export]
info	Display system-wide information						#顯示系統相關信息
inspect Return 1ow-leve1 information on a container			#查看容器詳細信息
ki11	Ki11 a running container							# ki11 指定docker 容器
load	Load an image from a tar archive					#從一個tar包中加載-一個鏡像[對應save]
login	Register or Login to the docker registry server		#註冊或者登錄一個docker 源服務器
logout	Log out fromLa Docker registry server				#從當前Docker registry 退出
1ogs	Fetch the 1ogs of a container						#輸出當村容器日誌信息
port	Lookup the public- facing port which is NAT-ed to PRIVATE PORT	#查看映射端口對應的容器內郵源端
pause	Pause a11 processes within a container				#暫停容器
ps	List containers											#列出容器列表
pull	Pull an image or a repository from the docker registry server #從docker境像源原 務器拉取指定鏡像或者庫鏡像
push	Push an image or a repository to the docker registry server	#推送指定鏡像或者庫鏡像至docker源服務器
restart	Restart a running container							#重啓運行的容器
rm	Remove one or more containers							#移除一個或者多個容器
rmi	Remove one or more images								#移除一個或多個鏡像[無容器使用該鏡像纔可刪除,否則需刪除相關容器纔可繼續或-個強制刪除]
run	Run a command in a new container						#創建一個新的容器並運行一個命令
save	Save an image toa tar archive						#保存一個鏡像爲一個tar包[對應load]
search	Search for an image on the Docker Hub				#在docker hub中搜索鏡像
start	Start a stopped containers							#啓動容器
stop	stop a running containers							#停止容器
tag	Tag an image into a reposi tory							#給源中鏡像打標籤
top	Lookup the running processes of a container				#查看容器中運行的進程信息
unpause	Unpause a paused container							#取消暫停容器
version	Show the docker vers ion information				#查看docker 版本號
wait	B1ock until a container stops, then print its exit code # 截取容器停止時的退出狀態值

docker的命令十分多,上面我們學習的是最常用的容器和鏡像命令,之後會學更多

作業練習

docker安裝nginx

# 搜索鏡像 search 建議去docker hub上搜索
# 下載鏡像 pull
# 運行測試

[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              602e111c06b6        3 weeks ago         127MB
centos              latest              470671670cac        3 months ago        237MB

# -d 後臺執行
# --name 給容器命名
# -p 宿主機端口:容器內部端口  (映射)
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker run -d --name nginx01 -p 8070:80 nginx
83505a20805b0891e43e895097a7c84a1450a65b0d1b83e54880fafa7b8ef8a5
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
83505a20805b        nginx               "nginx -g 'daemon of…"   9 seconds ago       Up 8 seconds        0.0.0.0:8070->80/tcp   nginx01

# 進入容器
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker exec -it nginx01 /bin/bash
root@83505a20805b:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@83505a20805b:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@83505a20805b:/# cd /etc/nginx
root@83505a20805b:/etc/nginx# ls
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf

# 退出容器
root@83505a20805b:/etc/nginx# exit
exit
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
83505a20805b        nginx               "nginx -g 'daemon of…"   8 minutes ago       Up 8 minutes        0.0.0.0:8070->80/tcp   nginx01

# 停止容器運行
[root@iZm5eicbmpex37r3ecz3h7Z ~]# docker stop 83505a20805b
83505a20805b

image-20200515175549138

我們現在每次改動nginx配置文件,都需要進入容器內部,十分麻煩,我要是可以在容器外部提供一個映射額路徑,打到在容器外部提供一個映射路徑,達到在容器外修改文件,容器內部就可以自動修改. 數據卷技術 -v

docker安裝tomcat

# 官方的使用
docker run -it --rm tomcat:9.0

# 我們之前的啓動都是後臺,停止了容器後,容器還是可以查到  docker run -it --rm 一般用來測試,用完就刪除

# 下載再啓動
docker pull tomcat

# 啓動運行
docker run -d -p 80:8080 --name tomcat01 tomcat

# 測試訪問沒有問題,但是404,因爲webapps中沒有項目,需要把webapps.dist下的東西拷貝到webapps中

docker安裝ES+Kibana

問題?不可以使用kibana直接連接ES,因爲他們是互相隔離的,那麼如何解決呢?

image-20200515180948411

可視化

  • portainer(先用這個)
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI/CD再用)

什麼是potainer?

Docker圖形化界面管理工具!提供-個後臺面板供我們操作

docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

訪問測試: htp://ip:8088/ (第一次訪問較慢,但是我加載很快,嘻嘻~)
通過它來訪問了:

image-20200515181642166

Docker鏡像

鏡像是什麼

鏡像是種輕量圾。可執行的獨立軟件包。用來打包軟件運行環境和基於運行環境開發的軟件,它包含運行某個軟件所需的所有內容,包括代碼。運行時。庫環境變量和配置文件。

所有的應用,直接打包成docker鏡像,就直接可以跑起來

如何得到鏡像:

  • 從遠程倉庫下載
  • 朋友拷貝給你
  • 自己製作一個DockerFile

Docker鏡像加載原理

UnionFD(聯合文件系統)

我們下載的時候看到的一層層就是這個

UnionFS (聯合文件系統) : Union文件系統( UnionFS )是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作爲一次提交來一層層的疊加 ,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。Union 文件系統是Docker鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像) ,可以製作各種具體的應用鏡像。
特性: 一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄

Docker鏡像加載原理

docker的鏡像實際上由一層一層的文件 系統組成,這種層級的文件系統UnionFS.
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引導加載kernel, Linux剛啓動時會加載bootfs文件系統,在Docker鏡像的最底層是bootfs.這-層與我們典型的Linux/Unix系統是一樣的,包含boo加載器和內核。當boot加載完成之後整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs.
rootfs (root file system) , 在bootfs之上。包含的就是典型Linux系統中的/dev, /proc, /bin, /etc等標準目錄和文件。rootfs就是各種不同的操作系統發行版,比如Ubuntu , Centos等等。

image-20200515183353270

平時我們安裝進虛擬機的CentOS都是好幾個G,爲什麼Docker這裏才200M?

image-20200515183441644

對於一個精簡的OS , rootfs可以很小,只需要包含最基本的命令,工具和程序庫就可以了,因爲底層直接用Host的kernel,自己只需要提供rootfs就可以了。由此可見對於不同的linux發行版bootfs基本是一致的, rootfs會有差別,因此不同的發行版可以公用bootfs.

虛擬機是分鐘級的,容器是秒級

分層理解

分層的鏡像

我們可以去下載一個鏡像,注意觀察下載的日誌輸出,可以看到是一層一層的在下載!

image-20200515184048255

思考:爲什麼Docker鏡像要採用這種分層的結構呢?
最大的好處,我覺得莫過於是資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那麼宿主機只需在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像 ,這樣就可以爲所有的容器服務了,而且鏡像的每一層都可以被共享。
查看鏡像分層的方式可以通過docker image inspect命令!

理解:

所有的Docker鏡像都起始於一個基礎鏡像層 ,當進行修改或增加新的內容時,就會在當前鏡像層之上,創建新的鏡像層。
舉一個簡單的例子,假如基於Ubuntu Linux 16.04創建一個新的鏡像 ,這就是新鏡像的第一-層 ;如果在該鏡像中添加Python包,就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就會創建第三個鏡像層。
該鏡像當前已經包含3個鏡像層,如下圖所示(這只是-個用於演示的很簡單的例子).

image-20200515184319837

在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點非常重要。 下圖中舉了一個簡單的例子,每個鏡像層包含3個文件,而鏡像包含了來自兩個鏡像層的6個文件。

image-20200515184528807

上圖中的鏡像層跟之前圖中的略有區別,主要目的是便於展示文件。
下圖中展示了一個稍微複雜的三層鏡像,在外部看來整個鏡像只有6個文件,這是因爲最上層中的文件7是文件5的一個更新版本。

image-20200515184555874

這種情況下,上層鏡像層中的文件覆蓋了底層鏡像層中的文件。這樣就使得文件的更新版本作爲一個新鏡像層添加到鏡像當中。
Docker通過存儲引擎(新版本採用快照機制)的方式來實現鏡像層堆棧,並保證多鏡像層對外展示爲統一的文件系統。
Linux.上可用的存儲引擎有AUFS. Overlay2、 Device Mapper, Btrfs 以及ZFS.顧名思義,每種存儲引擎都基於Linux中對應的文件系統或者塊設備技術,並且每種存儲引擎都有其獨有的性能特點。
Docker在Windows.上僅支持windowsfilter -種存儲引擎,該引擎基於NTFS文件系統之上實現了分層和CoW[1]。
下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆疊併合並,對外提供統一的視圖。

image-20200515184812509

特點

Docker鏡像都是隻讀的,當容器啓動時, 一個新的可寫層被加載到鏡像的頂部!
這一層就是我們通常說的容器層,容器之下的都叫鏡像層!

commit鏡像

docker commit 提交容器成爲一個新的副本
# 命令和git基本類似
docker commit -m="提交的描述信息" -a="作者" 容器id 目標鏡像名:[TAG]

實戰測試

# 啓動一個默認的tomcat

# 發現這個默認的tomcat webapps下沒有項目,官方的默認鏡像下就是沒有文件的

# 我們自己拷貝進去基本的文件,然後提交

# 將我們操作過的容器通過commit提交爲新的鏡像,我們以後就用我們修改過的鏡像就可以,這就是我們一個修改過的鏡像

image-20200516173535945

如果你想要保存當前容器的狀態,就可以通過commit來提交,獲得一個鏡像
就好比我們以前學習VM時候,快照!

到這裏就算docker入門了.

容器數據卷

什麼是容器數據卷

docker的理念回顧

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

問題:如果數據都在容器中,如果我們將容器刪除,數據就會丟失

需求:數據可以持久化

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

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

image-20200516182220440

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

使用數據卷

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

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

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

# 啓動之後,查看容器元信息
docker inspect 容器id  

image-20200516183404138

測試文件的同步

image-20200516184143851

再來測試

1.停止容器

2.主機上修改文件

3.啓動容器

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

image-20200516184749320

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

實戰:安裝mysql

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

# 獲取鏡像
[root@iZm5eicbmpex37r3ecz3h7Z /]# 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 容器名字
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 

# 啓動成功之後,在本地使用Navicat連接測試一下
# Navicat連接到服務器的3310 --- 3310與容器內的3306映射,連接成功

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

image-20200516193333896

image-20200516193355167

如果我們將容器刪除,我們掛載到本地的數據卷依舊不會丟失,這就實現了容器數據持久化功能.

具名和匿名掛載

# 匿名掛載
-d -P --name nginx01 -v /etc/nginx nginx
-v 容器內路徑 	-P 隨機映射端口

# 查看所有的卷的情況
[root@iZm5eicbmpex37r3ecz3h7Z /]# docker volume ls
local               0b2e6680ba0d6dcc8b141b7efb4661da724688b3789ebc03880e099c2deda420

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

# 具名掛載
[root@iZm5eicbmpex37r3ecz3h7Z /]# docker volume ls
DRIVER              VOLUME NAME
local               0b2e6680ba0d6dcc8b141b7efb4661da724688b3789ebc03880e099c2deda420
local               64e78ed3b5fbb992a4cc1eb6f68ea094afbf07d681872fca9dfe29bee4d11d54
local               juming-nginx

# 通過 -v 卷名:容器內路徑
# 查看一下這個卷
[root@iZm5eicbmpex37r3ecz3h7Z /]# docker volume inspect juming-nginx

image-20200516194758529

所有的docker容器內的卷,沒有指定目錄的情況下都是在’/var/lib/docker/volumes/xxx/_data’

我們通過具名掛載可以方便的找到我們的一個卷,大多數情況下我們使用具名掛載

# 如何確定是具名掛載還是匿名掛載,還是指定路徑掛載
-v 容器內路徑	 		 # 匿名掛載
-v 卷名:容器內路徑			# 具名掛載
-v /宿主機路徑:容器內路徑   # 指定路徑掛載,一般是/開頭的,指絕對路徑

拓展:

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

# 一旦設置了這個容器權限,容器對我們掛載出來的內容就限定了
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,就說明這個路徑只能通過宿主機來操作,容器內無法操作
# 默認rw

初識DockerFile

DockerFile就是用來構建Docker鏡像的構建文件 命令腳本. 先體驗一下

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

# 創建一個dockerfile文件,名字可以隨意,建議還是dockerfile
# 文件中的內容 指令(大寫) 參數
FROM centos

VOLUME ["volume01","volume02"]

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

# 這裏的每個命令,就是鏡像的一層
# 執行dockerfile
docker build -f /home/docker-test-volume/dockerfile1 -t kangyuan/centos:1.0 .

image-20200516221922089

# 啓動自己寫的image

image-20200516222318405

這個目錄就是我們生成鏡像的時候自動掛載的,數據卷目錄

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

image-20200516222453639
查看一下掛載的路徑

image-20200516222940877

# 新建一個文件
[root@5a096611a0e1 /]# cd volume01
[root@5a096611a0e1 volume01]# ls
[root@5a096611a0e1 volume01]# touch container.txt
[root@5a096611a0e1 volume01]# ls
container.txt

# 測試一下我們剛纔的文件是否同步了
[root@iZm5eicbmpex37r3ecz3h7Z home]# cd /var/lib/docker/volumes/63f56582dd79cac81b74f14256738103d0a950539edbafd6b8dbfe06c53ac91b/_data
[root@iZm5eicbmpex37r3ecz3h7Z _data]# ls
container.txt

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

假設構建鏡像時沒有掛載卷,要手動鏡像掛載 -v 卷名:容器內路徑

數據卷容器

多個容器同步數據

image-20200516225618428

# 啓動3個容器,通過我們剛纔自己的鏡像啓動
docker run -it --name=docker01 kangyuan/centos:1.0
docker run -it --name docker02 --volumes-from docker01 kangyuan/centos:1.0

image-20200516225952874

image-20200516230614310

image-20200516230443727

image-20200516231541424

# 測試刪除docker01,查看docker02和docker03是否還可以訪問volume01中的文件
# 測試結果發現依舊可以訪問

image-20200516231932298

多個mysql實現數據共享

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 

docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql02 --volumes-from mysql01 mysql:5.7 

# 這個時候,可以實現兩個容器數據同步

結論:

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

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

DockerFile

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

構建步驟:

  1. 編寫一個dockerfile文件
  2. docker build 構建成爲一個鏡像
  3. docker run 運行鏡像
  4. docker push 發佈鏡像(DockerHub,阿里雲鏡像倉庫)

查看一下官方是怎麼做的?

image-20200516233011527

跳轉到了github,發現就是一個Dockerfile

image-20200516233100080

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

官方既然可以製作鏡像,我們當然也可以

Dockerfile構建過程

基礎知識:

  1. 每個保留關鍵字(指令)都必須是大寫字母
  2. 從上到下順序執行
  3. #表示註釋
  4. 每一個指令都會創建一個新的鏡像層,並提交

image-20200516233824923

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

Docker鏡像逐漸成爲了企業交付的標準,必須要掌握

步驟:

Dockerfile: 構建文件,定義了一切的步驟,相當於源代碼

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

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

Dockerfile的指令

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

image-20200516234710747

以前我們是使用別人的,現在我們知道了這些指令,練習自己寫一個鏡像

實戰測試

Dockerhub中99%的鏡像都是從這個基礎鏡像過來的 FROM scratch,然後配置需要的軟件和配置來進行的構建

image-20200517093121645

創建一個自己的CentOS

# 1.編寫dockerfile文件
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# cat mydockerfile-centos 
FROM centos
MAINTAINER kangyuan<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

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

EXPOSE 80

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

# 2.通過這個文件構建鏡像 
# 命令 docker build -f dockerfile文件路徑 -t 鏡像名[:tag] .(這裏有個點)
Successfully built 1134d387377e
Successfully tagged mycentos:0.1

# 3.測試運行

對比:之前的原生的centos

image-20200517095226167

我們增加之後的鏡像

image-20200517095342734

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

image-20200517095529559

我們平時拿到一個鏡像可以研究一下他是怎麼做的了

CMD與ENTRYPOINT的區別

CMD					# 指定這個容器啓動的時候要運行的命令,只有最後一個會生效,可被替代
ENTRYPOINT			# 指定這個容器啓動的時候要運行的命令,可以追加命令

測試CMD

# 編寫dockerfile文件
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]

# 構建鏡像
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .

# run運行,發現我們的ls -a生效
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# docker run cmdtest
.
..
.dockerenv
bin
dev
etc
home
lib
lib64

# 想追加一個命令 -l 發現報錯 (ls -al)
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# docker run cmdtest -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","-a"]		-l不是命令所以就會報錯

測試ENTRYPOINT

[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]

[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# docker run entrypoint-test
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found

# 我們的追加命令,是直接拼接在我們的ENTRYPOINT命令的後面
[root@iZm5eicbmpex37r3ecz3h7Z dockerfile]# docker run entrypoint-test -l
total 56
drwxr-xr-x   1 root root 4096 May 17 02:13 .
drwxr-xr-x   1 root root 4096 May 17 02:13 ..
-rwxr-xr-x   1 root root    0 May 17 02:13 .dockerenv
lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root  340 May 17 02:13 dev
drwxr-xr-x   1 root root 4096 May 17 02:13 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
drwx------   2 root root 4096 Jan 13 21:48 lost+found

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

實戰:Tomcat鏡像

  1. 準備鏡像文件tomcat壓縮包,jdk壓縮包image-20200517104329638
  2. 編寫dockerfile文件,官方命名Dockerfile,build會自動尋找這個文件,就不需要-f指定了
FROM centos
MAINTAINER kangyuan<[email protected]>

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
  1. 構件鏡像
docker build -t diytomcat . 
  1. 啓動鏡像
docker run -d -p 3030:8080 --name kangyuantomcat 
-v /root/dockertest/test:/usr/local/apache-tomcat-8.5.24/webapps/test 
-v /root/dockertest/tomcatlogs/:/usr/local/apache-tomcat-8.5.24/logs diytomcat
  1. 訪問測試 成功
  2. 發佈項目(由於做了卷掛載,我們直接在本地編寫項目就可以發佈了)
<?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,offer</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("-------my test web logs-------");
%>
</body>
</html>

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

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

發佈自己的鏡像

DockerHub

  1. 地址 https://hub.docker.com/ 註冊自己的賬號
  2. 確定這個賬號可以登錄
  3. 在我們服務器上提交自己的鏡像
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker login -u imdeemo
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
  1. 登錄完畢後就可以提交鏡像了.就是一步docker push
# push自己的鏡像到服務器上
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker push diytomcat        
The push refers to repository [docker.io/library/diytomcat]
222e77312b5e: Preparing 
aa99731ac7f3: Preparing 
450eefc399f6: Preparing 
f9028fc5fdeb: Preparing 
0683de282177: Preparing 
denied: requested access to the resource is denied # 拒絕

# 解決方案:增加一個tag
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker tag diytomcat imdeemo/diytomcat
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
diytomcat             latest              6368ed9615df        42 minutes ago      695MB
imdeemo/diytomcat     latest              6368ed9615df        42 minutes ago      695MB
# push,自己發佈的鏡像儘量帶上版本號
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker push imdeemo/diytomcat:latest

提交中:

image-20200517115905148

提交的時候也是按照鏡像的層級來進行提交的

阿里雲鏡像服務

  1. 登錄阿里雲
  2. 找到容器鏡像服務
  3. 創建命名空間image-20200517120626970
  4. 創建容器鏡像image-20200517120825399
  5. 瀏覽阿里雲image-20200517121018883
# 參考阿里雲給的示例

image-20200517122449548

小結

image-20200517122949059

Docker網絡原理

理解Docker0

清空所有環境

測試

image-20200517141145746

三個網絡

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

image-20200517141251895

[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker run -d -P --name tomcat01 tomcat

# 查看容器的內部網絡地址 ip addr,發現容器啓動的時候會得到一個eth0@if67 ip地址,docker分配的
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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
66: eth0@if67: <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通容器內部
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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.068 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.065 ms

# linux可以ping通docker容器內部

原理

  1. 我們每啓動一個docker容器,docker就會給docker容器分配一個ip,我們只要安裝了docker,就會有一個網卡docker0 橋接模式,使用的技術是veth-pair 技術

    再次測試ip addrimage-20200517142032303

  2. 再啓動一個容器測試,發現又多了一對網卡image-20200517142305182

    # 我們發現這個容器帶來的網卡都是一對一對的
    # veth-pair 就是一對的虛擬設備接口,他們都是成對出現的,一段連着協議,一段彼此相連
    # 正因爲有了這個特性,veth-pair 充當一個橋樑,連接各種虛擬網絡設備的
    # OpenStac ,Docker容器之間的連接,OVS的連接,都是使用veth-pair 技術
    
    1. 我們測試一下tomcat01和tomcat02是否可以ping通

      [root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker exec -it tomcat02 ping 172.17.0.2
      
      # 結論: 容器和容器之間是可以互相ping通的
      

      繪製一個網絡模型圖:

      image-20200517143407259

    結論:tomcat01和tomcat02是共用的一個路由器,docker0

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

小結

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

image-20200517144308075

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

只要容器刪除,對應網橋一對就沒了.

image-20200517150028380

–link

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

[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known

# 如何可以解決呢
# 通過--link就可以解決網絡連通問題
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
434fab3886a930372a75935b23abb2da4df07d1d860143c258769961e8b93e5a
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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.070 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.074 ms

# 反向可以ping通嗎? 不行,因爲沒有配置
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker exec -it tomcat02 ping tomcat03 
ping: tomcat03: Name or service not known

探究:inspect

image-20200517150117413

其實這個tomcat03就是在本地配置了tomcat02的地址

# 查看hosts配置,在這裏發現
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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 a8be6dc01d63
172.17.0.4      434fab3886a9

本質探究 --link就是我們在hosts配置中增加了一個172.17.0.3 tomcat02 a8be6dc01d63

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

我們需要自定義網絡,不適用於docker0

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

自定義網絡

容器互聯

查看所有的docker網絡

image-20200517150956711

網絡模式

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

none: 不配置網絡

host: 和宿主機共享網絡

container: 容器網絡連通(用得少,侷限很大)

測試

# 我們直接啓動的命令	--net bridge, 而這個就是我們的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat 

# docker0特點: 默認,域名不能訪問,		--link可以打通連接

# 我們可以自定義一個網絡
# --driver bridge
# --subnet 192.168.0.0/16 	範圍 192.168.0.2~192.168.255.255
# --gateway 192.168.0.1
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
940e573879d97543226f71d368dc4a2662f1641c13959b41737d965936403bcb
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9ba63ff11231        bridge              bridge              local
3b094ea4e3d3        host                host                local
940e573879d9        mynet               bridge              local
ad203cf4b20d        none                null                local

image-20200517152812668

[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
058ac0a65032477c198fd3536aa7e720641655aec3943be1ee552b330b23815e
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker run -d -P --name tomcat-net-02 --net mynet tomcat 
4a6e38ec160660e70ef5e46112422052144b0b304352ae91f6fda7f8c3655686
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "940e573879d97543226f71d368dc4a2662f1641c13959b41737d965936403bcb",
        "Created": "2020-05-17T15:25:39.52346407+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": {
            "058ac0a65032477c198fd3536aa7e720641655aec3943be1ee552b330b23815e": {
                "Name": "tomcat-net-01",
                "EndpointID": "a955df5a5000239de6ef1aad9058df34b380d293ec1819303e87ef9709193ec5",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "4a6e38ec160660e70ef5e46112422052144b0b304352ae91f6fda7f8c3655686": {
                "Name": "tomcat-net-02",
                "EndpointID": "1f4f1dcf76e52919b4f6ef8d1ee128d50a5535293f0eed743a302e18fe290a06",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 再次測試ping連接
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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.110 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.064 ms

# 現在不適用--link也可以ping名字了
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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.036 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.065 ms

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

好處:

redis- 不同的集羣使用不同的網絡,保證集羣是安全和健康的

mysql- 不同的集羣使用不同的網絡,保證集羣是安全和健康的

網絡連通

image-20200517153643616

image-20200517153825451

# 測試打通tomcat01 - mynet
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker network connect mynet tomcat01

# 連通之後就是將tomcat01 放到了mynet網絡下

# 一個容器兩個ip地址	
# 好比 阿里雲服務:公網ip 私網ip

image-20200517154045325

# 01可以ping通
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# 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.081 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.070 ms

# 02依舊打不通
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker exec -it tomcat02 ping tomcat-net-01 
ping: tomcat-net-01: Name or service not known

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

實戰:部署Redis集羣

image-20200517165425416

shell腳本

# 創建網卡
docker network create redis --subnet 172.38.0.0/16

# 通過腳本創建六個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 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} 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@iZm5eicbmpex37r3ecz3h7Z /]# 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: bc3aff4049d9610330f51b58871769f8ac827c63 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 6af312198899e48ff01b1ee4a4158f7510e12d0b 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: c4f207bf3beb7ff1ac6142ab7b40166d57d34463 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: b2b335eb0306a36d23c9962b09f1ceed720200cc 172.38.0.14:6379
   replicates c4f207bf3beb7ff1ac6142ab7b40166d57d34463
S: c5bbf3ef339568f7d63000855d42ef366e52aba7 172.38.0.15:6379
   replicates bc3aff4049d9610330f51b58871769f8ac827c63
S: 5768864a0132bbc9139f16d1cf21b20868f66511 172.38.0.16:6379
   replicates 6af312198899e48ff01b1ee4a4158f7510e12d0b
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: bc3aff4049d9610330f51b58871769f8ac827c63 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 6af312198899e48ff01b1ee4a4158f7510e12d0b 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: b2b335eb0306a36d23c9962b09f1ceed720200cc 172.38.0.14:6379
   slots: (0 slots) slave
   replicates c4f207bf3beb7ff1ac6142ab7b40166d57d34463
S: 5768864a0132bbc9139f16d1cf21b20868f66511 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 6af312198899e48ff01b1ee4a4158f7510e12d0b
S: c5bbf3ef339568f7d63000855d42ef366e52aba7 172.38.0.15:6379
   slots: (0 slots) slave
   replicates bc3aff4049d9610330f51b58871769f8ac827c63
M: c4f207bf3beb7ff1ac6142ab7b40166d57d34463 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集羣完成

image-20200517180731205

Springboot微服務打包Docker鏡像

  1. 構建springboot項目
  2. 打包應用
  3. 編寫dockerfile
  4. 構建鏡像
  5. 發佈運行!

到這裏我們就完全夠用了Docker.

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

Docker Compose

Docker Swarm

CI/CD Jenkins

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章