第一本docker書-讀書筆記 第四章

第四章 使用docker鏡像和倉庫

docker鏡像是由文件系統(tǒng)疊加而成。最底端是一個引導(dǎo)文件系統(tǒng),即bootfs,第二層是root文件系統(tǒng)rootfs。

一次同時加載多個文件系統(tǒng),但從外面看起來,只能看到一個文件系統(tǒng),聯(lián)合加載會把各層文件系統(tǒng)疊加起來,這樣最終的文件系統(tǒng)會包含所有底層的文件和目錄

docker將這樣的文件系統(tǒng)稱之為鏡像。

docker文件系統(tǒng)層

在同個鏡像中,docker用寫時復(fù)制來保證鏡像都是只讀的,并且以后永遠(yuǎn)不會變化。

docker images利用這個命令可以看到我們的鏡像。

image-20201117081433465

鏡像保存在/var/lib/docker目錄下。其中containers目錄是所有的容器。

這個鏡像是我們在公有registry中拉取下來的,地址是這個。dockerhub

docker pull可以拉取鏡像倉庫中的鏡像。

通常會下載最新的鏡像,可以在鏡像名后面增加標(biāo)簽來指定要下載的鏡像內(nèi)容。

image-20201117082944110

在拉取鏡像的時候指定標(biāo)簽是個好習(xí)慣,從而能讓你知道你要拉取的鏡像的內(nèi)容。

區(qū)分倉庫名,docker中的倉庫有兩種,用戶倉庫和頂層倉庫。

用戶倉庫是docker用戶自己創(chuàng)建的,可能存在風(fēng)險,命名由兩部分組成,用戶名/倉庫名。

頂層倉庫是有docker管理人管理的,是安全的,命名只有倉庫名部分,如Ubuntu。

查找鏡像

docker search可以在docker倉庫中查找鏡像,查找列表可以看到倉庫名,鏡像描述,用戶評價,是否官方,自動構(gòu)建

image-20201119075814258

構(gòu)建鏡像

最好使用docker build命令和Dockerfile文件。雖然也可以使用docker commit,但是不推薦。

docker commit

docker可以將當(dāng)前狀態(tài)的容器,提交成為一個鏡像,這樣就不用了每次都需要重新執(zhí)行相關(guān)的命令成為一個你想要的鏡像了。而且他是基于鏡像差異去提交的,所以該次commit會很小。

Dockerfile

利用Dockerfile可以構(gòu)建一個屬于你自己的鏡像,而且鏡像構(gòu)建過程是透明的。

比如新建一個目錄,在該目錄下創(chuàng)建Dockerfile文件。內(nèi)容是:

FROM ubuntu
MAINTAINER huangzelin "838120089@qq.com" #標(biāo)識該鏡像的所有者和聯(lián)系方式
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'this is huangzelin' > /usr/share/nginx/html/index.html
EXPOSE 80 #暴露該鏡像的80端口

在當(dāng)前目錄下執(zhí)行

docker build -t="static_web"

等構(gòu)建完畢就能看到剛剛構(gòu)建的鏡像了。

image-20201124075545217

除了指定目錄以外,還可以通過指定git地址來獲取Dockerfile,這樣在多服務(wù)器的情況下,也能統(tǒng)一一份Dockerfile了。

運行該鏡像。

root@DESKTOP-3JK8RKR:/data/docker_test/static_web# docker run -t -i static_web /bin/bash
root@038c56a4542d:/# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

可以看到該鏡像已經(jīng)安裝了nginx。

docker在構(gòu)建的過程中會將每一步的構(gòu)建結(jié)果都提交為鏡像,所以每一步都會有緩存,如果你在第四步發(fā)生了變動,那么第一到三步是不用重新構(gòu)建的。所以最基礎(chǔ)的構(gòu)建應(yīng)該放在前面 如果不想要使用緩存,可以在build的時候指定

docker build --no-cache -t="static_web" .

利用docker history可以查看鏡像的構(gòu)建過程。

root@DESKTOP-3JK8RKR:/data/docker_test/static_web# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
static_web          latest              6c9a53fca598        19 minutes ago      158MB
<none>              <none>              9eed8ce3f990        5 days ago          158MB
ubuntu              latest              d70eaf7277ea        4 weeks ago         72.9MB
hello-world         latest              bf756fb1ae65        10 months ago       13.3kB
root@DESKTOP-3JK8RKR:/data/docker_test/static_web# docker history 6c9a53fca598
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
6c9a53fca598        19 minutes ago      /bin/sh -c #(nop)  EXPOSE 80                    0B
a2283161422c        19 minutes ago      /bin/sh -c echo 'this is huangzelin' > /usr/…   19B
631da22a6ab8        19 minutes ago      /bin/sh -c apt-get install -y nginx             59.2MB
136d23864f2b        19 minutes ago      /bin/sh -c apt-get update                       26.1MB
78e58f68d48e        20 minutes ago      /bin/sh -c #(nop)  MAINTAINER huangzelin "83…   0B
d70eaf7277ea        4 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           4 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B
<missing>           4 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     0B
<missing>           4 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   811B
<missing>           4 weeks ago         /bin/sh -c #(nop) ADD file:435d9776fdd3a1834…   72.9MB

讓nginx鏡像能真正跑起來。

 docker run -d -p 80 --name test_nginx static_web nginx -g "daemon off;"
ec4077f4ae9259d63b2b6fbfb541a70129d4b0c0deaeae26d6f6f60c2463623b

-d:是讓nginx以分離的方式跑起來。

nginx -g "daemon off;":這是在指定容器中要運行的命令。

-p:是暴露容器的端口給宿主機,這里沒有指定綁定到宿主機的那些端口,就會隨機選擇一個4915365535一個比較大的端口號來映射到容器的80端口中。

