Docker | Docker技术基础梳理(五) - Docker网络管理
Docker | Docker技術基礎梳理(五) - Docker網絡管理
鏈接:
原文鏈接
原文鏈接:
https://gitbook.cn/books/5b8f3c471966b44b00d26541/index.html
一、Docker 鏡像相關概念深入
1.1 鏡像
鏡像是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基于運行環境開發的軟件,它包含運行某個應用所需的所有內容,包括代碼、庫、環境變量和配置文件
1.2 基礎鏡像(scratch)
基礎鏡像簡單來說就是不依賴其他鏡像,完全從 0 開始構建,其他鏡像是在其基礎上進行構建的。
Docker Hub 中 99 % 的鏡像都是通過在 base 鏡像中安裝和配置需要的軟件構建出來的。
簡單理解有兩層含義:
不依賴其他鏡像,從 scrach 構建。其他鏡像可以以他為基礎進行擴展構建。
所以,能成為 base 鏡像的通常是各種 Linux 發行版的 Docker 鏡像,比如 Ubuntu、CentOS 等。
1.3 修改基礎鏡像疑問
正因為多個容器共享同一個基礎 base 鏡像,假如,我們某一個容器修改了基礎鏡像的某個文件,比如 /etc 下的某個配置,那么會不會影響其他鏡像呢?
答案是當然不會的,修改會被限制在當前容器內,在上一篇也提到過,多個容器之間是相互隔離、保證安全的,也就是在下面要提到的 Copy-on-Write 特性。
1.3 UnionFS 聯合文件系統
Union 文件系統 ( UnionFS ) 是一種分層、輕量級并且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加。
同時,可以將不同目錄掛載到同一個虛擬文件系統下( unite serveral directories into a single virtual filesystem )。
聯合文件系統是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基于基礎 base 鏡像(無父鏡像),可以制作各種具體的應用鏡像。
不同的 docker 容器可以共享一些基礎的文件系統層,再加上自己獨有的改動層,大大提高了存儲效率。
特點:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。
二、Docker 鏡像分層原理及特點
2.1 分層引入
當通過 docker 下載鏡像時,比如 docker pull mongo 發現會下載多個文件,其實這一個個文件就是該鏡像的一層。
通過如下命令可以查看鏡像的分層信息:
docker history container-id
示例:
enter image description here
2.2 鏡像疊加過程
鏡像可以分多層,每一層都有自己的 ID 和大小信息。新鏡像都是從 base 鏡像一層層疊加生成的,每安裝一個軟件就在現有鏡像基礎上疊加一層。
鏡像疊加過程如下:
enter image description here
2.3 AnotherUnionFS
Docker中 的 AUFS(AnotherUnionFS) 就是一種聯合文件系統。AUFS 支持為每一個成員目錄(類似 git 分支)設定為只讀、讀寫和寫出權限,同時 AUFS 里有一個類似分層的概念,對只讀權限的分支可以邏輯上進行增量的修改,并且不影響只讀部分。
簡單理解就是已構建的鏡像會設置成只讀層,read-write 寫操作是在 read-only 上的一種增量操作,所以不會影響到 read-only 層。
Docker 目前支持的聯合文件系統種類包括 AUFS,btrfs,vfs 和 DeviceMapper。
2.4 bootfs 與 rootfs
bootfs:在 Docker 鏡像的最底層就是 bootfs,這一層與典型的 Linux/Unix 系統是一樣的,主要包含 boot 加載器和 kernel 內核,bootloader主要是引導加載 kernel,Linux 剛啟動時會加載 bootfs 文件系統。當 boot 加載完成后整個內存就都在內存中了,此時內存的使用權已有 bootfs 交給內核,系統也會在此時卸載 bootfs。rootfs:Docker 在 bootfs 之上的一層是 rootfs(根文件系統),包含的就是典型 Linux 系統中的 /dev,/proc,/bin,/etc 等標準目錄和文件。rootfs 就是各種不同的操作系統發行版,比如 Ubuntu,CentOS 等。
enter image description here
2.5 Docker 的 rootfs 與傳統 Linux 的 rootfs 對比
傳統的 Linux 加載 bootfs 時會先將 rootfs 設置成 read-only,然后在系統自檢之后將 rootfs 從 read-only 改為 read-write。這樣就可以在 rootfs 上進行讀寫操作了。Docker 鏡像開始也把 rootfs 設置成 read-only,但在 bootfs 自檢完畢后,并不會把 rootfs 的 read-only 改為 read-write,而是利用 union amount(UnionFS 的一種掛載機制)將一個 read-write 文件系統掛載在 read-only 的 rootfs 之上,并且運行再次將下層的文件系統設定為 read-only 并向上疊加,這樣一組 read-only 和一個 read-write 的結構構成一個 container 的運行目錄,每一個被稱為一個 layer,如下圖所示:
enter image description here
也就是說,當鏡像被啟動實例化成容器后,系統會為在一層或多層的 read-only 的 rootfs 之上分配一層空的 read-write 的 rootfs 容器層,這個分配動作是由 docker run 發起的。
2.6 深入容器細節
Docker 守護進程會在 Docker 鏡像的最上層之上,再添加一個可讀寫層,容器所有的寫操作都會作用到這一層中。而如果 Docker 容器需要寫底層 Docker 鏡像中的文件,那么此時就會涉及 Copy-on-Write 的機制,即 aufs 等聯合文件系統保證:首先將此文件從 Docker 鏡像層中拷貝至最上層的可讀寫層,然后容器進程再對讀寫層中的副本進行寫操縱。對于容器進程來講,它只能看到最上層的文件。所有對容器的改動,無論添加、刪除、還是修改文件都只會發生在容器層中。只有容器層是可寫的,容器層下面的所有鏡像層都是只讀的。鏡像層數量可能會很多,所有鏡像層會聯合在一起組成一個統一的文件系統。如果不同層中有一個相同路徑的文件,比如 /a,上層的 /a會覆蓋下層的 /a,也就是說用戶只能訪問到上層中的文件 /a。在容器層中,用戶看到的是一個疊加之后的文件系統。
下面分別以增刪改讀文件為例,詳細說:
添加文件:在容器中創建文件時,新文件被添加到容器層中。讀取文件:在容器中讀取某個文件時,Docker 會從上往下依次在各鏡像層中查找此文件。一旦找到,立即將其復制到容器層,然后打開并讀入內存。修改文件:在容器中修改已存在的文件時,Docker 會從上往下依次在各鏡像層中查找此文件。一旦找到,立即將其復制到容器層,然后修改。刪除文件:在容器中刪除文件時,Docker 也是從上往下依次在鏡像層中查找此文件。找到后,會在容器層中記錄下此刪除操作。只有當需要修改時才復制一份數據,這種特性被稱作 Copy-on-Write。可見,容器層保存的是鏡像變化的部分,不會對鏡像本身進行任何修改。
這樣就解釋了我們前面提出的問題:容器層記錄對鏡像的修改,所有鏡像層都是只讀的,不會被容器修改,所以鏡像可以被多個容器共享。
2.7 鏡像分層好處
最大好處就是共享資源,比如多個鏡像都是從相同的 base 鏡像構建而來,那么 Docker Host 只需要在磁盤上保留一份 base 鏡像,同時在內存中也加載一份 base 鏡像,就可以為所有容器服務了,并且每一層鏡像都是可共享的。
2.8 CentOS 與 Tomcat 鏡像大小對比
enter image description here
通過上圖,可以看出,centos 鏡像大小只有 200MB,而 Tomcat 鏡像大小為 463M,這明顯和我們潛意識中的常識不符吧,正常來講 centos 至少也得 2 G,而 Tomcat 最多也就是 15MB 而已。那這是為什么呢?
對于 centos 鏡像來說,底層直接用 Host 的 kernel,自動提供 rootfs 就行了,而對于一個精簡的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序庫就可以了。平時安裝的 centos 除了 rootfs 外,還回選裝很多軟件、服務和圖形桌面等,需要好幾個 GB 也就不足為奇了。而通過查看 Tomcat 的鏡像層,發現除了 tomcat 應用外,還會有 kernel、rootfs、jdk 等各種信息,所以它比 centos 鏡像大也是正常的。
2.9 Docker 鏡像特點 – Copy-on-Write
Docker 鏡像都是只讀的當容器啟動時,一個新的可寫層被加載到鏡像的頂部,這一層通常稱為容器層,容器層之下都成為鏡像層新數據會直接存放在最上面的容器層修改現有數據會先從鏡像層將數據拷貝到容器層,修改后的數據直接保存在容器層,鏡像層保持不變如果多個層中有命名相同的文件,用戶只能看到最上面那層中的文件打個比方,如果想修改一個文件,系統實際上是將這個在 read-only 層的 rootfs 的文件拷貝到 read-write 層的 rootfs 之中,然后對它進行修改,但 read-only 層的文件并不會被修改,依然存在于 read-only 層之中,只不過是在 read-write 層下被隱藏了。這種模式被稱為 copy on write。也是 unionFS 的特性和 docker 的強大之處。這樣就允許鏡像被繼承,也就是說我們想生成一套虛擬環境不用從零開始了,而只要在一個相對完善的基礎環境之上來創建我們的虛擬環境就可以了,比如我們想生成一個具有 tomcat 環境的鏡像,只要在一個裝有 java 環境的鏡像之上來創建就可以了。這也是 docker 便捷性的體現。
三、Docker 容器數據卷
3.1 引入
先來看一下 Docker 的理念:
將應用與運行的環境打包形成容器運行,運行可以伴隨容器,但我們對數據的要求是希望可以持久化的容器之間希望有可能共享數據
Docker 產生的數據,如果不通過 docker commit 生成新的鏡像,使得數據作為鏡像的一部分保存下來,那么當容器刪除后,數據自然也就消失了。
為了保存數據在 Docker 中,我們使用卷,這個有點類似 Redis 中的 rdb 和 aof 文件。
3.2 概念
卷就是目錄或文件,存在于一個或多個容器中,由 Docker 掛載到容器,但不屬于聯合文件系統,因此能夠繞過 Union File System 提供的一些用于持續存儲或共享數據的特性。
卷的設計目的就是數據的持久化,完全獨立于容器的生命周期,因此 Docker 不會在容器刪除時,刪除其掛載的數據卷。
容器卷也可以完成主機到容器、容器到主機的數據共享,類似 cp 命令。
3.3 特點
數據卷可以在容器之間共享或重用數據卷中的更改可以直接生效數據卷中的更改不會包含在鏡像的更新中數據卷的生命周期一直持續到沒有容器使用它為止
3.4 數據卷添加
3.4.1 直接命令添加
A. 命令
添加卷命令為:
docker run -it -v 宿主機目錄:容器目錄 鏡像名
eg. docker run -it -v /myDataVolume:/dataVolumeContainer centos 當執行網上述命令后,會分別在宿主機和容器根目錄下新建 myDataVolume 和 dataVolumeContainer 兩個文件夾
B. 查看數據卷是否掛載成功
查看數據卷是否添加成功:
通過查看對應的目錄是否生成通過docker inspect image-id查看
如下為通過第二種方式查看,截取的幾個關鍵信息:
“HostConfig”: {
“Binds”: [
“/myDataVolume:/dataVolumeContainer”
],
…
}
“Mounts”: [
{
“Type”: “bind”,
“Source”: “/myDataVolume”,
“Destination”: “/dataVolumeContainer”,
“Mode”: “”,
“RW”: true,
“Propagation”: “rprivate”
}
]
…
]
C. 容器和宿主機之間數據共享
在宿主機 myDataVolume 文件夾中新建內容為 hello 的 host.txt 文件在容器的 dataVolumeContainer 文件夾中查看文件列表,發現已經同步到宿主機的 host.txt 文件在容器的 dataVolumeContainer 文件夾中新建內容為 happ birthday 的 container.txt 文件,并在 host.txt 文件中新增 world 字符串在宿主機 myDataVolume 文件夾中查看文件及內容
最終數據如下:
enter image description here
D. 容器停止退出后,主機修改后是否同步
在容器通過 exit 或宿主機通過 docker stop 停止容器在宿主機 myDataVolume 文件夾中新建內容為 this is on container stop file 的 host02.txt在宿主機通過 docker start container-id 啟動容器通過 docker exec -it contain-id 進入容器,查看 dataVolumeContainer 目錄下文件
結論:當再次啟動容器時,在宿主機 myDataVolume 文件夾中內容會同步到容器中。
enter image description here
E. 命令 ( ro 只讀)
通過 docker run -it -v /myDataVolume2:/dataVolumeContainer2:ro 啟動容器在宿主機 myDataVolume2 目錄下新增文件 host.txt在容器 dataVolumeContainer2目錄下查看文件在容器dataVolumeContainer2 目錄下新增 container.txt 文件,發現報錯
enter image description here
通過 docker inspect container-id 查看權限
“Mounts”: [
{
“Type”: “bind”,
“Source”: “/myDataVolume2”,
“Destination”: “/dataVolumeContainer2”,
“Mode”: “ro”, // 只讀
“RW”: false,
“Propagation”: “rprivate”
}
],
…
結論:增加 ro 只讀參數的話,代表容器內目錄只能從宿主機同步,而不能在 dataVolumeContainer2 中進行增刪改操作。
3.4.2 Dockerfile 添加
Dockerfile 會在下一章節詳細講解,這里只需要按照步驟操作即可。
A. 在根目錄下新建 mydocker 文件夾并進入
cd /
mkdir mydocker
cd mydocker
B. 可在 Dockerfile 中使用 VOLUME 命令來給鏡像添加一個或多個數據卷
VOLUME[’/dataVolumeContainer1’,’/dataVolumeContainer2’,’/dataVolumeContainer3’]
出于可移植和分享的考慮,使用-v 宿主機目錄:容器目錄這種方法不能關直接在Dockerfile中實現。
由于宿主機目錄是依賴特定宿主機的,因此并不能保證所有的宿主機上都存在這樣的特定目錄。
C. File 構建
在 mydocker 目錄下新建 Dockerfile 文件,并編寫內容如下:
volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo “finished,–success1”
CMD /bin/bash
D. build生成鏡像
使用如下命令進行構建
docker build -f 指定目錄/Dockerfile -t 命名空間/鏡像名:TAG
eg.
docker build -f /mydocker/Dockerfile -t happy:centos
ps:此處定位為鏡像為happy,TAG為centos,建議書寫為happy/centos:1.0
構建過程如下:
enter image description here
如圖,我們在 Dockerfile 中的編寫的命令也是順序執行的,在執行完畢后構建出 id 為 fed673f01e52 的鏡像。
通過 docker images 查看,可以看到剛剛構建好的鏡像文件:
enter image description here
E. 運行容器
通過命令 docker run -it happy:centos 運行容器進入容器后,在根目錄下執行 ll 命令,會發現,在 Dockerfile 中配置的 VOLUME 已經生效,自動生成了 dataVolumeContainer1、dataVolumeContainer2 兩個文件夾
F. 查看宿主機目錄
在通過 docker run -it -v 命令時,可以指定宿主機目錄,那通過 Dockerfile 方式,如何查看對應的宿主機目錄呢?
當然,還是通過全能的 docker inspect 命令,來查看,關鍵信息如下:
“Mounts”: [
{
“Type”: “volume”,
“Name”: “382f84de2953b04ccdeba4c3cc1de219c8039c07f43e9d424f2087fc5785e60b”,
“Source”: “/var/lib/docker/volumes/382f84de2953b04ccdeba4c3cc1de219c8039c07f43e9d424f2087fc5785e60b/_data”,// 宿主機對應目錄
“Destination”: “/dataVolumeContainer1”,
“Driver”: “local”,
“Mode”: “”,
“RW”: true,
“Propagation”: “”
},
…
]
大家可以參照上一節使用命令添加容器卷中不斷增刪改文件方式來驗證同步效果,結論是一樣的,這里就不再贅述了。
3.4 數據卷容器
3.4.1 概念
已命名的容器掛載數據卷,其他容器通過掛載這個(父容器)實現數據共享,掛載數據卷的容器,成為數據卷容器。
3.4.2 volumes-from
以上一節中新建的鏡像 happy:centos 為模板運行容器 dc1 、dc2 和 dc3。
他們已經具有容器卷:
dataVolumeContainer1、dataVolumeContainer2。
操作步驟如下:
啟動父容器 dc01,并且在 dataVolumeContainer1 文件夾中新建 dc01_add.txt 文件,命令如下:
docker run -it --name dc01 happy:centos
cd dataVolumeContainer1
touch dc01_add.txt
分別啟動 dc02 和 dc03 兩個容器,繼承自 dc01,分別在 dc02、dc03 中的 dataVolumeContainer1 中添加 dc02_add.txt 和 dc03_add.txt,命令如下:
docker run -it --name dc02 --volumes-from dc01 happy:centos
cd dataVolumeContainer1
touch dc02_add.txt
docker run -it --name dc03 --volumes-from dc01 happy:centos
cd dataVolumeContainer1
touch dc03_add.txt
分別查看 dc01、dc02 和 dc03 下 dataVolumeContainer1 下文件,會發現全部同步刪除 dc01 容器,dc02 添加 dc02_update.txt 文件,查看 dc03 容器是否會同步到(會)刪除 dc02,新建 dc04 繼承自 dc03,再刪除 dc03,查看 dc04 容器中 dataVolumeContainer1 下文件是否存在(都存在)
結論:容器之間配置信息的傳遞,數據卷的生命周期一直持續到沒有容器使用它為止,這也是其特性之一。
四、Dockerfile 全解析
4.1 概念
Dockerfile 是用來構建 Docker 鏡像的構建文件,是由一系列命令和參數構成的腳本。
4.2 構建步驟
編寫Dockerfile文件docker builddocker run
4.3 構建過程解析
4.3.1 基礎知識
每條保留字指定都必須大寫字母且后面要至少跟隨一個參數指定按照從上到下,順序執行# 表示注釋每條指令都會創建一個新的鏡像層,并對鏡像進行提交
4.3.2 Dockerfile 執行流程
docker 從基礎鏡像運行一個容器執行一條指令并對容器做出修改執行類似 docker commit 指令提交一個新的鏡像層docker 再基于剛提交的鏡像運行一個新容器執行 dockerfile 中的下一條指令直到所有指令都執行完成
4.3.3 小結與關系
從應用軟件的角度來看,Dockerfile、Docker鏡像和Docker容器分別代表軟件的三個階段:
Dockerfile:軟件的原材料
Docker鏡像:軟件的交付品
Docker容器:軟件的運行狀態
Dockerfile面向開發,Docker鏡像成為交付標準,Docker容器則涉及部署與運維,三者缺一不可,合力充當Docker體系的基石。
enter image description here
三者關系如下:
Dockerfile:需要定義一個 Dockerfile,Dockerfile 定義了進程需要的一切東西。Dockerfile 設計的內容包括執行代碼或者文件、環境變量、依賴包、運行時環境、動態鏈接庫、操作系統的發行版本、服務進程和內核進程(當應用進程需要和系統服務和內核進程打交道時,需要考慮如何設計 namespace 的權限控制)等。Docker 鏡像:在用 Dockerfile 定義一個文件后,docker build 會產生一個 Docker 鏡像,當運行 Docker 鏡像時,才真正開始提供服務。Docker 容器:容器是直接提供服務的。
4.4 Dockerfile 體系結構(保留字指令)
FROM:基礎鏡像,當前新鏡像是基于哪個鏡像MAINTAINER:鏡像維護者的姓名和郵件地址RUN:容器構建時需要運行的命令EXPOSE:當前容器對外暴露的端口WORKDIR:指定在創建容器后,終端默認登陸進來后的工作目錄,一個落腳點ENV:用來在構建鏡像過程中設置環境變量ADD:將宿主機目錄下的文件拷貝到鏡像且 ADD 命令會自動處理 URL 和解壓 tar 壓縮包COPY:類似 ADD,拷貝文件和目錄到鏡像中。 將從構建上下文目錄中<源路徑>的文件/目錄復制到新的一層鏡像內的<目標目錄>位置。
COPY src des
COPY [“src” “des”]
VOLUME:數據容器卷,用于保存數據和持久化工作CMD:指定一個容器啟動時要運行的命令。Dockerfile 中可以有多個 CMD 命令,但只有最后一個生效,CMD 會被 docker run 之后的參數替換ENTRYPOINT:指定一個容器啟動時要運行的命令。其目的和 CMD 命令一樣,都是在指定容器啟動程序及參數ONBUILD:當構建一個被繼承的 Dockerfile 時運行命令,父鏡像在被子繼承后父鏡像的 onbuild 被觸發
總結如下:
enter image description here
4.5 案例之自定義鏡像 centos
4.5.1 引入
從 dockerhub 拉下來的 centos 鏡像,默認工作目錄是根目錄,并且不支持 vim 和 ifconfig 等配置,如下:
enter image description here
4.5.2 目標
登陸后切換默認路徑增加 vim 編輯器查看網絡配置 ifconfig 支持
4.5.3 編寫 Dockerfile
在根目錄下新建文件夾 mydocker,并新建 Dockerfile_mycentos,內容如下:
FROM centos
MAINTAINER happyhappy@126.com
ENV MYPATH /tmp
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 9001
CMD echo $MYPATH
CMD echo “build success”
CMD /bin/bash
4.5.4 構建鏡像
執行命令,通過剛編寫好的 Dockerfile 構建鏡像,語法如下:
docker build -f Dockerfile路徑 -t 新鏡像名:TAG
示例:
docker build -f /mydocker/Dockerfile_mycentos -t happy/mycentos:1.0 .
4.5.5 運行
構建完成后,可以正常運行鏡像了,命令如下:
docker run -it happy/centos:1.0
此時,會發現,默認工作目錄已經發生變化,同時該鏡像也支持 vim 和 ifconfig 查看網絡配置了。
4.5.6 查看鏡像變更歷史
通過如下命令可以查看指定鏡像的變更(生成)歷史:
docker history image-id
4.6 CMD 和 ENTRYPOINT 區別
4.6.1 CMD
指定一個容器啟動時要運行的命令Dockerfile 中可以有多個 CMD 指令,但只要最后一個生效CMD 會被 docker run 之后的參數替換
示例:
執行 docker run -it -p 7777:8080 tomcat 啟動 tomcat 容器,此時在瀏覽器通過訪問 http://ip:7777 就可以訪問到剛啟動的 tomcat 實例了執行 docker run -it -p 7777:7070 tomcat ls -l,會發現并沒有出現啟動 tomcat 時的輸出,而是輸出了 /usr/local/tomcat 目錄下的文件和文件夾信息,瀏覽器也無法訪問啟動的 tomcat 實例,這也就驗證了 CMD 參數替換的特點輸出 /usr/local/tomcat 是因為在 tomcat 的 Dockerfile 中指定了 WORKDIR 為 /usr/local/tomcat此處在docker run 后增加參數相當于在 Dockerfile 中增加 CMD ls -l /usr/local/tomcat
4.6.2 ENTRYPOINT
指定一個容器啟動時要運行的命令docker run 之后的參數會被當作參數傳遞給 ENTRYPOINT,形成新的命令組合
示例:
目標:制作ENTRYPOINT版本查詢ip信息鏡像
步驟:
A. 編寫Dockerfile,如下:
FROM centos
RUN yum install -y curl
ENTRYPOINT [“curl”,"-s",“http://ip.cn”]
B. build 鏡像
docker build -f /mydocker/Dockerfile -t myip .
C. 運行鏡像
使用如下命令運行容器:
docker run myip
D. 擴展功能,增加http報文頭
curl命令通過-i參數可以查看報文頭。 通過如下命令,可在剛才構建的鏡像基礎上擴展該功能:
docker run myip -i
此處,相當于在 Dockerfile 相當于 CMD [“curl”,"-s -i",“http://ip.cn”],如果此處 Dockerfile 中使用 CMD [“curl”,"-s",“http://ip.cn”] 的話,增加 -i 參數后,相當于 CMD [“curl”,"-s -i",“http://ip.cn”] CMD -i,根據 CMD 指令的特點,只會執行 CMD -i,那么很明顯就運行報錯了,所以這就是兩者的不同,相比而言,ENTRYPOINT 更加強大。
五、Docker 實戰
5.1 自定義 tomcat9 鏡像
A. 新建 tomcat9 文件夾,用于存放相關文件
mkdir -p /mydocker/tomcat9
cd /mydocker/tomcat9
B. 新建 copy.txt用于測試 COPY 指令
touch copy.txt
C. 將 jdk 和 tomcat 壓縮包拷貝到當前目錄
cp /tmp/apache-tomcat-9.0.8-tar.gz ./
cp /tmp/jdk-8u171-linux-x64-tar.gz ./
D. 新建 Dockerfile,內容如下
FROM centos
MAINTAINER happyhappy@126.com
把宿主機當前上下文的copy.txt拷貝到容器/usr/local路徑下
COPY copy.txt /usr/local/copyincontainer.txt
把jdk和tomcat添加到容器并解壓縮
ADD jdk-8u171-linux-x64-tar.gz /usr/local/
ADD apache-tomcat-9.0.8-tar.gz /usr/local/
安裝vim編輯器
RUN yum -y install vim
設置工作路徑
ENV MYPATH /usr/local
WORKDIR $MYPATH
配置jdk和tomcat環境變量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH JAVAHOME/lib/dt.jar:JAVA_HOME/lib/dt.jar:JAVAH?OME/lib/dt.jar:JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
ENV PATH PATH:PATH:PATH:JAVA_HOME/bin:CATALINAHOME/lib:CATALINA_HOME/lib:CATALINAH?OME/lib:CATALINA_HOME/bin
容器運行時監聽端口
EXPOSE 8080
啟動時運行tomcat
ENTRYPOINT [“usr/local/apache-tomcat-9.0.8/bin/startup.sh”]
CMD [“usr/local/apache-tomcat-9.0.8/bin/catalina.sh”,“run”]
CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out
E. 構建鏡像
docker build -f Dockerfile -t happy/mytomcat9:1.0
F. 運行
docker run -d -p 8081:8080 --name mytomcat9 -v /mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /mydocker/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true happy/mytomcat9:1.0
乍一看,挺復雜,其實拆分開就特別簡單了,無非就是增加了兩個數據卷,存儲和持久化數據而已。
G. 發布 test 項目
在 /mydocker/tomcat9/test 目錄下,新建最簡單的 web 工程文件即可,例如新建WEB-INF文件夾,并且在 WEB-INF 中新建web.xml和hello.jsp,然后重啟容器即可。
此時,再通過瀏覽器訪問 http://ip:8081/test/hello.jsp 就可以看到剛添加的頁面,同時在 tomcat9logs 文件夾中也會有對應的日志信息。
5.2 安裝 Tomcat
安裝 tomcat 比較簡單,只需要注意端口映射即可,步驟如下:
5.2.1. docker hub上查找tomcat鏡像
docker search tomcat
5.2.2. 從 docker hub 上拉取 tomcat 鏡像到本地
docker pull tomcat
5.2.3. 通過 docker images 查看是否拉取成功
docker images
5.2.4. 使用 tomcat 鏡像創建容器(運行鏡像)
docker run -it -p 9999:8080 --name tomcat01 tomcat
5.3 安裝 MySQL
5.3.1. 下載鏡像
docker pull mysql
5.3.2. 通過鏡像啟動容器
docker run --name mysql01 -d mysql
此時,通過 docker ps 查看運行中的容器,缺發現沒有剛剛啟動的 mysql01,通過 docker ps -a 發現,其狀態已經是 Exited,路徑如下:
enter image description here
那就查看一下 mysql01 的日志信息,看看有沒有保存,命令為 docker logs 9b0f3098ce78,發現錯誤日志如下:
error: database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
原來是數據庫沒有初始化,并且沒設置 password,查閱文檔,發現:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
$ docker run --name some-mysql -e MY
… where some-mysql is the name you want to assign to your container, my-secret-pw is the password to be set for the MySQL root user and tag is the tag specifying the MySQL version you want. See the list above for relevant tags.
也就是說,需要指定 -e MYSQL_ROOT_PASSWORD=my-secret-pw 來設置 MySQL 中 root 用戶密碼。
so,那就試一下吧。
根據鏡像啟動容器,如下:
docker run --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
通過 docker ps 查看正在運行中容器,會發現 mysql 已經處于運行狀態了。
enter image description here
5.3.3. 將宿主機端口 5555 映射到 mysql 容器 3306
如題,將宿主機端口 5555 訪問映射到 mysql 容器的 3306 端口,命令如下:
docker run --name mysql03 -e MYSQL_ROOT_PASSWORD=123456 -p 5555:3306 -d mysql
如上,可再通過 docker ps 查看容器運行及 port。
5.3.4. 使用命令行連接到 mysql 容器
在本機使用 iTerm2 連接到 mysql 容器,執行如下命令:
mysql -h*...* -uroot -p123456 -P 5555
如連接失敗,請參考鏈接。
5.3.5. 使用 Navicat 連接到 mysql 容器
新建連接,如圖:
enter image description here
如連接失敗,請參考:
https://blog.csdn.net/u010358168/article/details/81253744https://blog.csdn.net/u010358168/article/details/53157857
解決。
5.4 安裝 Redis
5.4.1 拉取鏡像
docker pull redis:3.2
5.4.2 運行鏡像
docker run -p 6379:6379 -v /mydocker/myredis/data:/data -v /mydocker/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --apendonly yes
又是一長串命令,如果拆分開來的無非就是端口映射、數據卷等配置。
具體 redis.conf 配置,詳見博客
5.5 安裝 WordPress
5.5.1 WordPress簡介
WordPress 是一個非常著名的 PHP 編寫的博客平臺,發展到目前為止已經形成了一個龐大的網站平臺系統。在 WP 上有規模龐大的插件和主題,可以幫助我們快速建立一個博客甚至網站。
在 Windows 上可以非常方便的安裝 WordPress,因為 IIS 上集成了 WordPress 的一鍵安裝包。而在 Linux 上安裝 WordPress 就比較復雜了,我們需要配置 PHP 環境、Apache 或者 Nginx 服務器、MySQL 數據庫以及各種權限和訪問問題。所以在 Linux 上最好的辦法就是使用 Docker 來安裝 WordPress。
5.5.2 安裝 MySQL
WordPress 需要使用 MySQL 數據庫,這里也有兩種方式,第一種是安裝本地 MySQL,第二種就是在 Docker 中安裝 MySQL 鏡像。此處以在 Docker 中安裝 MySQL 為例進行演示。
安裝詳見 5.3 章節
5.5.3 安裝 WordPress
A. 搜索鏡像
docker search wordpress
B. 下載鏡像
docker pull wordpress
5.5.4 配置 WordPress
安裝完 MySQL,下載完 WordPress 鏡像后,就可以啟動 WordPress 了。
詳細的文檔參考這里。
docker run --name mywordpress --link mysql:mysql -p 8080:80 -d wordpress
name:指定要啟動的 WordPress 實例名稱link:指定要使用的 Docker MySQL 實例名稱p:將 Docker 內部的 80 端口映射到本地的 8080 端口上
然后打開瀏覽器,輸入 http://localhost:8080(端口號是命令中設置的),然后就可以看到 WordPress 了。按照提示輸入用戶名等信息,然后安裝 WordPress。等到它提示安裝完成,那么 WordPress 的安裝就算大功告成了。
最后稍加配置,再添加諸如內網映射等功能之后,站點就可以對外訪問了。
篇幅原因,不在此處進行過多細節講解,建議關注博客和公眾號 JADreamFactory,會有具體文章對細節進行講述。
5.6 本地鏡像推送到阿里云
5.6.1 阿里云 ECS Docker 生態
enter image description here
5.6.2 鏡像生成
通過前面的 Dockerfile 生成鏡像從運行中的容器創建一個新的鏡像
docker commit [OPTIONS] container-id [REPOSITORY[:TAG]]
5.6.3 本地鏡像推送到阿里云
A. 準備鏡像文件
通過docker build制作鏡像,參照前面若干示例,此處不再重復將修改后的鏡像重新打包為一個新鏡像,命令如下:
docker commit -a “rainbow” -m “my image” 容器ID new-image:版本號
ps:-a :鏡像的作者,-m:鏡像的提交信息,容器ID 是運行鏡像之后得到的那個容器 ID。
B. 阿里云開發者平臺
注冊并登陸開發者平臺,鏈接為:https://cr.console.aliyun.com/cn-hangzhou/repositories
C. 創建倉庫鏡像
如圖所示,創建鏡像倉庫:
enter image description here
設置代碼源:
enter image description here
D. 登錄阿里云Docker Registry
$ sudo docker login --username=****** registry.cn-hangzhou.aliyuncs.com
ps:用于登錄的用戶名為阿里云賬號全名,密碼為開通服務時設置的密碼,可以在產品控制臺首頁修改登錄密碼。
E. 將鏡像推送到Registry
$ sudo docker login --username=**** registry.cn-hangzhou.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/happy2018/test_repository:[鏡像版本號]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/happy2018/test_repository:[鏡像版本號]
ps:此處的 username 為阿里云的登錄賬號
5.6.4 將阿里云鏡像下載到本地
$ sudo docker pull registry.cn-hangzhou.aliyuncs.com/happy2018/test_repository:[鏡像版本號]
六、總結
文章篇幅過長,所以在部分知識點介紹時不會太細,但核心知識來說,絕對干貨滿滿,如果能掌握這些的話,可以達到初級到中級及實戰的目標。
通過本篇文章,希望你能了解并掌握:
Docker 鏡像原理、分層、UnionFS 聯合文件系統及特點Docker 容器數據卷的概念及如何通過兩種方式進行添加Dockerfile 關鍵指令及使用指定來自定義鏡像自行安裝配置 MySQL、Tomcat、Redis 和 Nginx 等
七、更多精彩
博主近期在 CSDN 寫博客,目前閱讀量已超過 17 W,后續針對該系列文章較多問題的解答及詳細專題會以博客或公眾號文章的形式發布,當然內容包括但不限于 Java、Android、Docker、SpringBoot、Redis 等等。
建議關注博客,點我前往推薦關注微信公眾號 JADreamFactory。
八、答謝
一鞠躬
再鞠躬
三鞠躬
再次感謝各位的支持,如有問題,歡迎指出~
總結
以上是生活随笔為你收集整理的Docker | Docker技术基础梳理(五) - Docker网络管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 真得有紫薇圣人吗!
- 下一篇: Redis 缓存穿透、雪崩、缓存数据库不