docker入门与实践之【05-Dockfile指令】
為什么80%的碼農都做不了架構師?>>> ??
1.COPY 復制文件
格式:
COPY <源路徑>... <目標路徑> COPY ["<源路徑1>",... "<目標路徑>"]COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄復制到新的一層的鏡像內的 <目標路徑> 位置。比如:
COPY package.json /usr/src/app/<源路徑> 可以是多個,甚至可以是通配符,其通配符規則要滿足 Go 的 filepath.Match 規則
<目標路徑> 可以是容器內的絕對路徑,也可以是相對于工作目錄的相對路徑(工作目錄可以用 WORKDIR 指令來指定)。
2.ADD 更高級的復制文件
ADD使用格式與COPY一致,不同的是,如果 <源路徑> 為一個 tar 壓縮文件的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,ADD 指令將會自動解壓縮這個壓縮文件到 <目標路徑> 去。 比如官方鏡像 ubuntu 中:
FROM scratch ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz / ...COPY與ADD選用原則: 所有的文件復制應使用 COPY 指令,僅在需要自動解壓縮的場合使用 ADD。
3.CMD 容器啟動命令
CMD 指令的格式和 RUN 相似,也是兩種格式:
shell 格式:CMD <命令> exec 格式:CMD ["可執行文件", "參數1", "參數2"...] 參數列表格式:CMD ["參數1", "參數2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具體的參數。如果使用 shell 格式的話,實際的命令會被包裝為 sh -c 的參數的形式進行執行。比如:CMD echo $HOME在實際執行中,會將其變更為: CMD [ "sh", "-c", "echo $HOME" ]
對于容器而言,其啟動程序就是容器應用進程,容器就是為了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出。因此,docker里systemctl、service等命令不能執行。
4.ENTRYPOINT 入口點
ENTRYPOINT 的目的和 CMD 一樣,都是在指定容器啟動程序及參數。
當指定了 ENTRYPOINT 后,CMD 的含義就發生了改變,不再是直接的運行其命令,而是將 CMD 的內容作為參數傳給 ENTRYPOINT 指令,換句話說實際執行時,將變為:
<ENTRYPOINT> "<CMD>"示例:生成獲取當前公網 IP 的鏡像
FROM ubuntu:16.04 RUN apt-get update \&& apt-get install -y curl \&& rm -rf /var/lib/apt/lists/* ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]執行:
#無參數 docker run myip #有參數,ENTRYPOINT會把參數(-i)一起傳入,然后執行。 #換句話說,ENTRYPOINT能獲取命令執行的參數 docker run myip -i5.ENV設置環境變量
格式有兩種:
ENV <key> <value> ENV <key1>=<value1> <key2>=<value2>...這個指令很簡單,就是設置環境變量而已,無論是后面的其它指令,如 RUN,還是運行時的應用,都可以直接使用這里定義的環境變量。
ENV VERSION=1.0 DEBUG=on \NAME="Happy Feet"這個例子中演示了如何換行,以及對含有空格的值用雙引號括起來的辦法,這和 Shell 下的行為是一致的。
6.ARG 構建參數
格式:ARG <參數名>[=<默認值>]
Dockerfile 中的 ARG 指令是定義參數名稱,以及定義其默認值。該默認值可以在構建命令 docker build 中用 --build-arg <參數名>=<值> 來覆蓋。
7.VOLUME 定義匿名卷
格式為:
VOLUME ["<路徑1>", "<路徑2>"...] VOLUME <路徑>容器器運行時應該盡量保持容器存儲層不發生寫操作,對于數據庫類需要保存動態數據的應用,其數據庫文件應該保存于卷(volume)中.
為了防止運行時用戶忘記將動態文件所保存目錄掛載為卷,在 Dockerfile 中,我們可以事先指定某些目錄掛載為匿名卷,這樣在運行時如果用戶不指定掛載,其應用也可以正常運行,不會向容器存儲層寫入大量數據。
VOLUME /data這里的 /data 目錄就會在運行時自動掛載為匿名卷,任何向 /data 中寫入的信息都不會記錄進容器存儲層, 從而保證了容器存儲層的無狀態化。
當然,運行時可以覆蓋這個掛載設置。比如:
docker run -d -v mydata:/data xxxx在這行命令中,就使用了 mydata 這個命名卷掛載到了 /data 這個位置,替代了 Dockerfile 中定義的匿名卷的掛載配置。
8.EXPOSE 聲明端口
格式為 EXPOSE <端口1> [<端口2>...]。
EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時并不會因為這個聲明應用就會開啟這個端口的服務。
要將 EXPOSE 和在運行時使用 -p <宿主端口>:<容器端口>區分開來:
- -p,是映射宿主端口和容器端口,換句話說,就是將容器的對應端口服務公開給外界訪問,
- EXPOSE 僅僅是聲明容器打算使用什么端口而已,并不會自動在宿主進行端口映射。
9.WORKDIR 指定工作目錄
格式為 WORKDIR <工作目錄路徑>。
使用 WORKDIR 指令可以來指定工作目錄(或者稱為當前目錄),以后各層的當前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR 會幫你建立目錄。
一個錯誤的例子:
RUN cd /app RUN echo "hello" > world.txt將這個 Dockerfile 進行構建鏡像運行后,會發現找不到 /app/world.txt 文件,或者其內容不是 hello。原因其實很簡單:第一層 RUN cd /app 的執行僅僅是當前進程的工作目錄變更。而到第二層的時候,啟動的是一個全新的容器,跟第一層的容器更完全沒關系。
因此如果需要改變以后各層的工作目錄的位置,那么應該使用 WORKDIR指令。
10.USER 指定當前用戶
格式:USER <用戶名> USER 指令用來改變之后層的執行 RUN, CMD 以及 ENTRYPOINT 這類命令的身份。
示例:用redis用戶啟動redis
RUN groupadd -r redis && useradd -r -g redis redis USER redis RUN [ "redis-server" ]11.健康檢查
格式:
HEALTHCHECK [選項] CMD <命令>:設置檢查容器健康狀況的命令 支持下列選項:--interval=<間隔>:兩次健康檢查的間隔,默認為 30 秒;--timeout=<時長>:健康檢查命令運行超時時間,如果超過這個時間,本次健康檢查就被視為失敗,默認 30 秒;--retries=<次數>:當連續失敗指定次數后,則將容器狀態視為 unhealthy,默認 3 次。 HEALTHCHECK NONE:如果基礎鏡像有健康檢查指令,使用這行可以屏蔽掉其健康檢查指令為了幫助排障,健康檢查命令的輸出(包括 stdout 以及 stderr)都會被存儲于健康狀態里,可以用 docker inspect 來查看。
12.ONBUILD
格式:ONBUILD <其它指令>。
ONBUILD 是一個特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而這些指令,在當前鏡像構建時并不會被執行。只有當以當前鏡像為基礎鏡像,去構建下一級鏡像的時候才會被執行。
示例:
FROM node:slim RUN mkdir /app WORKDIR /app ONBUILD COPY ./package.json /app ONBUILD RUN [ "npm", "install" ] ONBUILD COPY . /app/ CMD [ "npm", "start" ]假設以上鏡像為my-node,后續基于此鏡像構建時,使用
FROM my-node假設此鏡像為node
好處:
ONBUILD 后面的命令,在構建my-node時并不會執行,只有在構建node時才會執行。如果路徑需要修改,或npm install需要添加參數時,只需要修改my-node的dockerfile,并重新構建node即可,而不用修改node的dockerfile。生產環境中,基于my-node構建的node可能不止不過,這樣避免了多次修改。
轉載于:https://my.oschina.net/funcy/blog/1826707
總結
以上是生活随笔為你收集整理的docker入门与实践之【05-Dockfile指令】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记本电脑如何设置纯色壁纸和屏保
- 下一篇: xv6解析-- 多处理器操作