可以通過docker ps來查看端口分配情況。

root@DESKTOP-3JK8RKR:/data/docker_test/static_web# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
ec4077f4ae92        static_web          "nginx -g 'daemon of…"   11 minutes ago      Up 11 minutes       0.0.0.0:32768->80/tcp   test_nginx

可以看到32768指向了容器的80端口。

打開本地的32768頁面。

image-20201124082730264

還可以通過docker port查看端口映射情況。

root@DESKTOP-3JK8RKR:/data/docker_test/static_web# docker port test_nginx 80
0.0.0.0:32768

但是這種隨機的端口實用性不大,我們更多的是指定特定的端口去映射。

docker run -d -p 80:80 --name test_nginx static_web nginx -g "daemon off;"
ec4077f4ae9259d63b2b6fbfb541a70129d4b0c0deaeae26d6f6f60c2463623b

這樣我們就指定了本地的80端口映射到容器的80端口了,但是需要注意,一個端口只能被映射一次。

還可以

docker run -d -p 127.0.0.1:80:80 --name test_nginx static_web nginx -g "daemon off;"
ec4077f4ae9259d63b2b6fbfb541a70129d4b0c0deaeae26d6f6f60c2463623b

來指定綁定的ip。

docker還有個-P選項,這個選項會暴露容器中EXPOSE指定的端口,不過不建議,因為多個端口提供服務(wù)違反了一個docker一個容器只運行一個服務(wù)的建議。

Dockerfile指令

CMD

cmd用于指定一個容器啟動時要運行的命令,這有點兒類似RUN指令,只是RUN指令是指定鏡像被構(gòu)建時要運行的命令,而CMD是指定容器被啟動時要運行的命令。這和docker run在后面指定容器要運行的命令非常相似。

當(dāng)然也可以為要運行的命令指定參數(shù),如

CMD ["/bin/bash", "-l"]

需要注意的是,我們在docker run的時候,顯式給他啟動命令,會覆蓋Dockerfile里面的CMD指令。

如果在Dockerfile中指定了多條CMD命令,也只有最后一條會生效。

ENTRYPOINT

ENTRYPOINT和CMD又有點類似,剛剛提到,docker run會覆蓋掉CMD指令,那我們有時候并不想覆蓋指令,而只是想指定啟動參數(shù)呢。

那么ENTRYPOINT就能做到。

ENTRYPOINT ["/usr/sbin/nginx"]
docker run -d -p 127.0.0.1:80:80 --name test_nginx static_web -g "daemon off;"

那么我們的容器啟動命令就是

 ["/usr/sbin/nginx", -g, "daemon off"]

和CMD組合能構(gòu)成一個默認(rèn)啟動的Dockerfile。

ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]

WORKDIR

WORKDIR 會指定一個工作目錄,進(jìn)入到該目錄內(nèi),ENTRYPOINT,RUN或CMD指定的程序?qū)谶@個目錄下執(zhí)行。

比如:

WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT ["rackup"]

相當(dāng)于我們cd到/opt/webapp/db目錄下,然后執(zhí)行安裝bundle,之后再cd到/opt/webapp目錄下,等待啟動命令的啟動。

我們可以在docker run的時候指定-w在運行時覆蓋工作目錄。

docker run -ti -w /var/log ubuntu pwd
/var/log

可以看到目錄切到了/var/log下面。

ENV

ENV用來設(shè)置鏡像的環(huán)境變量。

ENV RVM_PATH /home/rvm/

加入環(huán)境變量之后可以直接使用

WORKDIR $RVM_PATH

可以 docker run的時候用-e標(biāo)志來傳遞環(huán)境變量。

docker run -ti -e "WEB_PORT=8080" ubuntu env

USER

USER指令用來指定該鏡像會以什么樣的用戶去運行。

默認(rèn)是root。

也可以在docker run的時候指定-u去修改用戶。

VOLUME

VOLUME指令用來向基于鏡像創(chuàng)建的容器添加卷。這個卷可以在一個或多個容器中共享數(shù)據(jù)和持久化。

卷會一直存在直到?jīng)]有任何容器再使用它。

卷功能讓我們可以講數(shù)據(jù),數(shù)據(jù)庫或者其他東西添加到鏡像中,而不是將這些東西提交到鏡像中。

ADD

ADD指令用來將構(gòu)建環(huán)境的文件或目錄復(fù)制到鏡像中。

ADD software.lic /opt/application/software.lic

指向源文件的位置參數(shù)還可以是一個URL。

docker判斷文件還是目錄是看后面有沒有以/結(jié)尾。

而且如果傳輸?shù)脑次募莟ar包,docker還會幫我們解壓縮。

ADD lastest.tar.gz /var/www/wordpress/

這條命令會把lastest.tar.gz解壓縮到/var/www/wordpress/目錄下。不過url的行為可能不一樣。

PS:ADD會使構(gòu)建緩存失效。

COPY

COPY和ADD類似,但是COPY不能從URL中獲取數(shù)據(jù),也不會自動解壓縮。

ONBUILD

ONBUILD指令能為鏡像添加觸發(fā)器。當(dāng)一個鏡像被用作其他鏡像的基礎(chǔ)鏡像時,觸發(fā)器會被執(zhí)行??梢哉J(rèn)為這些指令是在FORM之后指定的。

ONBUILD ADD ./app/src
ONBUILD RUN cd /app/src && make

ONBUILD指令可以通過在鏡像上運行docker inspect命令來查看。

ONBUILD只會被繼承一次,所以只會被子鏡像中執(zhí)行,而不會在孫子鏡像中執(zhí)行。

刪除鏡像

如果你不需要一個鏡像了,你可以用

docker rmi image_name

進(jìn)行刪除。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容