06-Dockerfile命令

Dockerfile命令

一、Dockerfile

Dockerfile由一行行命令語(yǔ)句組成。一般而言,Dockerfile可以分為四部分:基礎(chǔ)鏡像信息、維護(hù)信息、鏡像操作指令、啟動(dòng)時(shí)執(zhí)行指令

image.png
  • FROM指定基礎(chǔ)鏡像,最好挑一些 apline,slim 之類的基礎(chǔ)小鏡像
  • scratch鏡像是一個(gè)空鏡像,常用于多階段構(gòu)建

二、RUN

  • RUN指令在當(dāng)前鏡像層頂部的新層執(zhí)行任何命令,并提交結(jié)果,生成新的鏡像層
  • 生成的提交鏡像將用于Dockerfile的下一步。分層運(yùn)行RUN指令并生成提交符號(hào)Docker的核心概念,就想源代碼控制一樣
  • exec形式命令可以避免破壞 shell字符串,并使用不包含指定shell可執(zhí)行文件的基本鏡像運(yùn)行RUN命令??梢允褂?code>shell命令更改shell形式的默認(rèn)shell。在shell形式中,您可以使用(反斜杠)將一條RUN指令繼續(xù)到下一行
RUN <command>(shell形式,/bin/sh -c 的方式運(yùn)行,避免破壞 shell 字符串)
RUN ["executable", "param1", "param2"](exec 形式)

1、實(shí)例測(cè)試

  • Dockerfile 文件
FROM alpine
LABEL   maintainer=Raven xinshi=Wang  # 附近信息
ENV msg = "Hello World"  #定義 環(huán)境變量
RUN echo $msg
RUN ["echo", "$msg"]
RUN /bin/sh -c 'echo $msg'
RUN ["/bin/sh", "-c", "echo $msg"]
  • 使用Dockerfile文件構(gòu)建本地鏡像
# docker build -t 鏡像名稱
docker build -t test/myapp .
# 不使用緩存
docker build --no-cache -t raven/test3 .
  • 輸出
Sending build context to Docker daemon  77.82kB
Step 1/7 : FROM alpine
 ---> 14119a10abf4
Step 2/7 : LABEL   maintainer=Raven xinshi=Wang
 ---> Running in b2d7f6e38073
Removing intermediate container b2d7f6e38073
 ---> fae0897bf471
Step 3/7 : ENV msg = "Hello World"
 ---> Running in cd3ca7432b87
Removing intermediate container cd3ca7432b87
 ---> b33af3d9eac3
Step 4/7 : RUN echo $msg  ##使用  echo 模式可以取出環(huán)境變量中的值
 ---> Running in e18551f17104
= Hello World
Removing intermediate container e18551f17104
 ---> bc3abc7fe94c
Step 5/7 : RUN ["echo", "$msg"]  ##使用  exec 模式無(wú)法取出環(huán)境變量中的值
 ---> Running in 819fe9ffc7e5
$msg
Removing intermediate container 819fe9ffc7e5
 ---> 29d5a4c3032a
Step 6/7 : RUN /bin/sh -c 'echo $msg'  ##使用  sh 模式直接取出環(huán)境變量中的值
 ---> Running in fff5e64394c1
= Hello World
Removing intermediate container fff5e64394c1
 ---> 90405522a350
Step 7/7 : RUN ["/bin/sh", "-c", "echo $msg"]  ##使用  exec 模式直接取出環(huán)境
 ---> Running in 62e0db2c9f52
= Hello World
Removing intermediate container 62e0db2c9f52
 ---> bc78919ab073
Successfully built bc78919ab073
Successfully tagged raven/test3:latest

小結(jié)

  • 由于 [ ] 不是shell形式,所以不能輸出變量信息,而是輸出$msg。其他任何 /bin/sh -c 的形式都可以輸出變量信息
  • shell 是 /bin/sh -c <command> 的格式
  • exec 是 ["/bin/sh", "-c", command] 的格式 等價(jià)于 shell 方式
  • exec 默認(rèn)方式不會(huì)進(jìn)行變量替換

三、CMD 和 ENTRYPOINT

1、CMD 的三種寫法

  • CMD ["executable", "param1", "param2"],exec方式,推薦
  • CMD ["param1", "param2"] 為 ENTRYPOINT 提供默認(rèn)參數(shù)
  • CMD command param1 param2 shell 格式

