文章目錄
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倉庫:商店) — 下載我們發佈的鏡像 – 直接運行即可
Docker的思想來自於集裝箱
JRE – 多個應用 (端口衝突) – 原來都是交叉的
隔離:Docker核心思想–>打包裝箱. 每個箱子是互相隔離的
Docker給以上的問題,提出瞭解決方案.
虛擬機技術缺點:
1, 資源佔用十分多
2, 冗餘步驟多
3, 啓動很慢
Docker的歷史
Docker能幹嘛
容器化技術
容器化技術並不是模擬一個完整的操作系統
比較Docker和虛擬機技術的不同:
- 傳統虛擬機,虛擬出一條硬件,運行一個 完整的操作系統,然後在這個系統上安裝和運行軟件
- 容器內的應用直接運行在宿主機的內容, 容器是沒有自己的內核的,也沒有虛擬我們的硬件,所以就輕便了
- 每個容器間是相互隔離的,每個容器內部都有一個屬於自己的文件系統,互不影響
DevOps(開發,運維)
應用更快速的交付和部署
傳統:一堆幫助文檔,安裝程序
Docker:打包鏡像發佈測試,一鍵運行
更便捷的升級和擴縮容
使用了Docker之後,我們部署應用就和搭積木一樣
項目打包爲一個鏡像,水平擴展服務器A,服務器B
更簡單的系統運維繫統
在容器化之後,我們的開發,測試環境都是高度一致的.
更高效的計算資源利用
1核2g的服務器 可以同時運行幾十個tomcat?!!!
Docker是內核級別的虛擬化,可以在一個物理機上運行很多的容器實例
服務器的性能可以被壓榨到極致!
Docker安裝
Docker的基本組成
鏡像(image):
docker鏡像就好比是一個模板,可以通過這個模板來創建容器服務,tomcat鏡像–>run—>tomcat01容器(提供服務器).通過這個鏡像可以創建多個容器(最終服務運行或者項目運行就是在容器中的).
容器(container):
Docker利用容器技術,獨立運行一個或者-個組應用 ,通過鏡像來創建的。啓動,停止,刪除,基本命令!
目前就可以把這個容器理解爲就是一個簡易的linux系統.
倉庫(repository):
倉庫就是存放鏡像的地方.
倉庫分爲公有倉庫和私有倉庫.
Docker Hub(默認是國外的)
像阿里雲之類的大型企業都有容器服務器(配置鏡像加速)
安裝Docker
環境準備
- 需要會一點點的Linux基礎
- CentOS 7
- 我們使用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查看是否安裝成功
# 7.使用hello owrld測試
$ sudo docker run hello-world
# 判斷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的默認工作路徑
阿里雲鏡像加速
登錄阿里雲找到容器服務
找到鏡像加速地址
配置使用
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流程
run的運行流程圖
底層原理
Docker是怎麼工作的?
Docker是一個Client -Server結構的系統, Docker的守護進程運行在主機上。通過Socket從客戶端訪問.
DockerServer接收到Docker-Client的信息,就會執行這條命令.
Docker爲什麼比VM快?
-
Docker有比虛擬機更少的抽象層
-
Docker利用的是宿主機的內核,vm是需要Guest OS.
-
所以說,新建一個容器的時候,docker不需要像虛擬機一樣重新加載一個操作系統內核,避免引導.虛擬機是加載Guest OS,分鐘級別的,而Docker是利用宿主機的操作系統,省略了這個複雜的過程,秒級!
學習完畢所有的命令,再回過頭來看這段理論就會很清晰.
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
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 卷的技術,可以實現
小結
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
我們現在每次改動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,因爲他們是互相隔離的,那麼如何解決呢?
可視化
- 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/ (第一次訪問較慢,但是我加載很快,嘻嘻~)
通過它來訪問了:
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等等。
平時我們安裝進虛擬機的CentOS都是好幾個G,爲什麼Docker這裏才200M?
對於一個精簡的OS , rootfs可以很小,只需要包含最基本的命令,工具和程序庫就可以了,因爲底層直接用Host的kernel,自己只需要提供rootfs就可以了。由此可見對於不同的linux發行版bootfs基本是一致的, rootfs會有差別,因此不同的發行版可以公用bootfs.
虛擬機是分鐘級的,容器是秒級
分層理解
分層的鏡像
我們可以去下載一個鏡像,注意觀察下載的日誌輸出,可以看到是一層一層的在下載!
思考:爲什麼Docker鏡像要採用這種分層的結構呢?
最大的好處,我覺得莫過於是資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那麼宿主機只需在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像 ,這樣就可以爲所有的容器服務了,而且鏡像的每一層都可以被共享。
查看鏡像分層的方式可以通過docker image inspect命令!
理解:
所有的Docker鏡像都起始於一個基礎鏡像層 ,當進行修改或增加新的內容時,就會在當前鏡像層之上,創建新的鏡像層。
舉一個簡單的例子,假如基於Ubuntu Linux 16.04創建一個新的鏡像 ,這就是新鏡像的第一-層 ;如果在該鏡像中添加Python包,就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就會創建第三個鏡像層。
該鏡像當前已經包含3個鏡像層,如下圖所示(這只是-個用於演示的很簡單的例子).
在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點非常重要。 下圖中舉了一個簡單的例子,每個鏡像層包含3個文件,而鏡像包含了來自兩個鏡像層的6個文件。
上圖中的鏡像層跟之前圖中的略有區別,主要目的是便於展示文件。
下圖中展示了一個稍微複雜的三層鏡像,在外部看來整個鏡像只有6個文件,這是因爲最上層中的文件7是文件5的一個更新版本。
這種情況下,上層鏡像層中的文件覆蓋了底層鏡像層中的文件。這樣就使得文件的更新版本作爲一個新鏡像層添加到鏡像當中。
Docker通過存儲引擎(新版本採用快照機制)的方式來實現鏡像層堆棧,並保證多鏡像層對外展示爲統一的文件系統。
Linux.上可用的存儲引擎有AUFS. Overlay2、 Device Mapper, Btrfs 以及ZFS.顧名思義,每種存儲引擎都基於Linux中對應的文件系統或者塊設備技術,並且每種存儲引擎都有其獨有的性能特點。
Docker在Windows.上僅支持windowsfilter -種存儲引擎,該引擎基於NTFS文件系統之上實現了分層和CoW[1]。
下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆疊併合並,對外提供統一的視圖。
特點
Docker鏡像都是隻讀的,當容器啓動時, 一個新的可寫層被加載到鏡像的頂部!
這一層就是我們通常說的容器層,容器之下的都叫鏡像層!
commit鏡像
docker commit 提交容器成爲一個新的副本
# 命令和git基本類似
docker commit -m="提交的描述信息" -a="作者" 容器id 目標鏡像名:[TAG]
實戰測試
# 啓動一個默認的tomcat
# 發現這個默認的tomcat webapps下沒有項目,官方的默認鏡像下就是沒有文件的
# 我們自己拷貝進去基本的文件,然後提交
# 將我們操作過的容器通過commit提交爲新的鏡像,我們以後就用我們修改過的鏡像就可以,這就是我們一個修改過的鏡像
如果你想要保存當前容器的狀態,就可以通過commit來提交,獲得一個鏡像
就好比我們以前學習VM時候,快照!
到這裏就算docker入門了.
容器數據卷
什麼是容器數據卷
docker的理念回顧
將應用和環境打包成一個鏡像
問題:如果數據都在容器中,如果我們將容器刪除,數據就會丟失
需求:數據可以持久化
容器之間可以有一個數據共享的技術,Docker容器中產生的數據,同步到本地
這就是卷技術,目錄的掛載,將我們容器內的目錄,掛載到Linux上面.
一句話:容器的持久化和同步操作,榮期間也是可以數據共享的
使用數據卷
方式一:直接使用命令來掛載 -v
docker run -it -v 主機目錄:容器內目錄
# 測試
[root@iZm5eicbmpex37r3ecz3h7Z es]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 啓動之後,查看容器元信息
docker inspect 容器id
測試文件的同步
再來測試
1.停止容器
2.主機上修改文件
3.啓動容器
4.容器內的數據依舊是同步的
好處 :我們以後修改只需要在本地修改即可,容器內會自動同步
實戰:安裝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
# 成功
如果我們將容器刪除,我們掛載到本地的數據卷依舊不會丟失,這就實現了容器數據持久化功能.
具名和匿名掛載
# 匿名掛載
-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
所有的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
這個目錄就是我們生成鏡像的時候自動掛載的,數據卷目錄
這個卷和外部一定有一個同步的目錄
查看一下掛載的路徑
# 新建一個文件
[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 卷名:容器內路徑
數據卷容器
多個容器同步數據
# 啓動3個容器,通過我們剛纔自己的鏡像啓動
docker run -it --name=docker01 kangyuan/centos:1.0
docker run -it --name docker02 --volumes-from docker01 kangyuan/centos:1.0
# 測試刪除docker01,查看docker02和docker03是否還可以訪問volume01中的文件
# 測試結果發現依舊可以訪問
多個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鏡像的文件 命令參數腳本
構建步驟:
- 編寫一個dockerfile文件
- docker build 構建成爲一個鏡像
- docker run 運行鏡像
- docker push 發佈鏡像(DockerHub,阿里雲鏡像倉庫)
查看一下官方是怎麼做的?
跳轉到了github,發現就是一個Dockerfile
很多官方鏡像都是基礎包,很多功能沒有,我們通常會自己搭建自己的鏡像
官方既然可以製作鏡像,我們當然也可以
Dockerfile構建過程
基礎知識:
- 每個保留關鍵字(指令)都必須是大寫字母
- 從上到下順序執行
- #表示註釋
- 每一個指令都會創建一個新的鏡像層,並提交
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 # 構建的時候設置環境變量
以前我們是使用別人的,現在我們知道了這些指令,練習自己寫一個鏡像
實戰測試
Dockerhub中99%的鏡像都是從這個基礎鏡像過來的 FROM scratch,然後配置需要的軟件和配置來進行的構建
創建一個自己的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
我們增加之後的鏡像
我們可以列出本地鏡像的變更歷史
我們平時拿到一個鏡像可以研究一下他是怎麼做的了
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鏡像
- 準備鏡像文件tomcat壓縮包,jdk壓縮包
- 編寫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
- 構件鏡像
docker build -t diytomcat .
- 啓動鏡像
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
- 訪問測試 成功
- 發佈項目(由於做了卷掛載,我們直接在本地編寫項目就可以發佈了)
<?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
- 地址 https://hub.docker.com/ 註冊自己的賬號
- 確定這個賬號可以登錄
- 在我們服務器上提交自己的鏡像
[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
- 登錄完畢後就可以提交鏡像了.就是一步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
提交中:
提交的時候也是按照鏡像的層級來進行提交的
阿里雲鏡像服務
- 登錄阿里雲
- 找到容器鏡像服務
- 創建命名空間
- 創建容器鏡像
- 瀏覽阿里雲
# 參考阿里雲給的示例
小結
Docker網絡原理
理解Docker0
清空所有環境
測試
三個網絡
# 問題: docker是如何處理容器網絡訪問的
[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容器內部
原理
-
我們每啓動一個docker容器,docker就會給docker容器分配一個ip,我們只要安裝了docker,就會有一個網卡docker0 橋接模式,使用的技術是veth-pair 技術
再次測試ip addr
-
再啓動一個容器測試,發現又多了一對網卡
# 我們發現這個容器帶來的網卡都是一對一對的 # veth-pair 就是一對的虛擬設備接口,他們都是成對出現的,一段連着協議,一段彼此相連 # 正因爲有了這個特性,veth-pair 充當一個橋樑,連接各種虛擬網絡設備的 # OpenStac ,Docker容器之間的連接,OVS的連接,都是使用veth-pair 技術
-
我們測試一下tomcat01和tomcat02是否可以ping通
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker exec -it tomcat02 ping 172.17.0.2 # 結論: 容器和容器之間是可以互相ping通的
繪製一個網絡模型圖:
結論:tomcat01和tomcat02是共用的一個路由器,docker0
所有的容器不指定網絡的情況下,都是docker0路由的,docker會給我們的容器分配一個默認的可用ip
-
小結
Docker使用的是Linux的橋接,宿主機中是一個Docker容器的網橋docker0.
Docker中的所有的網絡接口都是虛擬的,虛擬的轉發效率高.(內網傳遞文件)
只要容器刪除,對應網橋一對就沒了.
–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
其實這個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網絡
網絡模式
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
[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- 不同的集羣使用不同的網絡,保證集羣是安全和健康的
網絡連通
# 測試打通tomcat01 - mynet
[root@iZm5eicbmpex37r3ecz3h7Z tomcatlogs]# docker network connect mynet tomcat01
# 連通之後就是將tomcat01 放到了mynet網絡下
# 一個容器兩個ip地址
# 好比 阿里雲服務:公網ip 私網ip
# 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集羣
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集羣完成
Springboot微服務打包Docker鏡像
- 構建springboot項目
- 打包應用
- 編寫dockerfile
- 構建鏡像
- 發佈運行!
到這裏我們就完全夠用了Docker.
以後我們使用了Docker之後,給別人交付的就是一個鏡像即可