點(diǎn)墨網(wǎng)站網(wǎng)站seo設(shè)置是什么
Docker:鏡像構(gòu)建 DockerFile
- 鏡像構(gòu)建
- docker build
- Dockerfile
- FROM
- COPY
- ENV
- WORKDIR
- ADD
- RUN
- CMD
- ENTRYPOINT
- USER
- ARG
- VOLUME
鏡像構(gòu)建
在Docker
官方提供的鏡像中,大部分都是基礎(chǔ)鏡像,他們只提供某個簡單的功能,如果想要一個功能更加豐富的鏡像,就需要自己制作。
比如說一個容器配置完畢后,想要讓容器便于傳輸,就可以封裝為一個鏡像。或者說希望讓自己的容器可以被別人看到,提交到倉庫上去,也要先變?yōu)殓R像。
在Docker
指令中,docker commit
可以使用快照的形式快速制作一個鏡像,它直接將一個容器導(dǎo)出為鏡像。除此之外,Docker
還提供了另一種方式構(gòu)建鏡像:編寫Dockerfile
。
Dockerfile
是一個文件,首字母大小寫任意,依據(jù)這個文件,就可以構(gòu)建出一個鏡像。在聯(lián)網(wǎng)的狀態(tài)下,只要有這個文件,就可以構(gòu)建出任意的鏡像。
docker build
docker bild
命令可以讀取Dockerfile
文件,并依據(jù)文件構(gòu)建鏡像。
語法:
docker build [option] path
參數(shù):
-f
:指定要使用的Dockerfile
路徑,默認(rèn)為當(dāng)前目錄下的Dockerfile
文件-t
:指定鏡像的名稱與標(biāo)簽
具體使用,在稍后Dockerfile
編寫時一起講解。
Dockerfile
Dockerfile
是一個文本文件,內(nèi)部包含多條指令,這些指令描述了如何構(gòu)建一個鏡像,如果構(gòu)建的鏡像不符合要求,還可以修改Dockerfile
反復(fù)制作鏡像。
Dockerfile
的不區(qū)分大小寫,后續(xù)的指令都以大寫形式。
Dockerfile
使用#
進(jìn)行注釋:
# 這是一行注釋
FROM
功能
:指定一個基礎(chǔ)鏡像
語法:
FROM image[:tag] [AS name]
指定鏡像時,可以使用as
對這個鏡像重命名,這樣可以在一個DockerFile
中進(jìn)行多級構(gòu)建,這個稍后會講解。
示例:
FROM ubuntu:22.04 AS ubt1
FROM ubuntu:22.04 AS ubt2
使用FROM
指定基礎(chǔ)鏡像時,如果基礎(chǔ)鏡像不存在,那么會自動拉取。
COPY
功能
:從宿主機(jī)或者其它鏡像中拷貝文件
語法:
COPY [option] src[,src] dst
COPY [option] "src"[,"src"] "dst"
將文件從src
拷貝到dst
,如果有多個文件,使用逗號分隔。如果在文件名中沒有出現(xiàn)空格,可以不用雙引號,如果文件名內(nèi)有空格,就需要使用"src"
和"dst"
。
選項:
--chown
:修改用戶和組--from
:可以從之前的鏡像中拷貝文件
拷貝宿主機(jī)文件:
FROM ubuntu:22.04
COPY ./test.txt /
以上代碼指定了一個ubuntu
的基礎(chǔ)鏡像,并拷貝一個宿主機(jī)文件test.txt
到根目錄下。
通過docker build
構(gòu)建鏡像:
選項-t
指定鏡像名為my-ubuntu:v1
,隨后開始執(zhí)行Dockerfile
內(nèi)部的指令,可以看到[2/2]COPY ./test.txt /
,這就是之前寫的COPY
指令。
實例化一個容器:
進(jìn)入容器后,根目錄就多出了test.txt
文件,這是構(gòu)建鏡像時拷貝進(jìn)去的。
除此之外,還可以進(jìn)行多級構(gòu)建,所謂的多級構(gòu)建,就是可能最終鏡像內(nèi)部的文件來自不同環(huán)境。那么先在某些鏡像環(huán)境內(nèi)部生成所需的文件,再把文件拷貝到最終的鏡像內(nèi)。
示例:
FROM nginx AS build-stageFROM ubuntu
COPY --from=build-stage /usr/share/nginx/html /
以上代碼,先創(chuàng)建了一個nginx
鏡像,重命名為build-stage
,隨后創(chuàng)建一個ubuntu
鏡像,在ubuntu
鏡像中,拷貝來自build-stage
的內(nèi)容,把目錄/usr/share/nginx/html
下的文件拷貝到自己的根目錄。
多級構(gòu)建時,最終的鏡像是最后一個FROM
指定的鏡像,前面指定的鏡像都是為了生成某些文件。
構(gòu)建鏡像:
最終生成一個my-ubuntu:v2
鏡像。
進(jìn)入鏡像:
進(jìn)入后,根目錄多出了index.html
,輸出后得到一個Welcome to nginx!
的網(wǎng)頁文件,這個文件就是在nginx
鏡像生成的,最后拷貝到了ubuntu
中。
ENV
功能
:設(shè)置環(huán)境變量
語法:
ENV name=value
環(huán)境變量不僅可以在容器內(nèi)部使用,還可以在后文通過${}
引用。
示例:
FROM nginx AS build-stageFROM ubuntu
ENV ngx_path=/usr/share/nginx/html
COPY --from=build-stage ${ngx_path} /
定義了一個環(huán)境變量ngx_path
,后續(xù)可以直接通過${ngx_path}
取出變量值。
WORKDIR
功能
:修改工作目錄
語法:
WORKDIR path
在構(gòu)建鏡像時,默認(rèn)的工作目錄都是/
根目錄,如果想要切換目錄,可以使用WORKDIR
。
示例:
FROM nginx
WORKDIR /usr/share/nginx/html
COPY ./test.txt ./
以上代碼,把宿主機(jī)的./test.txt
文件拷貝到容器的/usr/share/nginx/html
目錄下。
因為修改了WORKDIR
,所以./
就是/usr/share/nginx/html
。
ADD
功能
:將文件添加到鏡像中,可以解壓縮tar壓縮文件
語法:
ADD src dst
選項:
--chown
:修改文件所有者和組
此處的COPY
非常類似COPY
,用法也是一致的,功能都是拷貝文件。
但是ADD
比COPY
更強(qiáng)大,如果src
是壓縮包,那么會自動完成解壓縮。如果src
是一個url
,還會完成自動下載。
示例:
FROM ubuntu:22.04
ADD ./test.tar /
將test.tar
文件,通過ADD
命令,添加到鏡像的根目錄中。
輸出結(jié)果:
創(chuàng)建完鏡像再啟動后,根目錄下的內(nèi)容不是test.tar
而是test.txt
,說明文件被自動解壓了。
RUN
功能
:在構(gòu)建鏡像的過程中執(zhí)行命令
語法:
RUN command
RUN ["command", "arg1", "arg2",...]
在構(gòu)建鏡像的過程中,可以通過RUN
執(zhí)行指定命令,兩種語法中,他們的效果其實是不一樣的。
直接RUN command
,會以/bin/sh -c
來執(zhí)行指令,這可以提供一些bash
的特性,比如可以使用通配符? *
等進(jìn)行替換,以及運(yùn)行.sh
程序等。
但是使用[]
的形式執(zhí)行命令,不會具有bash
特性。
示例:
FROM ubuntu:22.04
COPY ./test* /
RUN mkdir dir1
RUN mkdir dir2
RUN cp ./test* dir1
RUN ["cp", "./test*", "dir2"]
以上代碼,把宿主機(jī)的./test*
拷貝到鏡像的根目錄,這是一個通配符,可以拷貝多個文件。
隨后通過RUN
執(zhí)行mkdir
命令,創(chuàng)建了兩個目錄。最后把從宿主機(jī)拷貝來的文件再拷貝到目錄里面,分別使用RUN command
和RUN []
兩種語法。
輸出結(jié)果:
在當(dāng)前目錄下,有test
、test.cpp
、test.java
、test.txt
四個文件,構(gòu)建鏡像時,可以看到RUN cp ./test* dir1
執(zhí)行成功了,但是RUN ["cp", "./test*", "dir2"]
失敗了。
因為RUN []
不支持bash
特性,導(dǎo)致無法匹配./test*
通配符,最后顯示找不到./test*
這個文件。
CMD
功能
:指定容器啟動時執(zhí)行的命令
語法:
CMD ["command","arg1","arg2",...]
CMD command arg1 arg2 ...
其中CMD command
和CMD []
的兩種形式,和之前的RUN
一樣,重點(diǎn)在于是否具有shell
特性。
示例:
FROM ubuntu:22.04
CMD ["echo", "hello world"]
這個鏡像,在啟動時會執(zhí)行CMD
內(nèi)的命令,輸出hello world
字符串。
原先ubuntu
的CMD
是bash
,也就是進(jìn)入命令行,由于輸出字符串的命令將其覆蓋了,所以無法直接進(jìn)入命令行。
除此之外,CMD
的命令還會進(jìn)行覆蓋,比如Dockerfile
內(nèi)部的多個CMD
,后面的會覆蓋前面的:
FROM ubuntu:22.04
CMD ["echo", "hello world"]
CMD ["echo", "hello C++"]
CMD ["echo", "hello Docker"]
最后該鏡像的命令是echo “hello Docker”
,前兩個被覆蓋了。
除此之外,在啟動容器時用戶也可以指定命令,這個命令也可以覆蓋CMD
:
ENTRYPOINT
功能
:指定容器啟動時執(zhí)行的命令
語法:
ENTRYPOINT ["command", "arg1", "arg2",...]
ENTRYPOINT command arg1 arg2 ...
ENTRYPOINT
和CMD
的功能是一樣的,但是語法特性略有差別。
在CMD
中,后面的CMD
會覆蓋前面的CMD
,啟動容器時的命令也會覆蓋CMD
。
在ENTRYPOINT
中,一個Dockerfile
只有最后一個ENTRYPOINT
生效,但是用戶輸入命令時,會變成ENTRYPOINT
的參數(shù),而不是覆蓋。
示例:
FROM ubuntu:22.04
ENTRYPOINT ["echo", "hello world"]
構(gòu)建成功后,在啟動容器時指定命令echo "hello Docker"
,輸出結(jié)果卻不是hello Docker
,而是:
hello world echo hello Docker
這是因為后面的echo "hello Docker"
都變成了ENTRYPOINT
內(nèi)部的指令的參數(shù),最后相當(dāng)于執(zhí)行:
echo "hello world" "echo" "hello Docker"
USER
功能
:指定運(yùn)行容器時的用戶或用戶ID
語法:
USER user[:group]
默認(rèn)情況下用戶為root
,可以通過USER
命令修改后文執(zhí)行指令時的用戶。
示例:
FROM ubuntu:22.04
RUN useradd new_usr
USER new_usr
WORKDIR /home/new_usr
以上代碼,通過RUN
創(chuàng)建了一個new_usr
用戶,并切換用戶為new_usr
。
輸出結(jié)果:
創(chuàng)建容器后,默認(rèn)用戶就是new_usr
,并且處于該用戶的家目錄中。
ARG
- 功能:定義構(gòu)建時的變量
語法:
ARG name[=value]
這個用于指定一些參數(shù),這個參數(shù)可以在Dockerfile
中通過${}
引用。
示例:
FROM ubuntu:22.04
ARG path=/home/new_usr
RUN useradd new_usr
USER new_usr
WORKDIR ${path}
將剛才的用戶家目錄定義在參數(shù)path
中,后續(xù)可以直接通過${path}
引用。
VOLUME
- 功能:創(chuàng)建一個匿名卷,并指定掛載點(diǎn)
語法:
VOLUME ["path"]
VOLUME path
由于鏡像實例化時,用戶所處的路徑是不確定的,就算確定了路徑,也不保證用戶存在這個路徑,所以在鏡像構(gòu)建階段不能創(chuàng)建綁定卷,只能創(chuàng)建匿名卷。
在VOLUME
的參數(shù)中,指定的path
就是要進(jìn)行綁定的匿名卷,可以持久化一些重要數(shù)據(jù),就算容器崩潰,用戶也有機(jī)會找回數(shù)據(jù)。