2、ENTRYPOINT 的兩種寫法

  • ENTRYPOINT ["executable", "param1", "param2"] exec方式,推薦
  • ENTRYPOINT command param1 param2 shell格式

3、只能有一個(gè)CMD

  • Dockerfile中只能有一條 CMD 指令。如果列出多個(gè) CMD,則只有最后一個(gè)CMD才會(huì)生效
  • CMD 的主要目的是為執(zhí)行中的容器提供默認(rèn)值。這些默認(rèn)值可以包含可執(zhí)行文件,也可以省略可執(zhí)行文件,在這種情況下,還必須指定 ENTRYPOINT 指令

4、CMD 為 ENTRYPOINT 提供默認(rèn)參數(shù)

  • 如果使用 CMD 為 ENTRYPOINT 指令提供默認(rèn)參數(shù),則 CMD 和 ENTRYPOINT 指令均應(yīng)使用 JSON 數(shù)組格式指定

5、指令小結(jié)
image.png

四、ARG

ARG 指令定義一個(gè)變量,可以在構(gòu)建時(shí) docker build 通過使用 --build-arg <varname>=<value>標(biāo)志的命令將其傳遞給構(gòu)建器。如果用戶指定了未在Dockerfile中定義的構(gòu)建參數(shù),則構(gòu)建會(huì)輸出警告

ARG <name>[=<default value>]

1、Dockerfile 有效的ARG

FROM
Learn more about the "FROM" Dockerfile command.
 busybox
ARG user1
ARG buildno
# ...

警告:不建議在構(gòu)建時(shí)來傳遞密鑰,如GitHub密鑰、用戶憑證等docker history。

2、默認(rèn)值

一條 ARG指令可以選擇包含一個(gè)默認(rèn)值

FROM busybox
ARG user1=someuser
ARG buildno=1
# ...

3、實(shí)戰(zhàn)

FROM alpine

ARG msg="hello world"

RUN echo $msg

CMD echo $msg
CMD ["/bin/sh", "-c", "echo 12345; echo $msg"]

3.1、通過Dockerfile構(gòu)建鏡像,Dockerfile文件名稱為Dockerfile_ARG

docker build -t raven:test --no-cache -f Dockerfile_ARG .
  • -t 指定鏡像名稱及版本(raven:test)
  • --no-cache:不使用緩存來執(zhí)行構(gòu)建鏡像
  • -f:指定Dockerfile文件路徑
  • 1、指定路徑
docker build -t raven:test --no-cache -f /root/Dockerfiles/Dockerfile_ARG .
  • 2、如果Dockerfile文件是以 Dockerfile 為名
docker build --no-cache -t raven:test .
Dockerfile文件名為 Dockerfile 時(shí).png
  • 3、構(gòu)建輸出
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM alpine
 ---> 14119a10abf4
Step 2/5 : ARG msg="hello world"  #使用ARG定義變量并賦有默認(rèn)值
 ---> Running in 43d888792aa5
Removing intermediate container 43d888792aa5
 ---> bb7718e13663
Step 3/5 : RUN echo $msg  
 ---> Running in f35a8d4d13ca
hello world
Removing intermediate container f35a8d4d13ca
 ---> 7e3c81cb6d6c
Step 4/5 : CMD echo $msg
 ---> Running in ccc3e0ca8813
Removing intermediate container ccc3e0ca8813
 ---> a5395b20fb48
Step 5/5 : CMD ["/bin/sh", "-c", "echo 12345; echo $msg"]
 ---> Running in e74bbc97d2be
Removing intermediate container e74bbc97d2be
 ---> 1b456c19fbbb
Successfully built 1b456c19fbbb
Successfully tagged raven:v1
  • 3.1、使用ARG訂單變量,可以使用 RUN echo $msg 來輸出msg變量值
  • 3.2、CMD echo $msg 這種方式無(wú)法取出ARG訂單的變量
  • 4、通過Dockerfile文件構(gòu)建鏡像成功
    構(gòu)建鏡像成功.png
  • 5、運(yùn)行鏡像
docker run -it raven:v1
運(yùn)行鏡像.png
  • RUN命令:是在構(gòu)建鏡像時(shí)輸出信息

  • CMD命令:是在運(yùn)行鏡像時(shí)輸出信息

  • CMD命令無(wú)法輸出ARG變量的值

  • 6、在構(gòu)建鏡像是修改變量

