Docker
簡介
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的映象中,然後釋出到任何流行的 Linux或Windows 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面。
Docker是基於 Go 語言開發的,是一個開源專案。
虛擬機器技術缺點:模擬一個完整的作業系統,資源佔用多,步驟冗餘,啟動慢。
Docker 容器化技術:不是模擬的一個完整的作業系統。執行在宿主機的核心上。每個容器內是互相隔離的,互不影響。
DevOps:開發 運維。
應用更快的交付和部署。
傳統:安裝各種的jar包,打包釋出。
Docker :一鍵打包映象釋出,測試。
更便捷的升級和擴縮容,專案打包為一個映象,部署應用就和搭積木一樣。
更簡單的系統運維,容器化後,開發測試環境都是一致的。
更高效的計算資源利用,Docke是核心級的虛擬化,在一個物理機上可以執行很多的容器。
Docker安裝
Docker的基本組成
映象(image):
就好比是一個模板,可通過這個映象來建立容器服務,比如 tomcat 映象--->run--->tomcat01容器,通過這個映象可以建立多個容器(應用最終在容器中執行)。
容器(container):
Docker利用容器技術,獨立執行一個或一組應用,通過映象建立。
啟動,停止,刪除,基本命令。
倉庫(repository):
存放映象的地方。倉庫分為公有倉庫和私有倉庫。
安裝Docker
環境準備:
- 需要會Linux基礎
- Centos7
- 使用Xshell連線遠端伺服器操作
- 已經購買雲伺服器(以下使用阿里雲)
環境檢視
#系統核心是3.0以上的
[root@zhourui /]# uname -r
4.18.0-193.28.1.el8_2.x86_64
#系統版本
[root@zhourui /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="8 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="8"
安裝:參考幫助文件 https://docs.docker.com/engine/install/centos/
解除安裝舊的版本
#解除安裝
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#需要的安裝包
yum install -y yum-utils
#設定映象的倉庫
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo #預設的是國外的十分慢
#阿里雲映象 (推薦使用)
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新yum軟體包索引
yun makecache fast
#安裝docker decker-ce社群版的 ee企業版
yum install docker-ce docker-ce-cli containerd.io
#啟動docker
systemctl start docker
#檢視是否安裝成功
docker version
#啟動 hello-world
docker run hello-world
#檢視下載的hello-world映象
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 weeks ago 13.3kB
#解除安裝docker
yum remove docker-ce docker-ce-cli containerd.io
#刪除資源
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
配置阿里雲映象加速
登入阿里雲找到容器服務。
找到容器映象服務
配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://tk46rux4.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
回顧helloworld流程
流程圖
工作原理
Docker是一個Client,Server結構的系統,Docker的守護程式執行在主機上,通過Socket從客戶端訪問。
DockerServer接收到DockerClient的指令,就會執行這個命令。
Docker為什麼比VNM快:
Docker有比虛擬機器更少的抽象層。
Docker利用的是宿主機的核心,VM有自己的Guest OS。
新建一個容器的時候,Docker不需要像虛擬機器一樣新建一個系統核心。利用宿主機的核心,提升了啟動速度和系統資源利用率。
Docker的常用命令
幫助命令
docker -version #顯示docker的版本資訊
docker info #docker的詳細資訊 映象和容器的數量
docker 命令 --help #萬能命令
docker --help #docker的所有命令
命令:官網地址 https://docs.docker.com/reference/
映象命令
docker images:檢視本機所有映象
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 weeks ago 13.3kB
#解釋
REPOSITORY 映象的倉庫源
TAG 映象的標籤
IMAGE ID 映象的 id
CREATED 映象的建立時間
SIZE 映象的大小
#可選項
-a, --all #顯示所有的映象
-q, --quiet #只顯示映象的id
docker search:搜尋映象
[root@zhourui /]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10634 [OK]
mariadb MariaDB Server is a high performing open sou… 3990 [OK]
#可選項
--filter=STARS=3000 #搜尋出來的就是stars大於等於3000的 -f簡寫
[root@zhourui /]# docker search mysql -f=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10634 [OK]
mariadb MariaDB Server is a high performing open sou… 3990 [OK]
docker pull:下載映象
#下載 docker pull 映象名 [:tag](可以選版本) 不寫版本預設latest最後一個
[root@zhourui /]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
a076a628af6f: Pull complete #分層下載 docker image核心 聯合檔案系統
f6c208f3f991: Pull complete
88a9455a9165: Pull complete
406c9b8427c6: Pull complete
7c88599c0b25: Pull complete
25b5c6debdaf: Pull complete
43a5816f1617: Pull complete
1a8c919e89bf: Pull complete
9f3cf4bd1a07: Pull complete
80539cea118d: Pull complete
201b3cad54ce: Pull complete
944ba37e1c06: Pull complete
Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c #簽名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真實地址
# docker pull mysql
# 等價
# docker pull docker.io/library/mysql:latest
#指定版本下載
[root@zhourui /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
a076a628af6f: Already exists #共用
f6c208f3f991: Already exists
88a9455a9165: Already exists
406c9b8427c6: Already exists
7c88599c0b25: Already exists
25b5c6debdaf: Already exists
43a5816f1617: Already exists
1831ac1245f4: Pull complete
37677b8c1f79: Pull complete
27e4ac3b0f6e: Pull complete
7227baa8c445: Pull complete
Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 weeks ago 13.3kB
mysql 5.7 a70d36bc331a 2 months ago 449MB
mysql latest c8562eaf9d81 2 months ago 546MB
docker rmi:刪除映象
#刪除指定的容器 根據id
[root@zhourui /]# docker rmi -f c8562eaf9d81
#刪除多個映象
[root@zhourui /]# docker rmi -f id1 id2 id3
#刪除全部容器
[root@zhourui /]# docker rmi -f $(docker images -aq)
容器命令
我們有了映象才可以建立容器,下載一個CentOS映象來測試學習。
docker pull centos
新建容器並啟動
docker run (可選引數) image
#引數說明
--name=“Name” #容器名字 tomcat01 tomcat01 來區分
-d #後臺方式執行
-it #使用互動方式執行,進入容器檢視內容
-p #指定容器的埠 -p 8080:8080
-p 主機埠:容器埠 (常用)
-p ip:主機埠:容器埠
-p 容器埠
容器埠(不寫-p)
-p #隨機指定埠
#啟動並進入容器
[root@zhourui /]# docker run -it centos /bin/bash
[root@b728c79b5448 /]# ls #檢視容器內的centos 基礎版本 很多的命令不完善
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@b728c79b5448 /]# exit #退出命令
exit
[root@zhourui /]# ls
bin boot dev etc home lib lib64 media mnt opt patch proc root run sbin srv sys tmp usr var www
列出所有執行的容器
# docker ps
#列出所有在執行的容器
-a #列出歷史執行過的容器
-n=? #顯示最近建立的n個容器
-q #列出執行容器的id
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@zhourui /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b728c79b5448 centos "/bin/bash" 4 minutes ago Exited (0) 2 minutes ago relaxed_elbakyan
0ce52f9209e4 d1165f221234 "/hello" 5 hours ago Exited (0) 5 hours ago intelligent_mirzakhani
退出容器
exit #容器停止並退出
ctrl +P +Q #按住這三個鍵 容器不停止退出
[root@zhourui /]# docker run -it centos /bin/bash
[root@c9797d0b4ba8 /]# [root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9797d0b4ba8 centos "/bin/bash" About a minute ago Up About a minute inspiring_faraday
刪除容器
docker rm #刪指定id的容器 不能刪除正在執行的容器 強制刪除 rm -f
docker rm -f $(docker ps -aq) #刪除全部的容器
docker -a-q|xargs docker rm #刪除全部容器
啟動和停止容器的操作
docker start 容器id #啟動
docker restart 容器id #重啟
docker stop 容器id #停止容器
docker kill 容器id #強制停止
常用其它命令
後臺啟動容器
# docker run -d 容器名 後臺啟動
[root@zhourui /]# docker run -d centos
#執行docker ps 發現centos停止了
#docker容器使用後臺執行,就必須有一個前臺程式,docker發現沒有應用,就會自動停止
檢視日誌
docker logs -f -t --tail 10 容器id #列印最近10條日誌
#編寫shell指令碼
“while true;do echo zhourrrrr;sleep 1;done”
[root@zhourui /]# docker run -d centos /bin/bash -c "while true;do echo zhourrrr;sleep 1;done"
e79bac46e660abb781dcce7b0dbd3a3a896b573a104fdd9a15db0bbf5331341b
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e79bac46e660 centos "/bin/bash -c 'while…" 3 seconds ago Up 1 second jolly_sanderson
#顯示日誌
-tf #顯示日誌 t 時間
--tail number #最近的多少條資料
[root@zhourui /]# docker logs -f -t --tail 10 e79bac46e660
檢視容器中的程式資訊
docker top 容器id
[root@zhourui /]# docker top e79bac46e660
UID PID PPID C STIME TTY
root 227610 227588 0 22:36 ?
root 229020 227610 0 22:45 ?
檢視映象源資料
docker inspect 容器id
[root@zhourui /]# docker inspect e79bac46e660
[
{
"Id": "e79bac46e660abb781dcce7b0dbd3a3a896b573a104fdd9a15db0bbf5331341b",
"Created": "2021-03-21T14:36:07.740342428Z",
"Path": "/bin/bash",
"Args": [
"-c",
"while true;do echo zhourrrr;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 227610,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-03-21T14:36:08.2053845Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
.........#省略...
}
}
進入當前正在執行的容器
#通常容器都是後臺的方式執行的,需要進入容器修改一些配置
#命令
docker exec -it 容器id bashShell(bin/bash)
#測試
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
538cddb5e369 centos "bin/bash -c 'while …" 14 seconds ago Up 13 seconds quizzical_wing
[root@zhourui /]# docker exec -it 538cddb5e369 bin/bash
[root@538cddb5e369 /]#
[root@538cddb5e369 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@538cddb5e369 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:08 ? 00:00:00 bin/bash -c while true;do echo zzzzzrr;sleep 2;done
root 66 0 0 11:10 pts/0 00:00:00 bin/bash
root 131 1 0 11:12 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2
root 132 66 0 11:12 pts/0 00:00:00 ps -ef
#方式二
docker attach 容器id
#測試
[root@zhourui /]# docker attach 538cddb5e369
zzzzzrr
zzzzzrr
zzzzzrr
zzzzzrr
#進去後是正在執行的當前程式碼,想停止可以新開一個視窗 docker rm -f $(docker ps -aq)
# docker exec 進入後開啟了一個新的終端,可以在裡面操作
# docker attach 進入容器正在執行的終端,不會啟動新的程式
從容器內拷貝檔案到主機上
docker cp 容器id:容器內路徑 目的主機路徑
#測試
[root@zhourui /]# cd /home
[root@zhourui home]# ls
www zhour.java
[root@zhourui home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44e87620bf99 centos "/bin/bash" About a minute ago Up About a minute romantic_burnell
#進入容器
[root@zhourui home]# docker attach 44e87620bf99
[root@44e87620bf99 /]# cd /home
[root@44e87620bf99 home]# ls
#在容器內新建一個檔案
[root@44e87620bf99 home]# touch zr.java
[root@44e87620bf99 home]# ls
zr.java
[root@44e87620bf99 home]# exit
exit
[root@zhourui home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@zhourui home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44e87620bf99 centos "/bin/bash" 3 minutes ago Exited (0) 6 seconds ago romantic_burnell
#將容器內的檔案拷貝到主機上
[root@zhourui home]# docker cp 44e87620bf99:/home/zr.java /home
[root@zhourui home]# ls
www zhour.java zr.java
[root@zhourui home]#
#拷貝是一個手動過程,後面學習使用 -v 卷的技術,可以實現自動同步
小結
常用命令
練習部署
部署Nginx
-
搜尋映象:docker search nginx
-
下載映象:docker pull nginx
-
執行測試:docker run -d --name nginx01 -p 3344:80 nginx (--name:起別名,-p 3344:80 3344是暴露的埠就是宿主機埠 80是nginx預設埠就是容器的埠)
[root@zhourui home]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest f6d0b4767a6c 2 months ago 133MB centos latest 300e315adb2f 3 months ago 209MB hello-world latest bf756fb1ae65 14 months ago 13.3kB #--name:起別名,-p 3344:80 3344是暴露的埠 80是nginx預設埠 [root@zhourui home]# docker run -d --name nginx01 -p 3344:80 nginx 56b36ad955ca7cf6d80708b20d7ffd1152a0ca974c312df45bfe9e31d0888e0b [root@zhourui home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 56b36ad955ca nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 0.0.0.0:3344->80/tcp nginx01 [root@zhourui home]# curl localhost:3344 [root@zhourui home]# docker exec -it nginx01 bin/bash root@56b36ad955ca:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@56b36ad955ca:/# cd /etc/nginx root@56b36ad955ca:/etc/nginx# ls conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf root@56b36ad955ca:/etc/nginx# #每次改動nginx的配置檔案,都需要進入容器的內部修改,非常麻煩,後面學習資料卷的技術就可以在容器外部修改檔案,容器內自動同步。
訪問自己伺服器的nginx:http://39.105.48.232:3344/(前提是自己阿里雲伺服器安全組中開啟了3344埠)
部署Tomcat
#docker hub 官方的使用
docker run -it --rm tomcat:9.0
#之前練習的啟動在後臺,停止容器後,容器還在,可以查到。run -it --rm 一般用來測試,用完即刪除(容器刪除映象還在)
[root@zhourui /]# docker pull tomcat
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 9.0 040bdb29ab37 2 months ago 649MB
tomcat latest 040bdb29ab37 2 months ago 649MB
nginx latest f6d0b4767a6c 2 months ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
[root@zhourui /]# docker run -d -p 3355:8080 --name tomcat01 tomcat
53197d7745a2d7f83f3a45b1f474a189eb7f496b0cf08c9a509a6c390680e347
[root@zhourui /]# curl localhost:3355
瀏覽器測試訪問:http://39.105.48.232:3355/(阿里雲安全組開啟埠),可以訪問但是顯示404。
#進入容器
[root@zhourui /]# docker exec -it tomcat01 /bin/bash
root@53197d7745a2:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@53197d7745a2:/usr/local/tomcat# cd webapps
root@53197d7745a2:/usr/local/tomcat/webapps# ls
root@53197d7745a2:/usr/local/tomcat/webapps#
#發現ll無法使用,ls-al可以使用,命令少了。webapps中是空的,預設的是最小的映象,不必要的被刪除了,保證的是最小可用環境。
如果想要訪問,可以複製webapps.dist目錄的內容到webapps中
root@53197d7745a2:/usr/local/tomcat/webapps# cd ..
root@53197d7745a2:/usr/local/tomcat# cd webapps.dist
root@53197d7745a2:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
root@53197d7745a2:/usr/local/tomcat/webapps.dist# cd ..
root@53197d7745a2:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@53197d7745a2:/usr/local/tomcat# cd webapps
root@53197d7745a2:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@53197d7745a2:/usr/local/tomcat/webapps#
再次重新整理網頁訪問即可!
部署es+kibana
#es暴漏的埠十分多
#es十分耗記憶體
#es的資料一般需要放置到安全目錄,掛載。
#--net somenetwork 網路配置
#啟動(啟動前停掉其它的容器,防止啟動不了)
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
#docker stats 容器id 檢視cpu的狀態
#啟動後 發現執行docker ps命令非常卡,因為記憶體快耗盡。
啟動後可以從寶塔上看到自己伺服器的記憶體狀態。(也可以使用命令docker stats 容器id 檢視cpu,記憶體的狀態)
停掉es
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
94c6cad2a01d elasticsearch:7.6.2 "/usr/local/bin/dock…" 5 minutes ago Up 5 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch
[root@zhourui /]# docker stop 94c6cad2a01d
94c6cad2a01d
這時檢視伺服器的狀態
再次啟動,增加記憶體的配置,修改配置檔案,-e 環境配置修改。
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
視覺化
- portainer(圖形化介面管理工具,提供一個皮膚供操作)
docker run -d -p 9222:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- Rancher(CI/CD 持續整合/持續部署時使用)
啟動portainer後訪問測試:http://39.105.48.232:9222/,密碼可以隨意輸入。
進入後選擇local,點選connect
可以看到映象,容器等
檢視映象
Docker映象
映象是什麼:映象是一種輕量級的,可執行的獨立軟體包。用來打包軟體執行環境和基於執行環境開發的軟體,它包含執行某個軟體所需的所有內容,包括程式碼,執行時,庫,環境變數和配置檔案。
將應用直接打包為docker映象,就可以直接跑起來。
如何得到映象:
- 從倉庫下載
- 自己製作一個映象
Docker映象載入原理
UnionFS(聯合檔案系統):Union檔案系統(UnionFS)是一種分層,輕量級並且高效能的檔案系統,它支援對檔案系統的修改作為一次提交來一層層的疊加,同時可以將不同的目錄掛載到同一個虛擬檔案系統下。Union檔案系統是 docker 映象的基礎。映象可以通過分層來進行繼承,基於基礎映象(沒有父映象),可以製作具體的應用映象。
特性:一次同時載入多個檔案系統,但從外面看起來,只能看到一個檔案系統,聯合載入會把各層檔案系統疊加起來,這樣最終的檔案系統會包含所有底層的檔案和目錄。
Docker映象載入原理:docker映象實際上是由一層一層的檔案系統組成,這種層級的檔案系統叫UnionFS(聯合檔案系統)。
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引導載入kernel,Linux剛啟動時會載入bootfs檔案系統,在Docker映象的最底層是bootfs,這一層與我們典型的Linux/Unix系統是一樣的,包含boot載入和核心,當boot載入完之後整個核心都在記憶體中了,此時記憶體的使用權已由bootfs轉交給核心,此時系統也會解除安裝bootfs。
rootfs(root file system)在bootfs之上,包含的就是典型LInux系統中的 /dev,/proc,/bin,/etc等標準目錄和檔案,rootfs就是各種不同的作業系統發行版,比如Ubantu,Centos等。
可以使用docker images看到Centos的映象非常小。
對於一個精簡的OS,rootfs可以很小,只需包含最基本的命令,工具和程式庫就可以了,因為底層直接用Host的kernel,自己只需提供rootfs就可以了,因此可見對於不同的Linux發行版,bootfs基本是一致的,rootfs會有差別,因此不同的發行版可以共用bootfs。
分層理解
下載一個映象,觀察日誌輸出,可以看到是一層一層的在下載(分層下載,提高了複用性)
使用docker inspect redis,可以看到RootFS
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864",
"sha256:8e14cb7841faede6e42ab797f915c329c22f3b39026f8338c4c75de26e5d4e82",
"sha256:1450b8f0019c829e638ab5c1f3c2674d117517669e41dd2d0409a668e0807e96",
"sha256:f927192cc30cb53065dc266f78ff12dc06651d6eb84088e82be2d98ac47d42a0",
"sha256:a24a292d018421783c491bc72f6601908cb844b17427bac92f0a22f5fd809665",
"sha256:3480f9cdd491225670e9899786128ffe47054b0a5d54c48f6b10623d2f340632"
]
},
理解:所有的Docker映象都起始於一個基礎映象層,當進行修改或增加新的內容時,都會在當前的映象層上,建立新的映象層。在新增額外的映象層時,映象始終保持是當前所有映象的組合。
特點:
docker映象都是隻讀的,當容器啟動時,一個新的可寫層被載入到映象的頂部。這一層通常是我們所說的容器層,容器之下都是映象層。
commit映象
docker commit #提交容器成為一個新的副本
#命令和git類似
docker commit -m=“提交描述資訊” -a=“作者” 容器id 目標映象名:[TAG]
測試
#啟動一個tomcat
docker run -it -p 8081:8080 tomcat
#在新的視窗進入tomcat
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS 1fd9b7b4cb3d tomcat "catalina.sh run" 28 seconds ago Up 27 seconds 0.0.0.0:8081->8080/tcp
[root@zhourui /]# docker exec -it 1fd9b7b4cb3d /bin/bash
#官方預設的tomcat的webapps下面沒有應用,自己拷貝
cp -r webapps.dist/* webapps
#提交自己的映象,以後使用修改過的映象即可
[root@zhourui /]# docker commit -a="zhourr" -m="add webapps" 1fd9b7b4cb3d tomcat02:1.0
sha256:1c7804b415ba38099178f63e48444aebec938252632defd16bb35acc71bdabab
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 1c7804b415ba 6 seconds ago 654MB
redis latest 621ceef7494a 2 months ago 104MB
tomcat 9.0 040bdb29ab37 2 months ago 649MB
tomcat latest 040bdb29ab37 2 months ago 649MB
nginx latest f6d0b4767a6c 2 months ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
portainer/portainer latest 62771b0b9b09 8 months ago 79.1MB
elasticsearch 7.6.2 f29a1ee41030 12 months ago 791MB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
[root@zhourui /]#
對容器進行修改後,想儲存容器的狀態,通過commit來提交,下次就可以使用自己提交的這個映象了。就好比 vm 的快照功能。
容器資料卷
如果資料在容器中,那麼將容器刪除,資料就會丟失!需求,資料可持久化!!
MySQL容器刪除,資料丟失,需求,MySQL資料可以儲存在本地!!
容器之間可以有一個資料共享的技術。Docker容器中產生的資料,同步到本地。
這就是卷技術!將容器內的目錄,掛載到主機上。
資料持久化和同步操作,容器間也是可以資料共享的。
使用資料卷
方式一:使用命令來掛載 -v
docker -it -v主機內的目錄:容器內的目錄
#測試
[root@zhourui home]# docker run -it -v /home/zrtest:/home centos /bin/bash
#啟動後使用 docker inspect 容器id 檢視
使用 docker inspect 容器id 檢視
測試檔案的同步
1.停止容器
2.修改宿主機上的檔案
3.啟動容器,發現檔案依舊是同步的
好處:以後修改只需要在本地修改即可,不需要進入容器!
部署MySQL
MySQL的資料持久化問題!
#獲取映象
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
#在本地連線上後建立一個test資料庫,檢視對映路徑是否可以。
在本地使用Navicat測試連線
將容器刪除後
[root@zhourui data]# ls
auto.cnf ca.pem client-key.pem ibdata1 ib_logfile1 mysql private_key.pem server-cert.pem sys
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 ibtmp1 performance_schema public_key.pem server-key.pem test
可以看到test資料庫還在,即掛載到本地的資料卷沒有丟失,這就實現了容器資料的持久化。
具名掛載和匿名掛載
#匿名掛載
-P(大寫P 隨機對映埠)
-v 容器內路徑
docker run -d -P --name nginx01 -v /etc/nginx nginx
#檢視所有的卷的情況
[root@zhourui home]# docker volume ls
DRIVER VOLUME NAME
local 42a60ffb1a9dfcefffdf269e3a08fcb9172a082babe6ea19b864d5f679eb4361
local 93e2f2060025965b83b0433b95e29ac325c25fa8684b79a12617438ffe898941
local 271ccfa1da7814fa8fceb5b482ce86009f97e29c09dca69bcc594a0d8fabb92a
#匿名掛載:這裡-v的時候只寫了容器內的路徑,沒有寫容器外的路徑
#具名掛載
[root@zhourui home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
3024685007a57eda45820c8c07920cea08b84b7847b86fd97f5f71f7100b8fbd
[root@zhourui home]# docker volume ls
DRIVER VOLUME NAME
local 42a60ffb1a9dfcefffdf269e3a08fcb9172a082babe6ea19b864d5f679eb4361
local 93e2f2060025965b83b0433b95e29ac325c25fa8684b79a12617438ffe898941
local 271ccfa1da7814fa8fceb5b482ce86009f97e29c09dca69bcc594a0d8fabb92a
local juming-nginx
[root@zhourui home]#
#通過-v 卷名:容器內名字
#檢視卷
[root@zhourui home]# docker volume inspect juming-nginx
所有docker容器內的卷,在沒有指定目錄的情況下都是在 /var/lib/docker/volumes/xxxx/_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,就說明這個檔案只能通過宿主機來操作,容器內部是無法操作的!
初識Dockerfile
Dockerfile就是用來構建 docker 映象的構建檔案!命令指令碼!
通過這個指令碼可以生成映象。映象是一層一層的,指令碼是一個個的命令,每個命令都是一層。
方式二:
[root@zhourui home]# pwd
/home
[root@zhourui home]# cd docker-test-volume/
[root@zhourui docker-test-volume]# pwd
/home/docker-test-volume
[root@zhourui docker-test-volume]# vim dockerfile #建立dockerfile
[root@zhourui docker-test-volume]# cat dockerfile #檔案中新增以下內容後檢視(檔案中內容 指令(大寫) 引數)
#每個命令就是映象的一層
FROM centos
VOLUME ["volume01","volume02"] #匿名掛載
CMD echo "....end...."
CMD /bin/bash
[root@zhourui docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile -t zhour/centos:1.0 .
#啟動自己生成的容器
docker run -it 29e054de9dd4 /bin/bash
#在volume01中建立檔案
[root@e224b7ebc0d7 volume01]# ls
[root@e224b7ebc0d7 volume01]# touch container.txt
[root@e224b7ebc0d7 volume01]# ls
container.txt
[root@e224b7ebc0d7 volume01]#
檢視匿名卷掛載的路徑:docker inspect 容器id
進入掛載的路徑中檢視
[root@zhourui /]# cd /var/lib/docker/volumes/f517ef934bb1d4376751cf0ec11608ed0fd287844436ba62cad973ce0f67dee8/_data
[root@zhourui _data]# ls
container.txt
[root@zhourui _data]#
可以看到檔案已經同步!!
這種方式較常使用,通常用於構建自己的映象。
假設構建映象時沒有掛載卷,需要手動掛載,-v 卷名:容器內路徑。
資料卷容器
啟動三個容器
#建立docker01
[root@zhourui /]# docker run -it --name docker01 29e054de9dd4
[root@255f9d13bea7 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
#建立docker02
[root@zhourui /]# docker run -it --name docker02 --volumes-from docker01 29e054de9dd4
[root@861b5d25a8ca /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
#在docker01的volume01中建立檔案
[root@zhourui /]# docker attach 255f9d13bea7
[root@255f9d13bea7 /]# cd volume01
[root@255f9d13bea7 volume01]# ls
[root@255f9d13bea7 volume01]# touch docker01
#進入docker02的volume01中檢視
[root@861b5d25a8ca /]# cd volume01
[root@861b5d25a8ca volume01]# ls
docker01
#建立docker03並在volume01中增加docker03檔案
[root@zhourui /]# docker run -it --name docker03 --volumes-from docker01 29e054de9dd4
[root@7a405584084a /]# cd volume01
[root@7a405584084a volume01]# ls
docker01
[root@7a405584084a volume01]# touch docker03
[root@7a405584084a volume01]# ls
docker01 docker03
#在docker01中檢視volume01
[root@255f9d13bea7 volume01]# ls
docker01 docker03
[root@255f9d13bea7 volume01]#
通過 --volumes-from 可以實現容器間的資料共享!!
可以測試刪除掉 docker01 ,再去檢視 docker02 和 docker03 ,資料仍然還在。
三個容器之間的檔案是相互拷貝的,刪掉一個不會丟失資料。
應用:多個 MySQL 或者 Redis 之間實現資料共享!!
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
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
#可以實現兩個MySQL之間的資料同步
結論:容器之間配置資訊的傳遞,資料卷容器的生命週期是一直持續到沒有容器使用為止。
通過 -v 將資料持久化到本地,本地的資料是不會刪除的。
DockerFile
DockerFile介紹
dockerfile是用來構建 docker 映象的檔案。命令引數指令碼。
構建步驟:
- 編寫一個 dockerfile 檔案
- docker build 構建成為一個映象
- docker run 執行映象
- docker push 釋出映象(dockerHub,阿里雲映象倉庫)
檢視官方 centos,點選版本會跳轉至 GitHUb
很多的官方映象都是基礎包,一些功能沒有,我們就需要自己搭建。
DockerFile構建過程
基礎知識:
- 每個保留關鍵字(指令)必須是大寫字母。
- 只需順序從上到下。
-
, 表示註釋。
- 每個指令都會建立提交一個新的映象層。
docker 是面向開發的,釋出專案做映象,就需要編寫 dockerfile 檔案。
Docker映象逐漸成為企業交付的標準。
dockerfile :構建檔案,定義了一切所需的環境和原始碼。
dockerImage:通過 dockerfile 構建生成的映象,最終釋出和執行的產品。
docker 容器:容器是映象執行起來後提供服務的。
DockerFile指令
FROM #基礎映象,一切從這裡開始構建
MAINTAINER #映象是誰寫的
RUN #docker 映象構建的時候需要執行的命令
ADD #步驟:使用tomcat映象,tomcat壓縮包,就是新增的內容
WORKDIR #映象的工作目錄
VOLUME #掛載的目錄位置
EXPOSE #暴漏埠配置
CMD #指定這個容器啟動的時候要執行的命令,只有最後一個會生效,可被替代
ENTRYPOINT #指定這個容器啟動的時候要執行的命令,可以追加命令
ONBUILD #當構建一個被繼承的 dockerfile 這個時候會執行 ONBUILD 的指令,觸發指令
COPY #類似add命令,將檔案拷貝拷貝到目錄中
ENV #構建的時候設定環境變數
實戰測試
Docker Hub 中99%的映象都是由這個基礎映象 FROM scratch 來配置構建的
FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201204"
CMD ["/bin/bash"]
建立一個自己的 CentOS
#編寫 dockerfile 的檔案
[root@zhourui home]# cd dockerfile/
[root@zhourui dockerfile]# ls
[root@zhourui dockerfile]# vim mydockerfile-centos
[root@zhourui dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER zhourr<813794474@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH #進去後的工作目錄,進去後 pwd 檢視
RUN yum -y install vim #安裝 vim
RUN yum -y install net-tools #安裝後可以使用 ifconfig (不安裝只能用 ip add)
EXPOSE 80
CMD echo $MYPATH
CMD echo "...end..."
CMD /bin/bash
#通過這個檔案構建映象
-f 構建檔案路徑
-t 映象名:[tag]
最後有個 .
[root@zhourui dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
...
Successfully built ddba7ccc7eee
Successfully tagged mycentos:0.1
#測試執行
docker run -it mycentos:0.1
預設的 centos 以下命令無法使用
[root@95c725dda358 /]# pwd
/
[root@95c725dda358 /]# vim
bash: vim: command not found
[root@95c725dda358 /]# ifconfig
bash: ifconfig: command not found
[root@95c725dda358 /]#
測試執行自己建立的映象這些命令就可以使用了。
我們可以列出本地映象的變更歷史 docker history 映象id
CMD和ENTRYPOINT的區別
CMD #指定這個容器啟動的時候要執行的命令,只有最後一個會生效,可被替代
ENTRYPOINT #指定這個容器啟動的時候要執行的命令,可以追加命令
測試 CMD
[root@zhourui dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
#構建映象
[root@zhourui dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
....
Successfully built a44c7103184f
Successfully tagged cmdtest:latest
# run 執行,可以看到 ls-a 命令生效
[root@zhourui dockerfile]# docker run a44c7103184f
.
..
.dockerenv
bin
dev
etc
home
lib
...
#追加一個 l ,希望返回 ls-al
[root@zhourui dockerfile]# docker run a44c7103184f -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
#此時報錯,因為使用CMD,-l替換了["ls","-a"],-l不是命令,所以報錯
#需要使用以下完整命令
[root@zhourui dockerfile]# docker run a44c7103184f ls -al
測試 ENTRYPOINT
[root@zhourui dockerfile]# vim dockerfile-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
[root@zhourui dockerfile]# docker build -f dockerfile-entrypoint -t entrypointtest .
...
Successfully built 34773b8b0398
Successfully tagged entrypointtest:latest
[root@zhourui dockerfile]# docker run 34773b8b0398
.
..
.dockerenv
bin
dev
etc
home
lib
...
# 新增 -l,是可以直接追加到後面的,ls -a -l
[root@zhourui dockerfile]# docker run 34773b8b0398 -l
total 0
drwxr-xr-x 1 root root 6 Mar 27 14:51 .
drwxr-xr-x 1 root root 6 Mar 27 14:51 ..
-rwxr-xr-x 1 root root 0 Mar 27 14:51 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 340 Mar 27 14:51 dev
drwxr-xr-x 1 root root 66 Mar 27 14:51 etc
drwxr-xr-x 2 root root 6 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
Docker中很多命令都十分相似,需要去對比測試一下,才能發現其中的區別。
實戰 Tomcat映象
-
準備映象檔案 tomcat 壓縮包,jdk壓縮包(放到home/zhour-tar目錄下)
-
編寫 Dockerfile 檔案,官方命名:Dockerfile,build的時候會自動尋找這個檔案,就不需要 -f 指定了。(在home/zhour-tar目錄下,vim Dockerfile),壓縮包會自動解壓。
FROM centos MAINTAINER zhourr<813794474@qq.com> COPY readme.txt /usr/local/read.txt ADD jdk-8u281-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.44.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_281 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.44 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.44 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.44/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.44/bin/logs/catalina.out
-
構建映象
[root@zhourui zhour-tar]# ls apache-tomcat-9.0.44.tar.gz Dockerfile jdk-8u281-linux-x64.tar.gz readme.txt #構建 [root@zhourui zhour-tar]# docker build -t diytomcat .
-
啟動映象
[root@zhourui zhour-tar]# docker run -d -p 3030:8080 --name zhoutomcat -v /home/zhour-tar/test:/usr/local/apache-tomcat-9.0.44/webapps/test -v /home/zhour-tar/tomcatlogs/:/usr/local/apache-tomcat-9.0.44/logs diytomcat
-
訪問測試
-
釋出專案(配置了資料卷掛載,直接在容器外編寫專案就可以釋出了)在test中新建
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> </web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello zhourrr!!</title> </head> <body> Hello World!<br/> <% System.out.println("----my tomcat test----"); %> </body> </html>
-
訪問http://39.105.48.232:3030/test/
-
日誌檢視,cd /home/zhour-tar/tomcatlogs。cat catalina.out
需要掌握 Dockersfile 的編寫!!
釋出映象
在 Docker Hub 上註冊賬號,在伺服器登入後就可以提交自己的映象了。
[root@zhourui 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@zhourui tomcatlogs]# docker login -u zhourui88
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
提交
[root@zhourui tomcatlogs]# docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
e21bfbb06ee5: Preparing
145f6d70801c: Preparing
f3ba2f2219d6: Preparing
f83a7c49f1e3: Preparing
2653d992f4ef: Preparing
denied: requested access to the resource is denied #拒絕
#需要增加一個tag
[root@zhourui tomcatlogs]# docker tag ea84d80641b1 zhourui88/tomcat:1.0
#檢視
[root@zhourui tomcatlogs]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diytomcat latest ea84d80641b1 About an hour ago 640MB
zhourui88/tomcat 1.0 ea84d80641b1 About an hour ago 640MB
#提交
[root@zhourui tomcatlogs]# docker push zhourui88/tomcat:1.0
提交的時候映象也是按層級來提交的!
阿里雲伺服器
-
登入阿里雲
-
找到容器映象服務
-
建立名稱空間
-
建立容器映象
-
點選映象倉庫名 zhourui-test 瀏覽阿里雲
#登入
[root@zhourui /]# sudo docker login --username=周銳822 registry.cn-beijing.aliyuncs.com
#提交到阿里雲,這裡沒有更改tag,顯示上傳成功,但是我沒有找到映象
[root@zhourui /]# docker push zhourui88/tomcat:1.0
The push refers to repository [docker.io/zhourui88/tomcat]
e21bfbb06ee5: Layer already exists
145f6d70801c: Layer already exists
f3ba2f2219d6: Pushing [==========> ] 77.66MB/356.6MB
f83a7c49f1e3: Layer already exists
#上傳阿里雲
[root@zhourui /]# sudo docker tag ea84d80641b1 registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test:1.0
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED
diytomcat latest ea84d80641b1 3 hours ago
zhourui88/tomcat 1.0 ea84d80641b1 3 hours ago
registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test 1.0 ea84d80641b1 3 hours ago
[root@zhourui /]# docker push registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test:1.0
上傳後檢視
小結
Docker網路
理解 Dockers0
ip addr
#啟動容器
[root@zhourui /]# docker run -d -P --name tomcat01 tomcat
72dee6c91e3f593c69858191014b9d228c6494b0aa049cd1f620350c1c46cd56
#檢視容器內部網路地址 eth0@if123 ip地址 docker分配的
[root@zhourui /]# 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
122: eth0@if123: <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@zhourui /]# 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.062 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.045 ms
原理:我們每啟動一個 docker 容器,docker就會給docker容器分配一個ip,我們只要安裝了docker,就會有一個網路卡docker0.
橋接模式,使用的技術是 evth-pair 技術
這時再輸入 ip addr,發現多了一個網路卡
再啟動一個 tomcat02 發現又多了一個網路卡 (docker run -d -P --name tomcat02 tomcat) ipaddr
檢視tomcat02 ip addr
[root@zhourui /]# docker exec -it tomcat02 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
124: eth0@if125: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
可以發現容器的網路卡都是一對一對的,【122: eth0@if123】【124: eth0@if125】。
evth-pair:就是一對虛擬裝置介面,它們都是成對出現的,一段連著協議,一段彼此相連。
所以,evth-pair就充當一個橋樑,連線各種虛擬網路裝置。
測試tomcat01和tomcat02之間能不能ping通:
[root@zhourui /]# 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.091 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.069 ms
#可以看到,容器之間是可以通訊的
流程圖理解
tomcat01 和 tomcat02 是公用一個路由器 docker0 。
所有容器不指定網路的情況下,都是 docker0 路由的,doker會給容器分配一個預設的可用 ip。
Docker使用的是 Linux 的橋接,宿主機中是 Docker 容器的網橋(Docker0)
Docker 中所有的網路介面都是虛擬的,虛擬的轉發效率高。
只要刪除容器,對應的網橋就沒了。
docker network ls,docker network inspect (橋接network id)可以檢視
--link
假設我們想通過容器的名字來ping,而不是通過ip,就需要使用 --link。
[root@zhourui /]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
#通過--link可以解決
[root@zhourui /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
131bbb6e180687ff284ef2cabc78f4104dfc5d1018ee1e2f11a5b6e192bdc8bb
[root@zhourui /]# 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.101 ms
#反向ping
[root@zhourui /]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
docker network ls,docker network inspect (橋接network id)可以檢視
--link 使用後,tomcat03在本地配置了tomcat02
[root@zhourui /]# 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 1fff64acaf04
172.17.0.4 131bbb6e1806
本質:在hosts的配置中增加了 tomcat02 的對映。
真實開發中,已經不建議使用 --link 了。
自定義網路,不使用 docker0。docker0不支援容器名連線訪問。
自定義網路
檢視所有的docker網路
[root@zhourui /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
25000c3be4a4 bridge bridge local #橋接
b518cb3beba9 host host local
bcd06ce03d47 none null local
網路模式
bridge:橋接(docker預設)自己建立也使用 bridge 模式
none:不配置網路
host:和宿主機共享網路
container:容器內網路聯通(侷限性很大)
測試:
#直接啟動,預設是 --net bridge 的,
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
# --gateway 192.168.0.1
[root@zhourui /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
6219f386e2bfc7f837554de2b011ec1d649d6eaafa617fcf4bdd2d8091cf82b2
[root@zhourui /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
25000c3be4a4 bridge bridge local
b518cb3beba9 host host local
6219f386e2bf mynet bridge local
bcd06ce03d47 none null local
檢視自己的網路:docker network inspect mynet
建立兩個容器,連上自己的網路
[root@zhourui /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
c638c0cee8dff978e60532b9a1ddac74f10a45bfb6b542bf3fd3079f69ec5515
[root@zhourui /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
e9aee8d922b19af82f02e9e50b28a301ab10e7eb57828c454cb57b9ac5bdc0ae
[root@zhourui /]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "6219f386e2bfc7f837554de2b011ec1d649d6eaafa617fcf4bdd2d8091cf82b2",
"Created": "2021-03-28T17:29:39.571024726+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": {
"c638c0cee8dff978e60532b9a1ddac74f10a45bfb6b542bf3fd3079f69ec5515": {
"Name": "tomcat-net-01",
"EndpointID": "6d4ac08b616e2e33e8fb7a3e8659b5a6ff2e381083572dbe202f7b8598347177",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"e9aee8d922b19af82f02e9e50b28a301ab10e7eb57828c454cb57b9ac5bdc0ae": {
"Name": "tomcat-net-02",
"EndpointID": "187733df51f17912e402211643ce7136cbb725d85a0c1045ef7e903471d9f878",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
#再次測試 ping 連線
[root@zhourui /]# 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.115 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.067 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.068 ms
^C
--- 192.168.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 67ms
rtt min/avg/max/mdev = 0.067/0.083/0.115/0.023 ms
#不使用 --link。也可以ping名字了
[root@zhourui /]# 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.075 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.086 ms
自定義的網路donker幫我們維護好了關係,推薦使用自定義的網路。
應用:
redis:不同的叢集使用不同的網路,保證叢集是安全和健康的(192.168.xxx.xxx)
mysql:不同的叢集使用不同的網路,保證叢集是安全和健康的(192.182.xxx.xxx)
網路聯通
建立兩個容器在預設的docker0網路下
[root@zhourui /]# docker run -d -P --name tomcat01 tomcat
[root@zhourui /]# docker run -d -P --name tomcat02 tomcat
現在就有以下的四個容器在在 docker0 和 mynet 網路下。怎樣去打通 tomcat01 連線到 mynet。
通過 --help 檢視命令
測試打通 tomcat01 連線到 mynet
[root@zhourui /]# docker network connect mynet tomcat01
[root@zhourui /]# docker network inspect mynet
#打通之後,tomcat01被放到了 mynet 網路下,
#一個容器兩個 ip 地址
測試
[root@zhourui /]# 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.092 ms
#反向也是可以ping通的
[root@zhourui /]# docker exec -it tomcat-net-01 ping tomcat01
PING tomcat01 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.118 ms
#tomcat02 是沒有連線上 mynet 的
[root@zhourui /]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
結論:如果需要跨網路操作,就需要使用 docker network connect 網路 容器名稱 來聯通!!
部署Redis叢集
#建立redis的網路
docker network create redis --subnet 172.38.0.0/16
#通過指令碼建立6個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 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
#建立叢集
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
[root@zhourui /]# 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: 1524f57c751c662847b24edb3cf4433e42e11dae 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 3d0a68b584e5935b6174d8b8e0603a14eb246393 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: cce404917b84b790cf39ac1f6dff85c1c080c9a1 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 2fb9e53fde60fb288e87a8bccf37f2d521c5f5be 172.38.0.14:6379
replicates cce404917b84b790cf39ac1f6dff85c1c080c9a1
S: d977bb4c2b2a45bbbeb74cc123bd87dba1acd257 172.38.0.15:6379
replicates 1524f57c751c662847b24edb3cf4433e42e11dae
S: 317ccf18aefe00a7a45820b6509bd8c9fc1f7097 172.38.0.16:6379
replicates 3d0a68b584e5935b6174d8b8e0603a14eb246393
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: 1524f57c751c662847b24edb3cf4433e42e11dae 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: cce404917b84b790cf39ac1f6dff85c1c080c9a1 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 3d0a68b584e5935b6174d8b8e0603a14eb246393 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 317ccf18aefe00a7a45820b6509bd8c9fc1f7097 172.38.0.16:6379
slots: (0 slots) slave
replicates 3d0a68b584e5935b6174d8b8e0603a14eb246393
S: d977bb4c2b2a45bbbeb74cc123bd87dba1acd257 172.38.0.15:6379
slots: (0 slots) slave
replicates 1524f57c751c662847b24edb3cf4433e42e11dae
S: 2fb9e53fde60fb288e87a8bccf37f2d521c5f5be 172.38.0.14:6379
slots: (0 slots) slave
replicates cce404917b84b790cf39ac1f6dff85c1c080c9a1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/data # redis-cli -c
127.0.0.1:6379> cluster info
127.0.0.1:6379> cluster nodes
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK
172.38.0.13:6379>
#新建視窗 docker stop redis-3
#獲取 a 的值
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
搭建redis叢集完成!!
SpringBoot打包Dockers映象
-
構建一個SpringBoot專案
@RestController public class HelloController { @RequestMapping("/hello") public String hello(){ return "Hello zhour!"; } }
-
打包應用,package
-
編寫dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["---server port 8080---"] EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]
-
構建映象(使用 ftp 將檔案上傳至伺服器)
[root@zhourui idea]# ls demo-docker-0.0.1-SNAPSHOT.jar Dockerfile [root@zhourui idea]# docker build -t boottestzr .
-
釋出執行
[root@zhourui idea]# docker run -d -P --name ideaboot-web boottestzr
-
訪問
如需瀏覽器訪問,阿里雲開發埠,或者執行時 -p 暴漏已開放的埠即可!!