1、Docker 簡介
一、什麼是 Docker
Docker 是使用最普遍的開源容器引擎,它完全釋放了計算虛擬化的威力,極大提升了應用的運行效率,下降了雲計算資源供應的成本! 使用 Docker,可讓應用的部署、測試和分發都變得史無前例的高效和輕鬆!linux
Docker 使用 Google 公司推出的 Go 語言 進行開發實現,基於 Linux 內核的 cgroup,namespace,以及 AUFS 類的 Union FS 等技術,對進程進行封裝隔離,屬於操做系統層面的虛擬化技術。因爲隔離的進程獨立於宿主和其它的隔離的進程,所以也稱其爲容器。nginx
Docker 在容器的基礎上,進行了進一步的封裝,從文件系統、網絡互聯到進程隔離等等,極大的簡化了容器的建立和維護。使得 Docker 技術比虛擬機技術更爲輕便、快捷。c++
二、爲何要用 Docker
① 更高效的利用系統資源:因爲容器不須要進行硬件虛擬以及運行完整操做系統等額外開銷,Docker 對系統資源的利用率更高。git
② 更快速的啓動時間:Docker 容器應用,因爲直接運行於宿主內核,無需啓動完整的操做系統,所以能夠作到秒級、甚至毫秒級的啓動時間。github
③ 一致的運行環境:Docker 的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性。redis
④ 持續交付和部署:使用 Docker 能夠經過定製應用鏡像來實現持續集成、持續交付、部署。一次建立或配置,能夠在任意地方正常運行。sql
⑤ 更輕鬆的遷移:Docker 確保了執行環境的一致性,使得應用的遷移更加容易。Docker 能夠在不少平臺上運行,不管是物理機、虛擬機、公有云、私有云,甚至是筆記本,其運行結果是一致的。docker
三、Docker 基本組成
① 鏡像(Images)
Docker 鏡像是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像不包含任何動態數據,其內容在構建以後也不會被改變。
Docker 設計時,充分利用 Union FS 的技術,將其設計爲分層存儲的架構,Docker 鏡像由多層文件系統聯合組成。鏡像構建時,會一層層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在本身這一層。
② 容器(Container)
鏡像(Image)和容器(Container)的關係,就像是面向對象程序設計中的 類 和 實例 同樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器能夠被建立、啓動、中止、刪除、暫停等。
容器的實質是進程,但與直接在宿主執行的進程不一樣,容器進程運行於屬於本身的獨立的 命名空間。所以容器能夠擁有本身的 root 文件系統、本身的網絡配置、本身的進程空間,甚至本身的用戶 ID 空間。容器內的進程是運行在一個隔離的環境裏,使用起來,就好像是在一個獨立於宿主的系統下操做同樣。
每個容器運行時,是以鏡像爲基礎層,在其上建立一個當前容器的存儲層,咱們能夠稱這個爲容器運行時讀寫而準備的存儲層爲容器存儲層。容器存儲層的生存週期和容器同樣,容器消亡時,容器存儲層也隨之消亡。所以,任何保存於容器存儲層的信息都會隨容器刪除而丟失。
按照 Docker 最佳實踐的要求,容器不該該向其存儲層內寫入任何數據,容器存儲層要保持無狀態化。全部的文件寫入操做,都應該使用 數據卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網絡存儲)發生讀寫,其性能和穩定性更高。
數據卷的生存週期獨立於容器,容器消亡,數據卷不會消亡。所以,使用數據卷後,容器能夠隨意刪除、從新 run ,數據卻不會丟失。
③ 鏡像倉庫(Registry)
鏡像倉庫是一個集中的存儲、分發鏡像的服務。一個 Docker Registry 中能夠包含多個倉庫(Repository);每一個倉庫能夠包含多個標籤(Tag);每一個標籤對應一個鏡像。
一般,一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就經常使用於對應該軟件的各個版本。咱們能夠經過 <倉庫名>:<標籤> 的格式來指定具體是這個軟件哪一個版本的鏡像。若是不給出標籤,將以 latest 做爲默認標籤。
最常使用的 Registry 公開服務是官方的 Docker Hub,這也是默認的 Registry,並擁有大量的高質量的官方鏡像。用戶還能夠在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 鏡像,能夠直接使用作爲私有 Registry 服務。
2、Docker 安裝
Docker 版本包含 社區版和企業版,咱們平常使用社區版足夠。Docker 社區版各個環境的安裝參考官方文檔:https://docs.docker.com/install/。後面的學習在 Linux CentOS7 上測試。
一、CentOS7 安裝步驟
CentOS 安裝參考官方文檔:https://docs.docker.com/install/linux/docker-ce/centos/
① 卸載舊版本
# yum remove docker docker-common docker-selinux
② 安裝依賴包
# yum install -y yum-utils device-mapper-persistent-data lvm2
③ 安裝 Docker 軟件包源
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
④ 安裝 Docker CE
# yum install docker-ce
⑤ 啓動 Docker 服務
# systemctl start docker
⑥ 設置開機啓動
# systemctl enable docker
⑦ 驗證安裝是否成功
# docker -v
# docker info
二、Docker 命令
經過 --help 參數能夠看到 docker 提供了哪些命令,能夠看到 docker 的用法是 docker [選項] 命令 。
命令有兩種形式,Management Commands 是子命令形式,每一個命令下還有子命令;Commands 是直接命令,至關於子命令的簡化形式。
繼續查看 Management Commands 有哪些子命令,例如查看 image 的子命令。docker image ls 等同於 docker images,docker image pull 等同於 docker pull。
3、鏡像管理
一、鏡像簡介
鏡像包含了一個軟件的運行環境,是一個不包含Linux內核而又精簡的Linux操做系統,一個鏡像能夠建立N個容器。
鏡像是一個分層存儲的架構,由多層文件系統聯合組成。鏡像構建時,會一層層構建,前一層是後一層的基礎。
從下載過程當中能夠看到,鏡像是由多層存儲所構成。下載也是一層層的去下載,並不是單一文件。下載過程當中給出了每一層的 ID 的前 12 位。而且下載結束後,給出該鏡像完整的 sha256 的摘要,以確保下載一致性。
經過 docker history <ID/NAME> 查看鏡像中各層內容及大小,每層會對應着 Dockerfile 中的一條指令。
因爲 Docker 鏡像是多層存儲結構,而且能夠繼承、複用,所以不一樣鏡像可能會由於使用相同的基礎鏡像,從而擁有共同的層。因爲 Docker 使用 Union FS,相同的層只須要保存一份便可,所以實際鏡像硬盤佔用空間極可能要比這個列表鏡像大小的總和要小的多。
二、鏡像管理
Docker 運行容器前須要本地存在對應的鏡像,若是鏡像不存在本地,Docker 會從鏡像倉庫下載,默認是 Docker Hub 公共註冊服務器中的倉庫。
Docker Hub 是由 Docker 公司負責維護的公共註冊中心,包含大量的優質容器鏡像,Docker 工具默認從這個公共鏡像庫下載鏡像。下載的鏡像如何使用能夠參考官方文檔。地址:https://hub.docker.com/explore
若是從 Docker Hub 下載鏡像很是緩慢,能夠先配置鏡像加速器,參考:https://www.daocloud.io/mirror
Linux下經過如下命令配置鏡像站:
# curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io # systemctl restart docker
① 搜索鏡像 :docker search <NAME> [選項]
OFFICIAL:是否官方版本;
② 下載鏡像 :docker pull [選項] [Docker Registry地址]<倉庫名>:<標籤>
Docker Registry地址:地址的格式通常是 <域名/IP>[:端口號] 。默認地址是Docker Hub。
倉庫名:倉庫名是兩段式名稱,既 <用戶名>/<軟件名> 。對於 Docker Hub,若是不給出用戶名,則默認爲 library ,也就是官方鏡像。
③ 列出本地鏡像 :docker images [選項]
TAG:標籤版本;IMAGE ID:鏡像ID;SIZE:鏡像大小;
查看虛懸鏡像(鏡像既沒有倉庫名,也沒有標籤,顯示爲 <none>):docker images -f dangling=true
默認的 docker images 列表中只會顯示頂層鏡像,若是但願顯示包括中間層鏡像在內的全部鏡像:docker images -a
只列出鏡像ID:docker images -q
列出部分鏡像:docker images redis
以特定格式顯示:docker images --format "{{.ID}}: {{.Repository}}"
④ 給鏡像打 Tag :docker tag <IMAGE ID> [<用戶名>/]<鏡像名>:<標籤>
鏡像的惟一標識是其 ID 和摘要,而一個鏡像能夠有多個標籤。
⑤ 刪除本地鏡像 :docker rmi [選項] <鏡像1> [<鏡像2> ...]
<鏡像> 能夠是鏡像短 ID、鏡像長 ID、鏡像名或者鏡像摘要。
刪除鏡像的時候,其實是在要求刪除某個標籤的鏡像。因此首先須要作的是將知足咱們要求的全部鏡像標籤都取消,這就是咱們看到的Untagged 的信息。
鏡像是多層存儲結構,所以在刪除的時候也是從上層向基礎層方向依次進行判斷刪除。鏡像的多層結構讓鏡像複用變得很是容易,所以頗有可能某個其它鏡像正依賴於當前鏡像的某一層。這種狀況,不會觸發刪除該層的行爲。直到沒有任何層依賴當前層時,纔會真實的刪除當前層。
除了鏡像依賴之外,還須要注意的是容器對鏡像的依賴。若是有用這個鏡像啓動的容器存在(即便容器沒有運行),那麼一樣不能夠刪除這個鏡像。若是這些容器是不須要的,應該先將它們刪除,而後再來刪除鏡像。
⑥ 批量刪除鏡像
刪除全部虛懸鏡像:docker rmi $(docker images -q -f dangling=true)
刪除全部倉庫名爲 redis 的鏡像:docker rmi $(docker images -q redis)
刪除全部在 mysql:8.0 以前的鏡像:docker rmi $(docker images -q -f before=mysql:8.0)
⑦ 導出鏡像:docker save -o <鏡像文件> <鏡像>
能夠將一個鏡像完整的導出,就能夠傳輸到其它地方去使用。
⑧ 導入鏡像:docker load -i <鏡像文件>
4、容器管理
一、建立容器
啓動容器有兩種方式,一種是基於鏡像新建一個容器並啓動,另一個是將在終止狀態(stopped)的容器從新啓動。Docker 容器很是輕量級,不少時候能夠隨時刪除和新建立容器。
建立容器的主要命令爲 docker run (或 docker container run),經常使用參數以下:
當利用 docker run 來建立容器時,Docker 在後臺運行的標準操做包括:
- 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
- 利用鏡像建立並啓動一個容器
- 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
- 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
- 從地址池配置一個 ip 地址給容器
- 執行用戶指定的應用程序
- 執行完畢後容器被終止
① 建立並進入容器:docker run -ti <IMAGE ID OR NAME> /bin/bash
建立容器,經過 -ti 參數分配一個 bash 終端,並進入容器內執行命令。退出容器時容器就被終止了。
② 容器後臺運行:docker run -d <IMAGE ID OR NAME>
容器是否會長久運行,是和 docker run 指定的命令有關,即容器內是否有前臺進程在運行,和 -d 參數無關。一個容器必須有一個進程來守護容器纔會在後臺長久運行。
例如經過 -d 參數後臺運行 centos,容器建立完成後將退出。而經過 -ti 分配一個僞終端後,容器內將有一個 bash 終端守護容器,容器不會退出。
③ 進入容器:docker exec -ti <CONTAINER ID> bash
④ 指定端口:docker run -d -p <宿主機端口>:<容器內端口> <IMAGE ID>
經過 -p 參數指定宿主機與容器內的端口映射,若是不指定宿主機端口,將會隨機映射一個宿主機端口。映射好端口後,宿主機外部就能夠經過該端口訪問容器了。
⑤ 宿主機重啓時自動重啓容器:docker run -d --restart always <IMAGE ID>
宿主機重啓時,docker 容器默認不會自動啓動,能夠經過 --restart=always 設置自動重啓。
二、容器資源限制
容器資源限制主要是對內存的限制和使用CPU數量的限制,經常使用選項以下:
① 使用例子
1) 限制容器最多使用500M內存和100M的Swap,並禁用OOM Killer。注意 --memory-swap 的值爲 --memory 的值加上 Swap 的值。
docker run -d --name nginx_1 --memory="500m" --memory-swap="600m" --oom-kill-disable nginx
若是 memory 小於等於 memory-swap,表示不使用Swap;若是 memory-swap="-1" 表示能夠無限使用Swap;若是不設置 memory-swap,其值默認爲 memory 的2倍。
2) 容許容器最多使用一個半的CPU:docker run -d --name nginx_2 --cpus="1.5" nginx
3) 容許容器最多使用 50% 的CPU:docker run -d --name nginx_3 --cpus=".5" nginx
② 查看容器資源使用統計:docker stats <CONTAINER ID>
經過 docker stats 能夠實時查看容器資源使用狀況。若是不對容器內存或CPU加以限制,將默認使用物理機全部內存和CPU。一般狀況下,爲了安全必定要限制容器內存和CPU,不然容器內程序遭到攻擊,可能無限佔用物理機的內存和CPU。
三、容器經常使用命令
① 中止容器:docker stop <CONTAINER ID>
② 重啓容器:docker start <CONTAINER ID>
③ 刪除容器
刪除已中止的容器:docker rm <CONTAINER ID>
強制刪除運行中的容器:docker rm -f <CONTAINER ID>
批量刪除Exited(0)狀態的容器:docker rm $(docker ps -aq -f exited=0)
批量刪除全部容器:docker rm -f $(docker ps -aq)
④ 查看容器日誌:docker logs <CONTAINER ID OR NAMES>
⑤ 查看容器詳細信息:docker inspect <CONTAINER ID>
⑥ 列出或指定容器端口映射:docker port <CONTAINER ID>
⑦ 顯示一個容器運行的進程:docker top <CONTAINER ID>
⑧ 拷貝文件/文件夾到容器:docker cp <dir> <CONTAINER ID>:<dir>
⑨ 查看容器與鏡像的差別:docker diff <CONTAINER ID>
5、管理應用程序數據
容器刪除後,裏面的數據將一同被刪除,所以須要將容器內常常變更的數據存儲在容器以外,這樣刪除容器以後數據依然存在。
Docker 提供三種方式將數據從宿主機掛載到容器中:
- volumes:由 Docker 管理的數據卷,是宿主機文件系統的一部分(/var/lib/docker/volumes)。是保存數據的最佳方式。
- bind mounts:將宿主機上的文件或目錄掛載到容器中,一般在容器須要使用宿主機上的目錄或文件時使用,好比蒐集宿主機的信息、掛載宿主機上的 maven 倉庫等。
- tmpfs:掛載存儲在主機系統的內存中,而不會寫入主機的文件系統。若是不但願將數據持久存儲在任何位置,可使用 tmpfs,同時避免寫入容器可寫層提升性能。這種方式使用比較少。
一、Volume
① 管理卷
建立數據卷:docker volume create <volume_name>
查看數據卷列表:docker volume ls
查看數據卷詳細信息:docker volume inspect <volume_name>
建立的數據卷默認在宿主機的 /var/lib/docker/volumes/ 下
② 建立容器時指定數據卷
1) 經過 --mount 方式:--mount src=<數據卷名稱>,dst=<容器內的數據目錄>,注意逗號之間不能有空格
docker run -d --name nginx_1 --mount src=nginx_html,dst=/usr/share/nginx/html nginx
2) 經過 -v 方式:-v <數據卷名稱>:<容器內的數據目錄>
docker run -d --name nginx_2 -v nginx_html:/usr/share/nginx/html nginx
以上兩種方式,--mount 更加通用直觀,-v 是老語法的方式。若是對應的數據卷不存在,將自動建立數據卷。若是掛載目標在容器中非空,則該目錄現有內容會自動同步到數據卷中。
③ 刪除數據卷:docker volume rm <volume_name>
數據卷是獨立於容器的生命週期的,刪除容器是不會刪除數據卷的,除非刪除數據卷,刪除數據卷以後數據也就丟失了。
若是數據卷正在被某個容器使用,將不能被刪除,須要先刪除使用此數據卷的全部容器以後才能刪除數據卷。
④ Volume 特色及使用場景
- 多個容器能夠同時掛載相同的卷,可用於多個運行容器之間共享數據。
- 當容器中止或被刪除後,數據卷依然存在。當明確刪除卷時,卷纔會被刪除。
- 能夠將容器的數據存儲在遠程主機或其它存儲上。
- 將數據從一臺 docker 主機遷移到另外一臺主機時,先中止容器,而後備份卷的目錄 /var/lib/docker/volumes
二、Bind Mounts
① 建立容器時綁定數據卷
1) 經過 --mount 方式:--mount type=bind,src=<宿主機目錄>,dst=<容器內的數據目錄>,注意逗號之間不能有空格
docker run -d --name nginx_1 --mount type=bind,src=/data/nginx/html,dst=/usr/share/nginx/html nginx
2) 經過 -v 方式:-v <宿主機目錄>:<容器內的數據目錄>
docker run -d --name nginx_2 -v /data/nginx/html:/usr/share/nginx/html nginx
以上兩種方式,若是源文件/目錄不存在,不會自動建立容器,會拋出錯誤。與 volume 方式相比,若是掛載目標在容器中非空,則該目錄現有內容將被隱藏,能夠理解成使用宿主機的目錄覆蓋了容器中的目錄,新增的數據會同步。
② Bind Mounts 特色及使用場景
- 從主機共享配置文件到容器。默認狀況下,掛載主機 /etc/resolv.conf 到每一個容器,提供 DNS 解析。
- 在 docker 主機上的開發環境和容器之間共享源代碼。例如,能夠將 maven target 目錄掛載到容器中,每次在 docker 主機上構建maven項目時,容器均可以訪問構建好的項目包。
- 當 docker 主機的文件或目
- 錄結構保證與容器所需的綁定掛載一致時,例如容器中須要統計主機的一些信息,能夠直接將主機的某些目錄直接掛載給容器使用。
6、容器網絡
一、Docker 網絡模式
① bridge:--net=bridge
默認網絡,docker 啓動後會建立一個 docker0 網橋,默認建立的容器會添加到這個網橋中。
建立容器時不指定網絡模式,默認使用 bridge 方式,經過容器網絡配置能夠看到會默認分配一個 docker0 的內網IP。
② host:--net=host
容器不會得到一個獨立的 network namespace,而是與主機共用一個。這就意味着容器不會有本身的網卡信息,而是使用宿主機的。容器除了網絡,其它都是隔離的。
能夠看到 host 網絡模式下,容器網絡配置與宿主機是同樣的。那麼容器內應用的端口將佔用宿主機的端口。
③ none:--net=none
獲取獨立的 network namespace,但不爲容器進行任何網絡配置,須要咱們手動配置。應用場景比較少。
④ container:--net=container:<CONTAINER NAME/ID>
與指定的容器使用同一個 network namespace,具備一樣的網絡配置信息,兩個容器除了網絡,其它都是隔離的。
1) 建立容器,並映射 9090 端口到容器的 80 端口,進入容器內,經過 netstat -antp 能夠看到沒有端口鏈接信息
2) 建立 nginx 容器,並使用 net_container 容器的網絡。能夠看到 net_container 容器內已經在監聽 nginx 的80端口了,並且經過 映射的 9090 端口能夠訪問到 nginx 服務。
⑤ 自定義網絡
與默認的bridge原理同樣,但自定義網絡具有內部DNS發現,能夠經過容器名或者主機名進行容器之間網絡通訊
首先建立一個自定義網絡,建立兩個容器並加入到自定義網絡,在容器中就能夠互相連通。
二、容器網絡訪問原理
當 Docker 啓動時,會自動在主機上建立一個 docker0 虛擬網橋(其上有一個 docker0 內部接口),其實是Linux 的一個 bridge,能夠理解爲一個軟件交換機。它在內核層連通了其餘的物理或虛擬網卡,這就將全部容器和本地主機都放到同一個物理網絡。
每次建立一個新容器的時候,Docker 從可用的地址段中選擇一個空閒的 IP 地址分配給容器的 eth0 端口。使用本地主機上 docker0 接口的 IP 做爲全部容器的默認網關。
當建立一個 Docker 容器的時候,同時會建立一對 veth pair 接口(當數據包發送到一個接口時,另一個接口也能夠收到相同的數據包)。這對接口一端在容器內,即 eth0 ;另外一端在本地並被掛載到 docker0 網橋,名稱以 veth 開頭。經過這種方式,主機能夠跟容器通訊,容器之間也能夠相互通訊。Docker 就建立了在主機和全部容器之間的一個虛擬共享網絡。
7、製做鏡像
一、Dockerfile
鏡像是多層存儲,每一層是在前一層的基礎上進行的修改;Dockerfile 是一個文本文件,其內包含了一條條的指令(Instruction),每一條指令構建一層,所以每一條指令的內容,就是描述該層應當如何構建。
咱們所使用的鏡像基本都是來自於 Docker Hub 的鏡像,直接使用這些鏡像是能夠知足必定的需求,而當這些鏡像沒法直接知足需求時,咱們就須要定製這些鏡像。
編寫 Dockerfile 時,主要會用到以下一些指令:
Dockerfile 中每個指令都會創建一層,在其上執行後面的命令,執行結束後, commit 這一層的修改,構成新的鏡像。對於有些指令,儘可能將多個指令合併成一個指令,不然容易產生很是臃腫、很是多層的鏡像,不只僅增長了構建部署的時間,也很容易出錯。並且Union FS 是有最大層數限制的,好比 AUFS不得超過 127 層。所以鏡像構建時,必定要確保每一層只添加真正須要添加的東西,任何無關的東西都應該清理掉。
① FROM
一個 Dockerfile 中 FROM 是必備的指令,而且必須是第一條指令。
格式:FROM <鏡像名稱>[:<TAG>]
Docker 還存在一個特殊的鏡像,名爲 scratch 。這個鏡像並不實際存在,它表示一個空白的鏡像。若是以 scratch 爲基礎鏡像的話,意味着不以任何鏡像爲基礎,接下來所寫的指令將做爲鏡像第一層開始存在。
② RUN
RUN 指令是用來執行命令行命令的。因爲命令行的強大能力, RUN 指令在定製鏡像時是最經常使用的指令之一。
多個 RUN 指令儘可能合併成一個,使用 && 將各個所需命令串聯起來。Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方式,以及行首 # 進行註釋的格式。
格式:
- shell 格式: RUN <命令> ,就像直接在命令行中輸入的命令同樣。
- exec 格式: RUN ["可執行文件", "參數1", "參數2"] ,這更像是函數調用中的格式。
③ COPY
COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置。<源路徑> 能夠是多個,甚至能夠是通配符。<目標路徑> 能夠是容器內的絕對路徑,也能夠是相對於工做目錄的相對路徑。
使用 COPY 指令,源文件的各類元數據都會保留。好比讀、寫、執行權限、文件變動時間等。
格式:
- COPY <源路徑>,... <目標路徑>
- COPY ["<源路徑1>",... "<目標路徑>"]
④ ENV
設置環境變量,不管是後面的其它指令,如 RUN ,仍是運行時的應用,均可以直接使用這裏定義的環境變量。
格式:
- ENV <key> <value>
- ENV <key1>=<value1> <key2>=<value2>...
⑤ USER
USER 用於切換到指定用戶,這個用戶必須是事先創建好的,不然沒法切換。
格式: USER <用戶名>
⑥ EXPOSE
EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時並不會由於這個聲明應用就會開啓這個端口的服務。
格式:EXPOSE <端口1> [<端口2>...]
⑦ HEALTHCHECK
HEALTHCHECK 指令是告訴 Docker 應該如何判斷容器的狀態是否正常。經過該指令指定一行命令,用這行命令來判斷容器主進程的服務狀態是否還正常,從而比較真實的反應容器實際狀態。
當在一個鏡像指定了 HEALTHCHECK 指令後,用其啓動容器,初始狀態會爲 starting ,在 HEALTHCHECK 指令檢查成功後變爲 healthy ,若是連續必定次數失敗,則會變爲 unhealthy
格式:
- HEALTHCHECK [選項] CMD <命令> :設置檢查容器健康情況的命令,CMD 命令的返回值決定了該次健康檢查的成功與否: 0 - 成功; 1 - 失敗;。
- HEALTHCHECK NONE :若是基礎鏡像有健康檢查指令,使用這行能夠屏蔽掉其健康檢查指令
HEALTHCHECK 支持下列選項:
- --interval=<間隔> :兩次健康檢查的間隔,默認爲 30 秒;
- --timeout=<時長> :健康檢查命令運行超時時間,若是超過這個時間,本次健康檢查就被視爲失敗,默認 30 秒;
- --retries=<次數> :當連續失敗指定次數後,則將容器狀態視爲unhealthy ,默認 3 次。
⑧ WORKDIR
使用 WORKDIR 指令能夠來指定工做目錄(或者稱爲當前目錄),之後各層的當前目錄就被改成指定的目錄,該目錄須要已經存在, WORKDIR 並不會幫你創建目錄。
在Dockerfile 中,兩行 RUN 命令的執行環境是不一樣的,是兩個徹底不一樣的容器。每個 RUN 都是啓動一個容器、執行命令、而後提交存儲層文件變動。所以若是須要改變之後各層的工做目錄的位置,那麼應該使用 WORKDIR 指令。
格式:WORKDIR <工做目錄路徑>
⑨ VOLUME
容器運行時應該儘可能保持容器存儲層不發生寫操做,對於數據庫類須要保存動態數據的應用,其數據庫文件應該保存於卷(volume)中。爲了防止運行時用戶忘記將動態文件所保存目錄掛載爲卷,在 Dockerfile 中,咱們能夠事先指定某些目錄掛載爲匿名卷,這樣在運行時若是用戶不指定掛載,其應用也能夠正常運行,不會向容器存儲層寫入大量數據。
格式:
- VOLUME ["<路徑1>", "<路徑2>"...]
- VOLUME <路徑>
這裏的路徑會在運行時自動掛載爲匿名卷,任何向此路徑中寫入的信息都不會記錄進容器存儲層,從而保證了容器存儲層的無狀態化。
⑩ CMD
CMD 指令用於指定默認的容器主進程的啓動命令。
格式:
- shell 格式: CMD <命令>
- exec 格式: CMD ["可執行文件", "參數1", "參數2"...]
在運行時能夠指定新的命令來替代鏡像設置中的這個默認命令,跟在鏡像名後面的是 command ,運行時會替換 CMD 的默認值;例如:docker run -ti nginx /bin/bash,"/bin/bash" 就是替換命令。
在指令格式上,通常推薦使用 exec 格式,這類格式在解析時會被解析爲 JSON數組,必定要使用雙引號,而不要使用單引號。若是使用 shell 格式的話,實際的命令會被包裝爲 sh -c 的參數的形式執行,如:CMD echo $HOME 會被包裝爲 CMD [ "sh", "-c", "echo $HOME" ],實際就是一個 shell 進程。
注意:Docker 不是虛擬機,容器中的應用都應該之前臺執行。對於容器而言,其啓動程序就是容器應用進程,容器就是爲了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出。啓動程序時,應要求其之前臺形式運行。
⑪ ENTRYPOINT
ENTRYPOINT 的目的和 CMD 同樣,都是在指定容器啓動程序及參數。 ENTRYPOINT 在運行時也能夠替代,不過比 CMD 要略顯繁瑣,須要經過 docker run 的參數 --entrypoint 來指定。
格式:
- shell 格式: ENTRYPOINT <命令>
- exec 格式: ENTRYPOINT ["可執行文件", "參數1", "參數2"...]
當指定了 ENTRYPOINT 後, CMD 的含義就發生了改變,再也不是直接的運行其命令,而是將 CMD 的內容做爲參數傳給 ENTRYPOINT 指令。ENTRYPOINT 中的參數始終會被使用,而 CMD 的額外參數能夠在容器啓動時動態替換掉。
例如: ENTRYPOINT ["/bin/echo", "hello"] 容器經過 docker run -ti <image> 啓動時,輸出爲:hello 容器經過 docker run -ti <image> docker 啓動時,輸出爲:hello docker 將Dockerfile修改成: ENTRYPOINT ["/bin/echo", "hello"] CMD ["world"] 容器經過 docker run -ti <image> 啓動時,輸出爲:hello world 容器經過 docker run -ti <image> docker 啓動時,輸出爲:hello docker
二、構建基礎鏡像
以構建 nginx 基礎鏡像爲例看如何使用 Dockerfile 構建鏡像。
① 編寫 Dockerfile
# 基於 centos:8 構建基礎鏡像 FROM centos:8 # 做者 MAINTAINER jiangzhou.bo@vip.163.com # 安裝編譯依賴的 gcc 等環境,注意最後清除安裝緩存以減少鏡像體積 RUN yum install -y gcc gcc-c++ make \ openssl-devel pcre-devel gd-devel \ iproute net-tools telnet wget curl \ && yum clean all \ && rm -rf /var/cache/yum/* # 編譯安裝 nginx RUN wget http://nginx.org/download/nginx-1.17.4.tar.gz \ && tar zxf nginx-1.17.4.tar.gz \ && cd nginx-1.17.4 \ && ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module \ && make && make install \ && rm -rf /usr/local/nginx/html/* \ && echo "hello nginx !" >> /usr/local/nginx/html/index.html \ && cd / && rm -rf nginx-1.17.4* # 加入 nginx 環境變量 ENV PATH $PATH:/usr/local/nginx/sbin # 拷貝上下文目錄下的配置文件 COPY ./nginx.conf /usr/local/nginx/conf/nginx.conf # 設置工做目錄 WORKDIR /usr/local/nginx # 暴露端口 EXPOSE 80 # daemon off: 要求 nginx 之前臺進行運行 CMD ["nginx", "-g", "daemon off;"]
② 構建鏡像
命令:docker build -t <鏡像名稱>:<TAG> [-f <Dockerfile 路徑>] <上下文目錄>
- 上下文目錄:鏡像構建的上下文。Docker 是 C/S 結構,docker 命令是客戶端工具,一切命令都是使用的遠程調用形式在服務端(Docker 引擎)完成。當構建的時候,用戶指定構建鏡像上下文的路徑,docker build 命令得知這個路徑後,會將路徑下的全部內容打包,而後上傳給 Docker 引擎。這樣 Docker 引擎收到這個上下文包後,展開就會得到構建鏡像所需的一切文件。這樣在 COPY 文件的時候,其實是複製上下文路徑下的文件。通常來講,應該將 Dockerfile 以及所需文件置於一個空目錄下,並指定這個空目錄爲上下文目錄。
- Dockerfile 路徑:可選,缺省時會尋找當前目錄下的 Dockerfile 文件,若是是其它名稱的 Dockerfile,可使用 -f 參數指定文件路徑。
在 nginx 目錄下包含了構建須要的 Dockerfile 文件及配置文件,docker build 執行時,能夠清晰地看到鏡像的構建過程。構建成功後,就能夠在本地看到已經構建好的鏡像。
基於構建的鏡像啓用容器並測試:
③ 構建應用鏡像
構件好基礎鏡像以後,以這個基礎鏡像來構建應用鏡像。
首先編寫 Dockerfile:將項目下的 html 目錄拷貝到 nginx 目錄下
FROM bojiangzhou/nginx:v1 COPY ./html /usr/local/nginx/html
項目鏡像構建成功後,運行鏡像,能夠看到內容已經被替換了。咱們構建好的項目鏡像就能夠傳給其餘用戶去使用了。
8、鏡像倉庫
一、Habor
鏡像倉庫是集中存放鏡像的地方。目前 Docker 官方維護了一個公共倉庫 Docker Hub,大部分需求,均可以經過在 Docker Hub 中直接下載鏡像來實現。
有時候使用 Docker Hub 這樣的公共倉庫可能不方便,用戶能夠建立一個本地倉庫供私人使用。docker-registry 是官方提供的工具,能夠用於構建私有的鏡像倉庫。
Habor 是由 VMWare 公司開源的容器鏡像倉庫,Habor 在 docker-registry 上進行了相應的企業級擴展,從而得到了更加普遍的應用。這章學習如何使用 Habor 搭建本地私有倉庫。
Harbor 安裝及配置要求參考:Installation and Configuration Guide
Harbor 使用文檔參考:User Guide
安裝 Harbor 前,需確保硬件條件至少 2核4G內存40G的硬盤,本機需已安裝 docker、docker-compose、openssl。
二、安裝 Docker Compose
Docker Compose 是 Docker 官方編排(Orchestration)項目之一,負責快速在集羣中部署分佈式應用。使用 Docker Compose 能夠輕鬆、高效的管理容器,它是一個用於定義和運行多容器 Docker 的應用程序工具。它容許用戶經過一個單獨的 docker-compose.yml 模板文件來定義一組相關聯的應用容器爲一個項目。Harbor 也是基於 docker compose 編排部署的。
① 安裝 Docker Compose 能夠經過下面命令自動下載適應版本的 Compose,併爲安裝腳本添加執行權限
# curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose
② 檢測安裝是否成功
# docker-compose -v
三、安裝 Harbor
① 首先從 github 下載二進制包,選擇一個最新版本安裝:https://github.com/goharbor/harbor/releases
# wget https://storage.googleapis.com/harbor-releases/release-1.9.0/harbor-offline-installer-v1.9.1.tgz
② 解壓
# tar zxvf harbor-offline-installer-v1.9.1.tgz # cd harbor
③ 修改配置文件
# vim harbor.yml
主要修改 hostname 爲可訪問的域名或IP、修改管理員密碼
④ 安裝
# ./prepare # ./install.sh
Harbor 安裝成功後,實際上就是經過 docker compose 啓動了相關組件的容器
⑤ Harbor 生命週期管理
harbor 基於 docker compose 編排部署,所以可使用 docker-compose 命令來管理 harbor 的生命週期。
首先切到 harbor 根目錄下
中止 harbor:docker-compose stop
重啓 harbor:docker-compose start
修改配置:
# #先中止 harbor # docker-compose down -v # #修改 harbor.yml # vim harbor.yml # #運行 prepare 填充配置 # ./prepare # #啓動harbor # docker-compose up -d
四、Harbor 簡單使用
① 訪問 Harbor
訪問配置的 hostname 進入 harbor 管理頁面。具體如何使用可參考官方文檔:User Guide
經過新建項目建立一個項目(bojiangzhou)用於測試。公開項目不需登陸就能夠下載鏡像,私有的須要登陸;上傳鏡像則都須要登陸才能上傳鏡像。
推送鏡像的命令格式能夠參考以下:
② 建立用戶
若想上傳鏡像,須要用戶登陸,首先在用戶管理建立用戶:
接着在項目中添加用戶成員:
③ 前置配置
上傳鏡像以前,首先須要將 harbor 倉庫配置爲 docker 授信的倉庫,不然將被拒絕鏈接:
vim /etc/docker/daemon.json # 配置以下內容 { "registry-mirrors": ["http://f1361db2.m.daocloud.io"], "insecure-registries": ["192.168.31.54"] }
以後重啓 docker 和 harbor:
#systemctl restart docker # cd /docker-test/harbor # docker-compose up -d
④ 鏡像倉庫登陸退出
登陸:docker login registry
退出:docker logout registry
⑤ 上傳鏡像
首先須要給鏡像打 Tag:docker tag SOURCE_IMAGE[:TAG] 192.168.31.54/bojiangzhou/IMAGE[:TAG]
接着推送鏡像:docker push 192.168.31.54/bojiangzhou/IMAGE[:TAG]
能夠看到鏡像已經推送到鏡像倉庫了:
下載倉庫鏡像:docker pull 192.168.31.54/bojiangzhou/nginx-app:1.0.0
9、圖形化管理
Portainer 是一個開源、輕量級 Docker 管理用戶頁面,基於 Docker API,管理 Docker 主機。通常單機下不會使用圖形管理頁面,這裏簡單瞭解下就好。
一、安裝 Portainer
① 建立數據卷:docker volume create portainer_volume
② 啓動 Portainer 容器:docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_volume:/data portainer/portainer
二、訪問 Portainer
訪問 ip:9000,便可進入 Portainer 管理頁面,首先須要建立一個管理用戶
接着鏈接本機
鏈接本地進入後就能夠進行容器、鏡像等的管理了。
--------------------------------------------------------------------------------------------------------------------------------