docker build --no-cache --build-arg msg="Raven" -t raven:v1 -f Dockerfile_ARG .
image.png
  • ARG指令定義了一個(gè)變量,用戶可以在構(gòu)建時(shí)使用--build-arg=value,docker build 命令會(huì)將其傳遞給構(gòu)建器
  • --build-arg 指定參數(shù)會(huì)覆蓋 Dockerfile 中指定的同名參數(shù)
  • 如果用戶指定了 未在Dockerfile中定義的構(gòu)建參數(shù),則構(gòu)建會(huì)輸出警告
  • ARG只在構(gòu)建器有效,運(yùn)行期無(wú)效
  • ARG變量定義從Dockerfile中定義的行開始生效
  • 使用ENV指令定義的環(huán)境變量始終會(huì)覆蓋同名的ARG指令
  • 再次強(qiáng)調(diào)不建議使用構(gòu)建時(shí)變量來傳遞:GitHub密鑰、用戶憑證等機(jī)密。因?yàn)闃?gòu)建時(shí)變量使用docker history是可見的

五、ENV

1、在構(gòu)建階段中所有后續(xù)指令的環(huán)境中使用,并且在許多情況下也可以內(nèi)聯(lián)替換
2、引號(hào)和反斜杠可用于在值中包含空格
3、ENV 可以使用 key value的寫法,但是這種不推薦使用了,后續(xù)版本可能會(huì)刪除
4、docker run --env 可以修改這些值
5、容器運(yùn)行時(shí) ENV 值可以生效
6、ENV在 image 階段就會(huì)被解析并持久化(docker inspect image)

1、ARG定義的變量,ENV是否可以使用

  • Dockerfile
FROM alpine
ARG msg1="hello world"
ENV msg2 = $msg1
RUN echo $msg1
RUN echo $msg2
CMD ["/bin/bash", "-c", "echo msg1_$msg1; echo msg2_$msg2;"]
  • 生成鏡像
docker build --no-cache -t raven:re -f Dockerfile_ARG_ENV .
編譯輸出.png
  • 創(chuàng)建容器
docker run -it raven:re
運(yùn)行鏡像.png
  • 總結(jié)
    • ARG 定義的參數(shù)無(wú)法在運(yùn)行時(shí)輸出默認(rèn)值,但是可以在運(yùn)行時(shí)通過參數(shù)(-e)來修改 ARG 類型的參數(shù)值
    • ENV 定義的參數(shù)在構(gòu)建和運(yùn)行階段都可以使用

2、ARG定義的變量,ENV是否可以使用但是在構(gòu)建鏡像時(shí)修改參數(shù)

  • Dockerfile文件和上面的一樣
  • 構(gòu)建鏡像
docker build --no-cache --build-arg msg1="Raven" -t raven:re -f Dockerfile_ARG_ENV .
構(gòu)建鏡像輸出.png
  • 運(yùn)行鏡像
docker run -it raven:re
運(yùn)行鏡像輸出.png

3、ENV參數(shù) 賦值給另外一個(gè) ENV參數(shù)

  • Dockerfile
FROM alpine
ENV msg1="hello world"
ENV msg2 = $msg1
RUN echo $msg1
RUN echo $msg2
CMD ["/bin/sh", "-c", "echo msg1_$msg1; echo msg2_$msg2;"]
  • 構(gòu)建鏡像
docker build --no-cache -t raven:env -f Dockerfile_ENV .
構(gòu)建輸出信息.png
  • 運(yùn)行鏡像
docker run -it raven:env
運(yùn)行輸出信息.png

4、構(gòu)建時(shí)修改msg1值

  • Dockerfile文件與 上面 3 一樣
  • 構(gòu)建鏡像
docker build --no-cache --build-arg msg1="Raven" -t raven:env -f Dockerfile_ENV .
構(gòu)建鏡像輸出.png
  • 總結(jié)
    • 構(gòu)建時(shí)無(wú)法修改 ENV 類型參數(shù)
    • 從這里可以得出 ARG 類型參數(shù)應(yīng)用在構(gòu)建階段
  • 運(yùn)行鏡像
docker run -e msg1="Raven" -it raven:env
運(yùn)行時(shí)輸出.png

六、總結(jié)

