如何通過(guò)DOCKER OVERLAY2目錄名查找容器名和容器ID
通過(guò)DOCKER OVERLAY2目錄名查找容器名和容器ID
有時(shí)候經(jīng)常會(huì)有個(gè)別容器占用磁盤(pán)空間特別大,這個(gè)時(shí)候就需要通過(guò)docker overlay2 目錄名查找對(duì)應(yīng)容器名:
1.首先進(jìn)入到 /var/lib/docker/overlay2 目錄下,查看誰(shuí)占用的較多
du -s ./* | sort -rn | more
2、查出所占用的大文件
3、再通過(guò)目錄名查找容器名
?docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}}' | grep bff25099a59b0fc8addd06f9223872f2904256f0432b3c3c47b58faef167115f
輸出依次為,進(jìn)程pid、容器ID、容器名、存儲(chǔ)work路徑,即可確定是哪個(gè)容器。
DOCKER入門(mén)
Docker基礎(chǔ)
docker保姆級(jí)教程
https://github.com/yeasy/docker_practice/blob/master/SUMMARY.md
Docker系統(tǒng)有兩個(gè)程序
docker服務(wù)端和docker客戶(hù)端。
其中docker服務(wù)端是一個(gè)服務(wù)進(jìn)程,管理著所有的容器。
docker客戶(hù)端則扮演著docker服務(wù)端的遠(yuǎn)程控制器,可以用來(lái)控制docker的服務(wù)端進(jìn)程。
大部分情況下,docker服務(wù)端和客戶(hù)端運(yùn)行在一臺(tái)機(jī)器上。
常用命令
// 查看docker版本信息 docker version // 搜索可用的鏡像 docker search mysql //拉取鏡像-默認(rèn)是拉取的最新版本 docker pull mysql //拉取鏡像-特定版本拉取(版本號(hào)一定要是官方放出的版本號(hào),否則是查找不到的) docker pull mysql:8.0.22 // 列舉本機(jī)所有鏡像 docker images -a // 列出鏡像結(jié)果,并且只包含鏡像ID和倉(cāng)庫(kù)名 docker images --format "{{.ID}}: {{.Repository}}" // 刪除鏡像('xxx'可以為鏡像id或鏡像REPOSITORY) docker rmi xxx // 保存對(duì)容器的修改(如安裝了ping) 參見(jiàn)https://www.docker.org.cn/book/docker/docer-save-changes-10.html 查看被修改的容器 :docker ps -l 提交指定容器保存為新的鏡像: docker commit <container id> <new image name> // 查看容器詳細(xì)信息 docker inspect xxx // 查看所有容器 docker ps -a [or] docker container ls -a // 查看運(yùn)行中的容器 docker ps // 刪除指定容器(Docker 會(huì)發(fā)送 SIGKILL 信號(hào)給容器。 加-f是刪除處于運(yùn)行中的容器) docker rm -f xxx // 查看docker容器日志 docker logs xxx // 新建并啟動(dòng)容器 docker run // docker run命令實(shí)用參數(shù)舉例 -d 讓docker處于后臺(tái)運(yùn)行 -P 容器內(nèi)部端口隨機(jī)映射到主機(jī)的端口 -p 容器內(nèi)部端口綁定到主機(jī)指定的端口(使用:docker run -d -p <主機(jī)端口>:<容器端口> ...) --name 給容器起別名(使用:docker run -d -P --name <容器別名> <鏡像>) -it 進(jìn)入交互式終端(這是兩個(gè)參數(shù),一個(gè)是 -i 交互式操作,一個(gè)是 -t 終端。通常還會(huì)在鏡像名后跟一個(gè)命令,如我們希望有個(gè)交互式 Shell,因此在鏡像后會(huì)跟一個(gè) bash) --rm 這個(gè)參數(shù)是說(shuō)容器退出后隨之將其刪除。 -v 添加數(shù)據(jù)卷(-v /my/own/datadir:/var/lib/mysql /my/own/datadir是主機(jī)的數(shù)據(jù)庫(kù)路徑 /var/lib/mysql是容器中的數(shù)據(jù)庫(kù)路徑) // 查看指定容器的啟動(dòng)命令 docker ps -a --no-trunc | grep xxx [or] 在docker inspect的Path參數(shù)也可見(jiàn) // 查看容器端口綁定情況 docker port xxx // 查看docker網(wǎng)絡(luò) docker network ls // 創(chuàng)建網(wǎng)絡(luò) docker network create -d bridge test-net (說(shuō)明:-d用于指定docker網(wǎng)絡(luò)類(lèi)型,分為bridge、overlay) // 連接容器(運(yùn)行一個(gè)容器并連接到新建的 test-net 網(wǎng)絡(luò)) docker run -itd --name test1 --network test-net ubuntu /bin/bash docker run -itd --name test2 --network test-net ubuntu /bin/bash (而后,test1、test2容器間便可以互相ping通了) // 進(jìn)入容器后,若發(fā)現(xiàn)有的命令不支持,如:ping www.baidu.com,提示:`bash: ping: command not found` // 這時(shí)就需要手動(dòng)安裝對(duì)應(yīng)命令了。但執(zhí)行apt-get install ping時(shí),又提示:`E: Unable to locate package ping` // 解決方式:先執(zhí)行apt-get update,再執(zhí)行apt-get install ping即可 // 構(gòu)建鏡像 docker build -t xxx .
拓展
redis-shake是一個(gè)用于做redis數(shù)據(jù)遷移的工具,并提供一定程度的數(shù)據(jù)清洗能力。
參見(jiàn):https://github.com/alibaba/RedisShake/blob/v3/README_zh.md
docker簡(jiǎn)介
參考:https://docs.kilvn.com/docker_practice/introduction/why.html
Docker 技術(shù)比虛擬機(jī)技術(shù)更為輕便、快捷。
傳統(tǒng)虛擬機(jī)技術(shù)是虛擬出一套硬件后,在其上運(yùn)行一個(gè)完整操作系統(tǒng),在該系統(tǒng)上再運(yùn)行所需應(yīng)用進(jìn)程;
而容器內(nèi)的應(yīng)用進(jìn)程直接運(yùn)行于宿主的內(nèi)核,容器內(nèi)沒(méi)有自己的內(nèi)核,而且也沒(méi)有進(jìn)行硬件虛擬。因此容器要比傳統(tǒng)虛擬機(jī)更為輕便。
** Q:docker優(yōu)勢(shì) ** 1、更高效的利用系統(tǒng)資源 由于容器不需要進(jìn)行硬件虛擬以及運(yùn)行完整操作系統(tǒng)等額外開(kāi)銷(xiāo),Docker 對(duì)系統(tǒng)資源的利用率更高。 無(wú)論是應(yīng)用執(zhí)行速度、內(nèi)存損耗或者文件存儲(chǔ)速度,都要比傳統(tǒng)虛擬機(jī)技術(shù)更高效。 因此,相比虛擬機(jī)技術(shù),一個(gè)相同配置的主機(jī),往往可以運(yùn)行更多數(shù)量的應(yīng)用。 2、更快速的啟動(dòng)時(shí)間 Docker容器應(yīng)用,由于直接運(yùn)行于宿主內(nèi)核,無(wú)需啟動(dòng)完整的操作系統(tǒng), 因此可以做到秒級(jí)、甚至毫秒級(jí)的啟動(dòng)時(shí)間。大大的節(jié)約了開(kāi)發(fā)、測(cè)試、部署的時(shí)間。 3、一致的運(yùn)行環(huán)境 開(kāi)發(fā)過(guò)程中一個(gè)常見(jiàn)的問(wèn)題是環(huán)境一致性問(wèn)題。 由于開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境不一致,導(dǎo)致有些 bug 并未在開(kāi)發(fā)過(guò)程中被發(fā)現(xiàn)。 而 Docker 的鏡像提供了除內(nèi)核外完整的運(yùn)行時(shí)環(huán)境,確保了應(yīng)用運(yùn)行環(huán)境一致性, 從而不會(huì)再出現(xiàn) “這段代碼在我機(jī)器上沒(méi)問(wèn)題啊” 這類(lèi)問(wèn)題。 4、持續(xù)交付和部署 對(duì)開(kāi)發(fā)和運(yùn)維(DevOps)人員來(lái)說(shuō),最希望的就是一次創(chuàng)建或配置,可以在任意地方正常運(yùn)行。 使用 Docker 可以通過(guò)定制應(yīng)用鏡像來(lái)實(shí)現(xiàn)持續(xù)集成、持續(xù)交付、部署。 開(kāi)發(fā)人員可以通過(guò) Dockerfile 來(lái)進(jìn)行鏡像構(gòu)建,并結(jié)合 持續(xù)集成(Continuous Integration) 系統(tǒng)進(jìn)行集成測(cè)試, 而運(yùn)維人員則可以直接在生產(chǎn)環(huán)境中快速部署該鏡像,甚至結(jié)合 持續(xù)部署(Continuous Delivery/Deployment) 系統(tǒng)進(jìn)行自動(dòng)部署。 5、更輕松的遷移 由于 Docker 確保了執(zhí)行環(huán)境的一致性,使得應(yīng)用的遷移更加容易。 因此用戶(hù)可以很輕易的將在一個(gè)平臺(tái)上運(yùn)行的應(yīng)用,遷移到另一個(gè)平臺(tái)上,而不用擔(dān)心運(yùn)行環(huán)境的變化導(dǎo)致應(yīng)用無(wú)法正常運(yùn)行的情況。 6、更輕松的擴(kuò)展和維護(hù) Docker 使用的分層存儲(chǔ)以及鏡像的技術(shù),使得應(yīng)用重復(fù)部分的復(fù)用更為容易, 也使得應(yīng)用的維護(hù)更新更加簡(jiǎn)單,基于基礎(chǔ)鏡像進(jìn)一步擴(kuò)展鏡像也變得非常簡(jiǎn)單。
基本概念
鏡像
操作系統(tǒng)分為內(nèi)核和用戶(hù)空間。
對(duì)于 Linux 而言,內(nèi)核啟動(dòng)后,會(huì)掛載 root 文件系統(tǒng)為其提供用戶(hù)空間支持。
而 Docker 鏡像(Image),就相當(dāng)于是一個(gè) root 文件系統(tǒng)。比如官方鏡像 ubuntu:14.04 就包含了完整的一套 Ubuntu 14.04 最小系統(tǒng)的 root 文件系統(tǒng)。
Docker 鏡像是一個(gè)特殊的文件系統(tǒng),除了提供容器運(yùn)行時(shí)所需的程序、庫(kù)、資源、配置等文件外,還包含了一些為運(yùn)行時(shí)準(zhǔn)備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶(hù)等)。鏡像不包含任何動(dòng)態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會(huì)被改變。
注意,當(dāng)我們運(yùn)行一個(gè)容器的時(shí)候(如果不使用卷,也沒(méi)綁定宿主機(jī)目錄的話(huà)),我們做的任何文件修改都會(huì)被記錄于容器存儲(chǔ)層里。而 Docker 提供了一個(gè) docker commit 命令,可以將容器的存儲(chǔ)層保存下來(lái)成為鏡像。
換句話(huà)說(shuō),就是在原有鏡像的基礎(chǔ)上,再疊加上容器的存儲(chǔ)層,并構(gòu)成新的鏡像。以后我們運(yùn)行這個(gè)新鏡像的時(shí)候,就會(huì)擁有原有容器最后的文件變化。
// docker commit 的語(yǔ)法格式為: docker commit [選項(xiàng)] <容器ID或容器名> [<倉(cāng)庫(kù)名>[:<標(biāo)簽>]] // 舉例 $ docker commit \ --author "Tao Wang <twang2218@gmail.com>" \ --message "修改了默認(rèn)網(wǎng)頁(yè)" \ webserver \ nginx:v2 // 查看鏡像的歷史版本提交信息 docker history nginx:v2
需慎用 docker commit
去生成鏡像,其生成的鏡像被稱(chēng)為黑箱鏡像。換句話(huà)說(shuō),就是除了制作鏡像的人知道執(zhí)行過(guò)什么命令、怎么生成的鏡像,別人根本無(wú)從得知,這種黑箱鏡像的維護(hù)工作是非常痛苦的。
回顧之前提及的鏡像所使用的分層存儲(chǔ)的概念,除當(dāng)前層外,之前的每一層都是不會(huì)發(fā)生改變的,換句話(huà)說(shuō),任何修改的結(jié)果僅僅是在當(dāng)前層進(jìn)行標(biāo)記、添加、修改,而不會(huì)改動(dòng)上一層。如果使用 docker commit 制作鏡像,以及后期修改的話(huà),每一次修改都會(huì)讓鏡像更加臃腫一次,所刪除的上一層的東西并不會(huì)丟失,會(huì)一直如影隨形的跟著這個(gè)鏡像,即使根本無(wú)法訪問(wèn)到™。這會(huì)讓鏡像更加臃腫。
鏡像的定制行為應(yīng)該使用 Dockerfile
來(lái)完成。
容器
鏡像(Image)和容器(Container)的關(guān)系,就像是面向?qū)ο蟪绦蛟O(shè)計(jì)中的類(lèi)和實(shí)例一樣。
鏡像是靜態(tài)的定義,容器是鏡像運(yùn)行時(shí)的實(shí)體。容器可以被創(chuàng)建、啟動(dòng)、停止、刪除、暫停等。
容器的實(shí)質(zhì)是進(jìn)程,但與直接在宿主執(zhí)行的進(jìn)程不同,容器進(jìn)程運(yùn)行于屬于自己的獨(dú)立的 命名空間。因此容器可以擁有自己的 root 文件系統(tǒng)、自己的網(wǎng)絡(luò)配置、自己的進(jìn)程空間,甚至自己的用戶(hù) ID 空間。容器內(nèi)的進(jìn)程是運(yùn)行在一個(gè)隔離的環(huán)境里,使用起來(lái),就好像是在一個(gè)獨(dú)立于宿主的系統(tǒng)下操作一樣。這種特性使得容器封裝的應(yīng)用比直接在宿主運(yùn)行更加安全。
每一個(gè)容器運(yùn)行時(shí),是以鏡像為基礎(chǔ)層,在其上創(chuàng)建一個(gè)當(dāng)前容器的存儲(chǔ)層,我們可以稱(chēng)這個(gè)為容器運(yùn)行時(shí)讀寫(xiě)而準(zhǔn)備的存儲(chǔ)層為容器存儲(chǔ)層。
容器存儲(chǔ)層的生存周期和容器一樣,容器消亡時(shí),容器存儲(chǔ)層也隨之消亡。因此,任何保存于容器存儲(chǔ)層的信息都會(huì)隨容器刪除而丟失。
按照 Docker 最佳實(shí)踐的要求,容器不應(yīng)該向其存儲(chǔ)層內(nèi)寫(xiě)入任何數(shù)據(jù),容器存儲(chǔ)層要保持無(wú)狀態(tài)化。所有的文件寫(xiě)入操作,都應(yīng)該使用 數(shù)據(jù)卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫(xiě)會(huì)跳過(guò)容器存儲(chǔ)層,直接對(duì)宿主(或網(wǎng)絡(luò)存儲(chǔ))發(fā)生讀寫(xiě),其性能和穩(wěn)定性更高。
數(shù)據(jù)卷的生存周期獨(dú)立于容器,容器消亡,數(shù)據(jù)卷不會(huì)消亡。因此,使用數(shù)據(jù)卷后,容器可以隨意刪除、重新 run,數(shù)據(jù)卻不會(huì)丟失。
當(dāng)利用 docker run 來(lái)創(chuàng)建容器時(shí),Docker 在后臺(tái)運(yùn)行的標(biāo)準(zhǔn)操作包括:
- 檢查本地是否存在指定的鏡像,不存在就從公有倉(cāng)庫(kù)下載
- 利用鏡像創(chuàng)建并啟動(dòng)一個(gè)容器
- 分配一個(gè)文件系統(tǒng),并在只讀的鏡像層外面掛載一層可讀寫(xiě)層
- 從宿主主機(jī)配置的網(wǎng)橋接口中橋接一個(gè)虛擬接口到容器中去
- 從地址池配置一個(gè) ip 地址給容器
- 執(zhí)行用戶(hù)指定的應(yīng)用程序
- 執(zhí)行完畢后容器被終止
倉(cāng)庫(kù)
一個(gè) Docker Registry 中可以包含多個(gè)倉(cāng)庫(kù)(Repository);每個(gè)倉(cāng)庫(kù)可以包含多個(gè)標(biāo)簽(Tag);每個(gè)標(biāo)簽對(duì)應(yīng)一個(gè)鏡像。
通常,一個(gè)倉(cāng)庫(kù)會(huì)包含同一個(gè)軟件不同版本的鏡像,而標(biāo)簽就常用于對(duì)應(yīng)該軟件的各個(gè)版本。我們可以通過(guò) <倉(cāng)庫(kù)名>:<標(biāo)簽> 的格式來(lái)指定具體是這個(gè)軟件哪個(gè)版本的鏡像。如果不給出標(biāo)簽,將以 latest 作為默認(rèn)標(biāo)簽。
倉(cāng)庫(kù)名經(jīng)常以 兩段式路徑 形式出現(xiàn),比如 jwilder/nginx-proxy,前者往往意味著 Docker Registry 多用戶(hù)環(huán)境下的用戶(hù)名,后者則往往是對(duì)應(yīng)的軟件名。
注冊(cè)服務(wù)器(Registry)是管理倉(cāng)庫(kù)(Repository)的具體服務(wù)器,倉(cāng)庫(kù)是集中存放鏡像的地方。
利用DockerFile定制鏡像
參見(jiàn):https://docs.kilvn.com/docker_practice/image/build.html
從之前的 docker commit 的學(xué)習(xí)中,我們可以了解到:鏡像的定制實(shí)際上就是定制每一層所添加的配置、文件。
如果我們可以把每一層修改、安裝、構(gòu)建、操作的命令都寫(xiě)入一個(gè)腳本,用這個(gè)腳本來(lái)構(gòu)建、定制鏡像,那么之前提及的無(wú)法重復(fù)的問(wèn)題、鏡像構(gòu)建透明性的問(wèn)題、體積的問(wèn)題就都會(huì)解決。這個(gè)腳本就是 Dockerfile。
Dockerfile 是一個(gè)文本文件,其內(nèi)包含了一條條的指令(Instruction),每一條指令構(gòu)建一層。
在docker build 命令最后有一個(gè) . 表示當(dāng)前目錄,其實(shí)這是在指定上下文路徑。
當(dāng)構(gòu)建的時(shí)候,用戶(hù)會(huì)指定構(gòu)建鏡像上下文的路徑,docker build 命令得知這個(gè)路徑后,會(huì)將路徑下的所有內(nèi)容打包,然后上傳給 Docker 引擎。這樣 Docker 引擎收到這個(gè)上下文包后,展開(kāi)就會(huì)獲得構(gòu)建鏡像所需的一切文件。
一般來(lái)說(shuō),應(yīng)該會(huì)將 Dockerfile 置于一個(gè)空目錄下,或者項(xiàng)目根目錄下。如果該目錄下沒(méi)有所需文件,那么應(yīng)該把所需文件復(fù)制一份過(guò)來(lái)。如果目錄下有些東西確實(shí)不希望構(gòu)建時(shí)傳給 Docker 引擎,那么可以用 .gitignore
一樣的語(yǔ)法寫(xiě)一個(gè) .dockerignore
,該文件是用于剔除不需要作為上下文傳遞給 Docker 引擎的。
在默認(rèn)情況下,如果不額外指定 Dockerfile 的話(huà),會(huì)將上下文目錄下的名為 Dockerfile 的文件作為 Dockerfile。
這只是默認(rèn)行為,實(shí)際上 Dockerfile 的文件名并不要求必須為 Dockerfile,而且并不要求必須位于上下文目錄中,比如可以用 -f …/Dockerfile.php 參數(shù)指定某個(gè)文件作為 Dockerfile。
常規(guī)構(gòu)建方法
docker build -t xxx .
其它構(gòu)建方法
1.直接用 Git repo 進(jìn)行構(gòu)建
docker build 還支持從 URL 構(gòu)建,比如可以直接從 Git repo 中構(gòu)建:
docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14
說(shuō)明:這行命令指定了構(gòu)建所需的 Git repo,并且指定默認(rèn)的 master 分支,構(gòu)建目錄為 /8.14/,然后 Docker 就會(huì)自己去 git clone 這個(gè)項(xiàng)目、切換到指定分支、并進(jìn)入到指定目錄后開(kāi)始構(gòu)建。
2.用給定的 tar 壓縮包構(gòu)建
docker build http://server/context.tar.gz
如果所給出的 URL 不是個(gè) Git repo,而是個(gè) tar 壓縮包,那么 Docker 引擎會(huì)下載這個(gè)包,并自動(dòng)解壓縮,以其作為上下文,開(kāi)始構(gòu)建。
3.從標(biāo)準(zhǔn)輸入中讀取 Dockerfile 進(jìn)行構(gòu)建
4.從標(biāo)準(zhǔn)輸入中讀取上下文壓縮包進(jìn)行構(gòu)建
Dockerfile指令詳解
// Dockerfile指令詳解 - FROM 指定基礎(chǔ)鏡像 所謂定制鏡像,那一定是以一個(gè)鏡像為基礎(chǔ),在其上進(jìn)行定制。而 FROM 就是指定基礎(chǔ)鏡像。 因此一個(gè) Dockerfile 中 FROM 是必備的指令,并且必須是第一條指令。 (Docker 還存在一個(gè)特殊的鏡像,名為 scratch。這個(gè)鏡像是虛擬的概念,并不實(shí)際存在,它表示一個(gè)空白的鏡像。因此直接 FROM scratch 會(huì)讓鏡像體積更加小巧。 如果以 scratch 為基礎(chǔ)鏡像的話(huà),意味著你不以任何鏡像為基礎(chǔ),接下來(lái)所寫(xiě)的指令將作為鏡像第一層開(kāi)始存在。) - RUN 執(zhí)行命令 其格式有兩種: 1. shell 格式:RUN <命令> 2. exec 格式:RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"] 每一個(gè) RUN 都是啟動(dòng)一個(gè)容器、執(zhí)行命令、然后提交存儲(chǔ)層文件變更。 對(duì)于有多個(gè)命令的情況,建議將命令間用‘&&'連接,避免多層構(gòu)建鏡像。正確示例: RUN buildDeps='gcc libc6-dev make' \ && apt-get update \ && apt-get install -y $buildDeps - COPY 復(fù)制文件 格式: COPY <源路徑>... <目標(biāo)路徑> COPY ["<源路徑1>",... "<目標(biāo)路徑>"] COPY 指令將從構(gòu)建上下文目錄中 <源路徑> 的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的 <目標(biāo)路徑> 位置。 比如: COPY package.json /usr/src/app/ COPY hom* /mydir/ <源路徑> 可以是多個(gè),甚至可以是通配符 <目標(biāo)路徑> 可以是容器內(nèi)的絕對(duì)路徑,也可以是相對(duì)于工作目錄的相對(duì)路徑(工作目錄可以用 WORKDIR 指令來(lái)指定)。 目標(biāo)路徑不需要事先創(chuàng)建,如果目錄不存在會(huì)在復(fù)制文件前先行創(chuàng)建缺失目錄。 - ADD 更高級(jí)的復(fù)制文件 ADD 指令和 COPY 的格式和性質(zhì)基本一致,但也有所不同。 比如 <源路徑> 可以是一個(gè) URL,這種情況下,Docker 引擎會(huì)試圖去下載這個(gè)鏈接的文件放到 <目標(biāo)路徑> 去。 下載后的文件權(quán)限自動(dòng)設(shè)置為 600,如果這并不是想要的權(quán)限,那么還需要增加額外的一層 RUN 進(jìn)行權(quán)限調(diào)整; 另外,如果下載的是個(gè)壓縮包,需要解壓縮,也一樣還需要額外的一層 RUN 指令進(jìn)行解壓縮。 所以不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下載,處理權(quán)限、解壓縮、然后清理無(wú)用文件更合理。 因此,這個(gè)功能其實(shí)并不實(shí)用,而且不推薦使用。 如果 <源路徑> 為一個(gè) tar 壓縮文件的話(huà),壓縮格式為 gzip, bzip2 以及 xz 的情況下,ADD 指令將會(huì)自動(dòng)解壓縮這個(gè)壓縮文件到 <目標(biāo)路徑> 去。 在 Docker 官方的最佳實(shí)踐文檔中要求,盡可能的使用 COPY,因?yàn)?COPY 的語(yǔ)義很明確,就是復(fù)制文件而已,而 ADD 則包含了更復(fù)雜的功能,其行為也不一定很清晰。 另外需要注意的是,ADD 指令會(huì)令鏡像構(gòu)建緩存失效,從而可能會(huì)令鏡像構(gòu)建變得比較緩慢。 - CMD 容器啟動(dòng)命令 CMD 指令的格式和 RUN 相似,也是兩種格式: shell 格式:CMD <命令> exec 格式:CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"...] Docker不是虛擬機(jī),容器就是進(jìn)程。既然是進(jìn)程,那么在啟動(dòng)容器的時(shí)候,需要指定所運(yùn)行的程序及參數(shù)。 CMD 指令就是用于指定默認(rèn)的容器主進(jìn)程的啟動(dòng)命令的。 在指令格式上,一般推薦使用 exec 格式,這類(lèi)格式在解析時(shí)會(huì)被解析為 JSON 數(shù)組,因此一定要使用雙引號(hào) ",而不要使用單引號(hào)。 如果使用 shell 格式的話(huà),實(shí)際的命令會(huì)被包裝為 sh -c 的參數(shù)的形式進(jìn)行執(zhí)行。比如: CMD echo $HOME 在實(shí)際執(zhí)行中,會(huì)將其變更為: CMD [ "sh", "-c", "echo $HOME" ] 提到 CMD 就不得不提容器中應(yīng)用在前臺(tái)執(zhí)行和后臺(tái)執(zhí)行的問(wèn)題。 容器中的應(yīng)用都應(yīng)該以前臺(tái)執(zhí)行,而不是像虛擬機(jī)、物理機(jī)里面那樣,用 upstart/systemd 去啟動(dòng)后臺(tái)服務(wù),容器內(nèi)沒(méi)有后臺(tái)服務(wù)的概念。 對(duì)于容器而言,其啟動(dòng)程序就是容器應(yīng)用進(jìn)程,容器就是為了主進(jìn)程而存在的,主進(jìn)程退出,容器就失去了存在的意義,從而退出,其它輔助進(jìn)程不是它需要關(guān)心的東西。 舉例: CMD service nginx start 使用 service nginx start 命令,是希望以后臺(tái)守護(hù)進(jìn)程形式啟動(dòng) nginx 服務(wù)。 而剛才說(shuō)了 CMD service nginx start 會(huì)被理解為 CMD [ "sh", "-c", "service nginx start"],因此主進(jìn)程實(shí)際上是 sh。 那么當(dāng) service nginx start 命令結(jié)束后,sh 也就結(jié)束了,sh 作為主進(jìn)程退出了,自然就會(huì)令容器退出。 正確的做法是直接執(zhí)行 nginx 可執(zhí)行文件,并且要求以前臺(tái)形式運(yùn)行。比如: CMD ["nginx", "-g", "daemon off;"] - ENTRYPOINT 入口點(diǎn) ENTRYPOINT 的目的和 CMD 一樣,都是在指定容器啟動(dòng)程序及參數(shù)。ENTRYPOINT 在運(yùn)行時(shí)也可以替代,不過(guò)比 CMD 要略顯繁瑣,需要通過(guò) docker run 的參數(shù) --entrypoint 來(lái)指定。 當(dāng)指定了 ENTRYPOINT 后,CMD 的含義就發(fā)生了改變,不再是直接的運(yùn)行其命令,而是將 CMD 的內(nèi)容作為參數(shù)傳給 ENTRYPOINT 指令,換句話(huà)說(shuō)實(shí)際執(zhí)行時(shí),將變?yōu)椋? <ENTRYPOINT> "<CMD>" 其使用場(chǎng)景及好處參見(jiàn):https://docs.kilvn.com/docker_practice/image/dockerfile/entrypoint.html - ENV 設(shè)置環(huán)境變量 格式有兩種: ENV <key> <value> ENV <key1>=<value1> <key2>=<value2>... 這個(gè)指令很簡(jiǎn)單,就是設(shè)置環(huán)境變量而已。 環(huán)境變量可以使用的地方很多,很強(qiáng)大。通過(guò)環(huán)境變量,我們可以讓一份 Dockerfile 制作更多的鏡像,只需使用不同的環(huán)境變量即可。 - VOLUME 定義匿名卷 格式為: VOLUME ["<路徑1>", "<路徑2>"...] VOLUME <路徑> 之前我們說(shuō)過(guò),容器運(yùn)行時(shí)應(yīng)該盡量保持容器存儲(chǔ)層不發(fā)生寫(xiě)操作,對(duì)于數(shù)據(jù)庫(kù)類(lèi)需要保存動(dòng)態(tài)數(shù)據(jù)的應(yīng)用,其數(shù)據(jù)庫(kù)文件應(yīng)該保存于卷(volume)中。 為了防止運(yùn)行時(shí)用戶(hù)忘記將動(dòng)態(tài)文件所保存目錄掛載為卷,在 Dockerfile 中,我們可以事先指定某些目錄掛載為匿名卷, 這樣在運(yùn)行時(shí)如果用戶(hù)不指定掛載,其應(yīng)用也可以正常運(yùn)行,不會(huì)向容器存儲(chǔ)層寫(xiě)入大量數(shù)據(jù)。 VOLUME /data 這里的 /data 目錄就會(huì)在運(yùn)行時(shí)自動(dòng)掛載為匿名卷,任何向 /data 中寫(xiě)入的信息都不會(huì)記錄進(jìn)容器存儲(chǔ)層, 從而保證了容器存儲(chǔ)層的無(wú)狀態(tài)化。當(dāng)然,運(yùn)行時(shí)可以覆蓋這個(gè)掛載設(shè)置。比如: docker run -d -v mydata:/data xxxx 在這行命令中,就使用了 mydata 這個(gè)命名卷掛載到了 /data 這個(gè)位置,替代了 Dockerfile 中定義的匿名卷的掛載配置。 - EXPOSE 聲明端口 格式為 EXPOSE <端口1> [<端口2>...] 指令是聲明運(yùn)行時(shí)容器提供服務(wù)端口,這只是一個(gè)聲明,在運(yùn)行時(shí)并不會(huì)因?yàn)檫@個(gè)聲明應(yīng)用就會(huì)開(kāi)啟這個(gè)端口的服務(wù)。 在 Dockerfile 中寫(xiě)入這樣的聲明有兩個(gè)好處: 一個(gè)是幫助鏡像使用者理解這個(gè)鏡像服務(wù)的守護(hù)端口,以方便配置映射; 另一個(gè)用處則是在運(yùn)行時(shí)使用隨機(jī)端口映射時(shí),也就是 docker run -P 時(shí),會(huì)自動(dòng)隨機(jī)映射 EXPOSE 的端口。 - WORKDIR 指定工作目錄 格式為 WORKDIR <工作目錄路徑> 使用 WORKDIR 指令可以來(lái)指定工作目錄(或者稱(chēng)為當(dāng)前目錄),以后各層的當(dāng)前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR 會(huì)幫你建立目錄。 - USER 指定當(dāng)前用戶(hù) 格式:USER <用戶(hù)名> USER 指令和 WORKDIR 相似,都是改變環(huán)境狀態(tài)并影響以后的層。 WORKDIR 是改變工作目錄, USER 則是改變之后層的執(zhí)行 RUN, CMD 以及 ENTRYPOINT 這類(lèi)命令的身份。 - HEALTHCHECK 健康檢查 格式: HEALTHCHECK [選項(xiàng)] CMD <命令>:設(shè)置檢查容器健康狀況的命令 HEALTHCHECK NONE:如果基礎(chǔ)鏡像有健康檢查指令,使用這行可以屏蔽掉其健康檢查指令 HEALTHCHECK 指令是告訴 Docker 應(yīng)該如何進(jìn)行判斷容器的狀態(tài)是否正常,這是 Docker 1.12 引入的新指令。 自 1.12 之后,Docker 提供了 HEALTHCHECK 指令,通過(guò)該指令指定一行命令,用這行命令來(lái)判斷容器主進(jìn)程的服務(wù)狀態(tài)是否還正常,從而比較真實(shí)的反應(yīng)容器實(shí)際狀態(tài)。 背景: 在沒(méi)有 HEALTHCHECK 指令前,Docker 引擎只可以通過(guò)容器內(nèi)主進(jìn)程是否退出來(lái)判斷容器是否狀態(tài)異常。 很多情況下這沒(méi)問(wèn)題,但是如果程序進(jìn)入死鎖狀態(tài),或者死循環(huán)狀態(tài),應(yīng)用進(jìn)程并不退出,但是該容器已經(jīng)無(wú)法提供服務(wù)了。 在 1.12 以前,Docker 不會(huì)檢測(cè)到容器的這種狀態(tài),從而不會(huì)重新調(diào)度,導(dǎo)致可能會(huì)有部分容器已經(jīng)無(wú)法提供服務(wù)了卻還在接受用戶(hù)請(qǐng)求。 當(dāng)在一個(gè)鏡像指定了 HEALTHCHECK 指令后,用其啟動(dòng)容器,初始狀態(tài)會(huì)為 starting,在 HEALTHCHECK 指令檢查成功后變?yōu)?healthy,如果連續(xù)一定次數(shù)失敗,則會(huì)變?yōu)?unhealthy。 HEALTHCHECK 支持下列選項(xiàng): --interval=<間隔>:兩次健康檢查的間隔,默認(rèn)為 30 秒; --timeout=<時(shí)長(zhǎng)>:健康檢查命令運(yùn)行超時(shí)時(shí)間,如果超過(guò)這個(gè)時(shí)間,本次健康檢查就被視為失敗,默認(rèn) 30 秒; --retries=<次數(shù)>:當(dāng)連續(xù)失敗指定次數(shù)后,則將容器狀態(tài)視為 unhealthy,默認(rèn) 3 次。 和 CMD, ENTRYPOINT 一樣,HEALTHCHECK 只可以出現(xiàn)一次,如果寫(xiě)了多個(gè),只有最后一個(gè)生效。 在 HEALTHCHECK [選項(xiàng)] CMD 后面的命令,格式和 ENTRYPOINT 一樣,分為 shell 格式,和 exec 格式。 命令的返回值決定了該次健康檢查的成功與否:0:成功;1:失敗 舉例: 假設(shè)我們有個(gè)鏡像是個(gè)最簡(jiǎn)單的 Web 服務(wù),我們希望增加健康檢查來(lái)判斷其 Web 服務(wù)是否在正常工作,我們可以用 curl 來(lái)幫助判斷,其 Dockerfile 的 HEALTHCHECK 可以這么寫(xiě): FROM nginx RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/* HEALTHCHECK --interval=5s --timeout=3s \ CMD curl -fs http://localhost/ || exit 1 這里我們?cè)O(shè)置了每 5 秒檢查一次(這里為了試驗(yàn)所以間隔非常短,實(shí)際應(yīng)該相對(duì)較長(zhǎng)), 如果健康檢查命令超過(guò) 3 秒沒(méi)響應(yīng)就視為失敗,并且使用 curl -fs http://localhost/ || exit 1 作為健康檢查命令。 - ONBUILD 為他人做嫁衣裳 參見(jiàn):https://docs.kilvn.com/docker_practice/image/dockerfile/onbuild.html
保存鏡像
使用 docker save 命令可以將鏡像保存為歸檔文件。
保存鏡像為鏡像存儲(chǔ)文件的命令:
docker save mynginx | gzip > mynginx-latest.tar.gz
加載鏡像存儲(chǔ)文件到本地鏡像庫(kù)的命令:
docker load -i mynginx-latest.tar.gz
如果我們結(jié)合這兩個(gè)命令以及 ssh 甚至 pv 的話(huà),利用 Linux 強(qiáng)大的管道,我們可以寫(xiě)一個(gè)命令完成從一個(gè)機(jī)器將鏡像遷移到另一個(gè)機(jī)器,并且?guī)нM(jìn)度條的功能:
docker save <鏡像名> | bzip2 | pv | ssh <用戶(hù)名>@<主機(jī)名> 'cat | docker load'
導(dǎo)出容器快照到本地的命令:
docker export myubuntu > myubuntu.tar
導(dǎo)入容器快照到本地鏡像庫(kù)的命令:
cat myubuntu.tar | docker import - myubuntu:v1.0
鏡像存儲(chǔ)文件與容器快照文件的區(qū)別:
這兩者的區(qū)別在于容器快照文件將丟棄所有的歷史記錄和元數(shù)據(jù)信息(即僅保存容器當(dāng)時(shí)的快照狀態(tài)),而鏡像存儲(chǔ)文件將保存完整記錄,體積也要大。此外,從容器快照文件導(dǎo)入時(shí)可以重新指定標(biāo)簽等元數(shù)據(jù)信息。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
docker nginx 運(yùn)行后無(wú)法訪問(wèn)的問(wèn)題解決
這篇文章主要介紹了docker nginx 運(yùn)行后無(wú)法訪問(wèn)的問(wèn)題解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09docker安裝并運(yùn)行rabbitmq的實(shí)例代碼
在本篇文章里小編給大家整理了關(guān)于docker安裝并運(yùn)行rabbitmq的實(shí)例代碼以及相關(guān)知識(shí)點(diǎn),需要的朋友們學(xué)習(xí)下。2019-10-10Docker安裝wordpress并配置數(shù)據(jù)庫(kù)超詳細(xì)介紹版
安裝WordPress是一項(xiàng)常見(jiàn)的任務(wù),使用Docker可以使這個(gè)過(guò)程更加簡(jiǎn)單和可靠,下面這篇文章主要給大家介紹了關(guān)于Docker安裝wordpress并配置數(shù)據(jù)庫(kù)的相關(guān)資料,需要的朋友可以參考下2023-11-11Docker創(chuàng)建一個(gè)Nginx服務(wù)器的方法步驟
使用Dokcer可以很好的對(duì)鏡像進(jìn)行管理,創(chuàng)建和使用容器。這篇文章主要介紹了Docker創(chuàng)建一個(gè)Nginx服務(wù)器的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01docker啟動(dòng)springboot項(xiàng)目容器閃退的解決
本文主要介紹了docker啟動(dòng)springboot項(xiàng)目容器閃退,大部分原因是啟動(dòng)報(bào)錯(cuò),文中通過(guò)圖文示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07