1、在構(gòu)建鏡像階段,無(wú)法修改 ENV 類型參數(shù)

2、在運(yùn)行鏡像階段,當(dāng) ENV 參數(shù) msg2 = ENV參數(shù)類型msg1,修改msg1時(shí),并不會(huì)修改 msg2

image.png

3、在構(gòu)建階段 ENV 類型參數(shù)的值已經(jīng)確定,但是也可以在運(yùn)行時(shí)通過(-e)命令來修改

4、應(yīng)用選擇

4.1:ARG參數(shù):在運(yùn)行期間無(wú)法使用默認(rèn)值,但是可以通過 運(yùn)行命令傳參來使用,所以,不推薦在運(yùn)行期間使用ARG類型參數(shù)

4.2:ENV參數(shù):在運(yùn)行期間可以使用默認(rèn)值,也可以使用命令參數(shù)來傳值。但是在構(gòu)建期間無(wú)法通過構(gòu)建命令(--build-arg)來改變值,而是直接使用的默認(rèn)值。

七、ADD & COPY

ADD

ADD擁有自動(dòng)下載遠(yuǎn)程文件和解壓的功能

  • src 路徑必須在構(gòu)建的上下文中;不能使用../something /something這種方式,因?yàn)閐ocker構(gòu)建的第一步是將上下文目錄(和子目錄)發(fā)送到docker守護(hù)程序
  • 如果src是URL,并且dest不以斜杠結(jié)尾,則從URL下載文件并將其復(fù)制到dest
  • 如果dest以斜杠結(jié)尾,將自動(dòng)推斷出 URL 的名字(保留最后一部分),保存到dest
  • 如果src是目錄,則將復(fù)制目錄的整個(gè)內(nèi)容,包括文件系統(tǒng)元數(shù)據(jù)

7.1、遠(yuǎn)程文件(Redis)

1、目標(biāo)文件不帶斜杠

FROM alpine
#1、如果是遠(yuǎn)程文件,自動(dòng)下載
ADD http://download.redis.io/releases/redis-6.0.6.tar.gz /dest

RUN ls -l
image.png
  • 進(jìn)入容器
    image.png

2、目標(biāo)文件帶斜杠

  • Dockerfile
FROM alpine
#1、如果是遠(yuǎn)程文件,自動(dòng)下載
ADD http://download.redis.io/releases/redis-6.0.6.tar.gz /dest/

RUN ls -l
RUN cd /dest && ls -l
image.png

7.2、本地文件(宿主機(jī))

  • Dockerfile
FROM alpine
#1、如果是遠(yuǎn)程文件,自動(dòng)下載
ADD http://download.redis.io/releases/redis-6.0.6.tar.gz /dest/

#2、如果是本地壓縮包,自動(dòng)解壓
ADD *.tar.gz    /app/

RUN ls -l
RUN cd /dest && ls -l
RUN cd /app && ls -l
image.png

image.png

image.png

COPY

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
  • --chown 功能僅在用于構(gòu)建 Linux 容器的 Dockerfiles 上受支持,而在 Windows 容器上不起作用
  • COPY 指令從 src 復(fù)制新文件或目錄,并將它們添加到容器的文件系統(tǒng)中,
  • 可以指定多個(gè) src資源,但是文件和目錄的路徑將被解釋為相對(duì)于構(gòu)建上下文的源
  • 每個(gè) src都可以包含通配符,并且匹配將使用 Go 的 filepath.Match規(guī)則進(jìn)行

COPY命令

  • 拷貝當(dāng)前上下文,以home開始的所有資源
COPY hom* /mydir/
  • ? 匹配單個(gè)字符
COPY hom?.txt /mydir/
  • 目標(biāo)路徑如果設(shè)置為相對(duì)路徑,則相對(duì)與 WORKDIR 開始,把 "test.txt" 添加到<WORKDIR>/relativeDir/
COPY test.txt relativeDir/
  • 也可以使用絕對(duì)路徑,復(fù)制到容器指定位置
COPY test.txt /absoluteDir/
  • 所有復(fù)制的文件資源默認(rèn)都是使用 uid(0)/gid(0)的用戶,可以使用 --chown改變
COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/
  • 宿主文件的權(quán)限


    image.png
  • 使用COPY
  • Dockerfile
FROM alpine

COPY *.tar.gz    /app/
RUN ls -l
RUN cd /app && ls -l
image.png
  • 設(shè)置權(quán)限
  • Dockerfile
FROM alpine
#設(shè)置文件權(quán)限
COPY --chown=1000:1000 *.tar.gz    /app/
RUN ls -l
RUN cd /app && ls -l
image.png

八、WORKDIR 和 VOLUME

8.1、WORKDIR

  • WORKDIR 指令為Dockerfile中跟隨它的后續(xù)所有 RUN,CMD,ENTRYPOINTCOPYADD指令設(shè)置工作目錄。如果WORKDIR不存在,即使以后的Dockerfile指令中未使用它也將被創(chuàng)建。
  • WORKDIR指令可在Dockerfile中多次使用。如果提供了相對(duì)路徑,則它將相對(duì)于上一個(gè)WORKDIR指令的路徑
WORKDIR  /a
WORKDIR  b
WORKDIR  c
RUN pwd
#結(jié)果  /a/b/c
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
#結(jié)果  /path/$DIRNAME
  • 實(shí)戰(zhàn):如果需要修該Nginx顯示或者配置時(shí)
  • 1、首先需要進(jìn)入容器
docker exec -it 7ab174e8c7b2 /bin/bash
  • 2、尋找HTML資源
cd usr/share/nginx/html/
  • 這樣操作比較麻煩,可以使用WORKDIR來直接指定到常用的目錄(usr/share/nginx/html/),這樣進(jìn)入容器后就會(huì)自動(dòng)來到該目錄
  • Dockerfile
FROM nginx
#   進(jìn)入容器的指定目錄
WORKDIR /usr/share/nginx/html/
image.png

8.2、VOLUME

  • 把容器的某些文件夾映射到宿主機(jī)中
#  可以是JSON數(shù)組
VOLUME  ["/var/log/"]

#  可以直接寫
VOLUME  /var/log

#  可以空格分隔多個(gè)
VOLUME  /var/log  /var/db
  • 小結(jié)

    • 用VOLUME聲明了卷,那么以后對(duì)于卷內(nèi)容的修改會(huì)被丟棄,所以一定在 VOLUME 聲明之前修改內(nèi)容
  • 實(shí)戰(zhàn):修改宿主機(jī)中文件

上面使用WORKDIR來實(shí)現(xiàn)了一步定位到資源文件,但是還是需要進(jìn)入容器中,依然不是很方便,最好是可以在宿主機(jī)中修改容器中的資源文件

  • Dockerfile
FROM nginx
#   進(jìn)入容器的指定目錄
WORKDIR /usr/share/nginx/html/

#   掛載容器文件
VOLUME  ["/usr/share/nginx/html/"]
  • 進(jìn)入容器


    image.png
  • 查看容器

docker inspect 056c4dd90dd8
image.png
  • 宿主機(jī)中可以查詢到容器掛載出來的資源
    image.png
  • 默認(rèn)顯示
    image.png
  • 通過宿主機(jī)修改容器中資源
    image.png

九、USER

USER 指令設(shè)置運(yùn)行映像時(shí)要使用的用戶名(或UID,推薦使用UID)以及可選的用戶組(或GID,推薦使用GID),以及Dockerfile中USER后面所有RUN、CMD和ENTRYPOINT指令

USER <user>[:<group>]
USER <UID>[:<GID>]

十、EXPOSE

  • EXPOSE指令通知 Docker 容器在運(yùn)行時(shí)在指定的網(wǎng)絡(luò)端口上進(jìn)行監(jiān)聽。可以指定端口是監(jiān)聽TCP還是UDP,如果未指定協(xié)議,則默認(rèn)值為TCP
  • EXPOSE指令實(shí)際上不會(huì)發(fā)布端口。充當(dāng)構(gòu)建鏡像的人員與運(yùn)行容器的人員之間的一種文檔,即有關(guān)打算發(fā)布哪些端口的信息。要在運(yùn)行容器時(shí)實(shí)際發(fā)布端口,請(qǐng)?jiān)赿ocker run 上使用 -p 標(biāo)志發(fā)布并映射一個(gè)或多個(gè)端口,或使用 -P 標(biāo)志發(fā)布所有公開的端口并將其映射到高階端口
EXPOSE <port> [<port>/<protocol>...]
EXPOSE [80,443] 
EXPOSE 80/tcp 
EXPOSE 80/udp
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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