摘要:例如,以下命令將啟動一個默認監控端口的命令行參數將被追加到以形式的所有元素后面,并且覆蓋使用指定的所有元素。這種形式將使用處理代替環境變量,并且將忽略任何或者命令的命令行參數。下表顯示了對不同組合執行的命令
Docker可以從Dockerfile中讀取指令來自動構建鏡像。Dockerfile是一個文本文件,它包含了用戶可以在命令調用以制作鏡像的命令。用戶可以使用docker build連續執行一些命令行指令來開啟一個自動構建。
此文檔描述了在Dockerfile中可以使用的命令。當你讀完這個文檔時,請參閱Dockfile最佳實踐獲取進階指南。
使用docker build命令從Dockerfile和上下文構建鏡像。構建上下文是特定路徑或URL的文件集合。該路徑是你本地文件系統的一個目錄。URL是一個Git倉庫地址。
上下文會被遞歸處理。所以,路徑包含的任意字母路合URL包含的倉庫及其子模塊也會被處理。一下實例展示了一個使用當前目錄作為上下文的build命令:
$ docker build . Sending build context to Docker daemon 6.51 MB ...
構建由Docker daemon執行, 而非cli。構建進程的第一件事是(遞歸的)發送上下文給守護進程(daemon)。在大多數情況下,最好以一個空目錄下作為上下文發送給守護進程并且保持Dockerfile在該目錄下。只為構建Dockerfile增加必須的文件。
CMDCMD指令有三種用法:
CMD ["executable","param1","param2"] (exec形式, 這是首選形式)
CMD ["param1","param2"] (作為ENTRYPOINT默認參數)
CMD command param1 param2 (shell 形式)
一個Dockerfile里只能有一個CMD指令。如果你有多個CMD指令,只有 最后一個 生效。
CMD的主要目的是為運行容器提供默認值。 默認值可以包含一個可執行文件,也忽略可執行文件,在此情況下必須同時指定ENTRYPOINT指令。
注: 如果CMD用于為ENTRYPOINT指令提供默認參數,CMD和ENTRYPOINT都應該使用json數組格式。注: exec形式傳遞json數組,意味著你必須使用雙引號(")而不是單引號(")引用字符
注: 與shell形式不同,exec形式不會像,那樣調用命令行shell。這意味著沒有通常的shell處理。例如,CMD [ "echo", "$HOME" ]將不會對$HOME做變量替換。如果你想使用shell處理可使用shell形式或直接執行一個shell,例如:["sh", "-c", "echo $HOME"]。當使用exec形式并且直接執行一個shell,在這種情況下shell形式,執行環境變量擴展的是shell,而不是docker。
當使用shell或exec格式時,CMD指令設置鏡像運行時執行的命令。
如果你使用CMD的shell形式,
FROM ubuntu CMD echo "This is a test." | wc -
如果你想不使用shell運行你的
FROM ubuntu CMD ["/usr/bin/wc","--help"]
如果你系統容器每次運行相同的可執行文件,你應該考慮ENTRYPOINT和CMD結合使用。
如果用戶為docker run指定了參數,那么他們將覆蓋CMD中指定的默認參數。
注:不要混淆RUN和CMD。RUN實際上運行命令并提交結果;CMD在構建時什么都不執行,只是指定鏡像將要執行的命令。EXPOSE
EXPOSE[ ...]
EXPOSE指令通知Docker容器運行時監聽指定的網絡端口。EXPOSE不會使容器端口對宿主機可訪問。要那么做,你必須使用-p標記來發布一系列端口或者-P標記發布所有暴露端口。你可以暴露一個端口號并可以使用另一個端口對外發布。
要在宿主機系統上設置端口重定向,使用-P標記。Docker網絡功能支持網絡內創建網絡而不需要暴露端口,詳細信息請查看功能概述。
ADDADD有兩種形式:
ADD
ADD ["
ADD指令
ENTRYPOINTENTRYPOINT有2中形式:
ENTRYPOINT ["executable", "param1", "param2"] (exec 形式, 首選)
ENTRYPOINT command param1 param2 (shell 形式)
ENTRYPOINT允許你配置一個將作為可執行程序運行的容器。
例如,以下命令將啟動一個nginx默認監控80端口:
docker run -i -t --rm -p 80:80 nginx
docker run
shell形式阻止任何CMD或者run的命令行參數被使用,但是有個弊端,你的ENTRYPOINT將被作為/bin/sh -c的一個子命令啟動,不能傳遞信號。這意味著可執行程序不是容器ID為1的進程 - 并且不會接受Unix信號 - 所以你的可執行程序不會接受來自docker stop
只有Dockerfile最后一個ENTRYPOINT指令會生效。
VOLUMEVOLUME ["/data"]
VOLUME指令創建一個具有指定名稱的掛載點并且將其標記作為從宿主機或者其他容器外部掛載卷。值可以是一個JSON數組,VOLUME ["/var/log"],或者有多參數的純字符串,比如:VOLUME /var/log或者VOLUME /var/log /var/db。更多Docker客戶端的掛載指令信息/例子,移步文檔通過卷共享目錄。
docker run命令使用基礎鏡像內指定位置存在的任意數據初始化新創建的卷。比如,認為以下Dockerfile片段:
FROM ubuntu RUN mkdir /myvol RUN echo "hello world" > /myvol/greeting VOLUME /myvol
這個Dockerfile的結果是致使docker run會創建一個新的掛載點/myvol并且拷貝gretting文件到新創建的卷。
指定volumes的注意事項關于Dockerfile中的volumes,請注意以下事項。
基于Windows容器的Volumes: 當使用基于Windows的容器,容器內volume的目標位置必須是以下之一:
一個不存在的或者空目錄
C盤以外的驅動器:
從Dockerfile內更改卷: 如果任何構建步驟在volume聲明之后修改了數據,這些修改將會被丟棄。
JSON 格式: 列表將會被作為一個JSON數組解析。你必須使用雙引號(")而不是單引號(")將單詞包起來。
主機目錄在容器運行時聲明: 主機目錄(掛載點)本質上是與主機相關的。這是為了保證鏡像的可移植性。因為一個指定的主機目錄不能保證在所有的主機上可用。因此,你不能在Dockerfile內掛載一個主機目錄。VOLUME指令不支持指定一個主機目錄參數。你必須在容器創建或運行時指定掛載點。
Exec形式ENTRYPOINT實例你可以使用ENTRYPOINT的exec形式設置相當穩定的默認命令和參數,然后使用CMD任意一種形式設置額外的更可能被修改的其他附加默認值。
FROM ubuntu ENTRYPOINT ["top", "-b"] CMD ["-c"]
但你運行該容器時,你僅僅可以看到top進程:
$ docker run -it --rm --name test top -H top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05 Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
要進一步檢查結果,可以使用docker exec:
$ docker exec -it test ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
并且你可以使用docker stop test請求top優雅的退出。
以下Dockerfile展示了使用ENTRYPOINT在前端運行Apache(例如,PID為1)。
FROM debian:stable RUN apt-get update && apt-get install -y --force-yes apache2 EXPOSE 80 443 VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"] ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
如果你需要為單個可執行程序寫一個啟動腳本,你可以使用exec和gosu命令來確保最終執行程序可以收到Unix信號。
#!/usr/bin/env bash set -e if [ "$1" = "postgres" ]; then chown -R postgres "$PGDATA" if [ -z "$(ls -A "$PGDATA")" ]; then gosu postgres initdb fi exec gosu postgres "$@" fi exec "$@"
最后,如果你需要在退出時做一些額外的清理(或者與其他容器通信),或者配合執行多個可執行文件,你可能需要確保ENTRYPOINT腳本接受Unix信號,傳遞他們并做更多工作:
#!/bin/sh # Note: I"ve written this using sh so it works in the busybox container too # USE the trap if you need to also do manual cleanup after the service is stopped, # or need to start multiple services in the one container trap "echo TRAPed signal" HUP INT QUIT TERM # start service in background here /usr/sbin/apachectl start echo "[hit enter key to exit] or run "docker stop"" read # stop service and clean up here echo "stopping apache" /usr/sbin/apachectl stop echo "exited $0"
如果你使用docker run -it -p 80:80 --name test apache運行該鏡像,然后你可以使用docker exec檢查容器進程,或者docker top,并且可以通過腳本停止Apache。
$ docker exec -it test ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2 root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux $ docker top test PID USER COMMAND 10035 root {run.sh} /bin/sh /run.sh 123 cmd cmd2 10054 root /usr/sbin/apache2 -k start 10055 33 /usr/sbin/apache2 -k start 10056 33 /usr/sbin/apache2 -k start $ /usr/bin/time docker stop test test real 0m 0.27s user 0m 0.03s sys 0m 0.03s
注:你可以使用--entrypoint覆蓋ENTRYPOINT配置,但是這只會將二進制設置為exec(sh -c不會被使用)。Shell形式ENTRYPOINT實例注:exec形式被解析為JSON數組,意味著你必須使用雙引號(")包裹單詞而不是單引號(")。
注:不像shell形式,exec形式并不會調用shell命令。這意味著不會做普通的shell處理。例如,ENTRIPOIN ["echo", "$HOME"]將不能對$HOME做變量置換。如果你既想shell處理又想使用shell形式或直接執行一shell,例如:ENTRYPOINT ["sh", "-c", "echo $HOME"]。當使用exec形式和直接執行shell時,在shell形式這種情況下,是shell做的環境變量擴展,而不是docker。
你可以為ENTRYPOINT指定一個純文本的字符串,它會以/bin/sh -c的形式運行。這種形式將使用shell處理shell代替shell環境變量,并且將忽略任何CMD或者docker run命令的命令行參數。為了確保docker stop能夠正常發出信號給任何長時間運行的ENTRYPOINT可執行文件,您需要記住使用exec啟動它:
FROM ubuntu ENTRYPOINT exec top -b
當你啟動鏡像,你會看到PID為1的進程:
$ docker run -it --rm --name test top Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq Load average: 0.08 0.03 0.05 2/98 6 PID PPID USER STAT VSZ %VSZ %CPU COMMAND 1 0 root R 3164 0% 0% top -b
它將會在執行docker stop時徹底退出:
$ /usr/bin/time docker stop test test real 0m 0.20s user 0m 0.02s sys 0m 0.04s
如果你忘記了在ENTRYPOINT開頭增加exec:
FROM ubuntu ENTRYPOINT top -b CMD --ignored-param1
你可以啟動它(為了下一步給它指定名稱):
$ docker run -it --name test top --ignored-param2 Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq Load average: 0.01 0.02 0.05 2/101 7 PID PPID USER STAT VSZ %VSZ %CPU COMMAND 1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2 7 1 root R 3164 0% 0% top -b
你可以看到top的輸出,ENTRYPOINT指定的不是PID 1。
如果你接下來執行docker stop test,容器不會被徹底退出 - 超時以后top命令會被發送一個SIGKILL。
$ docker exec -it test ps aux PID USER COMMAND 1 root /bin/sh -c top -b cmd cmd2 7 root top -b 8 root ps aux $ /usr/bin/time docker stop test test real 0m 10.19s user 0m 0.04s sys 0m 0.03s理解CMD和ENTRYPOINT如何交互
CMD和ENTRYPOINT指令都定義了當啟動一個容器時執行什么命令。描述他們如何一起工作的規則很少。
Dockerfile至少應該指定一個CMD或ENTRYPOINT命令。
當容器做一個可執行程序時,ENTRYPOINT應該被定義。
CMD應該被用作一種給ENTRYPOINT定義默認參數的方式,或在容器中執行ad-hoc命令的方式。
當運行容器時是用了交互參數時,CMD將被會被覆蓋。
下表顯示了對不同ENTRYPOINT / CMD組合執行的命令:
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28083.html
摘要:比如和指令,鏡像中的文件內容被檢查并且為每個文件計算校驗和。這些文件的最終修改和訪問時間將不被考慮到校驗和內。在查找緩存期間,校驗和將被用于與已存在的鏡像校驗和進行對比。 Docker 可以從 Dockerfile 中讀取指令自動構建鏡像,Dockerfile是一個包含構建指定鏡像所有命令的文本文件。Docker堅持使用特定的格式并且使用特定的命令。你可以在 Dockerfile參考 ...
摘要:在前一篇文章學習與和應用一初步認識中,我們初步介紹了解決了什么問題,容器化技術與傳統的虛擬化方式的區別,以及簡要介紹了的幾大核心概念鏡像容器和倉庫。針對上述問題,提供了的,通過使用指令配置的方式來創建鏡像。 在前一篇文章 Docker學習與和應用(一)_初步認識中,我們初步介紹了Docker解決了什么問題,Docker容器化技術與傳統的虛擬化方式的區別,以及簡要介紹了Docker的幾大...
摘要:更多的內容可以參考深入理解一命令參考的用法咧實例的寫法已經講述完畢,這兒有一個示例的指定系統我抄的他的創建私鑰修復登錄,否則登陸后的用戶會被秒退。 本系列教程翻譯自 Flux7 Docker Tutorial Series,系列共有九篇,本文譯自第三篇 Part 3: Automation is the Word Using DockerFile。 該系列所有文章將參考其他學...
摘要:更多的內容可以參考深入理解一命令參考的用法咧實例的寫法已經講述完畢,這兒有一個示例的指定系統我抄的他的創建私鑰修復登錄,否則登陸后的用戶會被秒退。 本系列教程翻譯自 Flux7 Docker Tutorial Series,系列共有九篇,本文譯自第三篇 Part 3: Automation is the Word Using DockerFile。 該系列所有文章將參考其他學...
閱讀 1123·2023-04-26 00:12
閱讀 3249·2021-11-17 09:33
閱讀 1061·2021-09-04 16:45
閱讀 1186·2021-09-02 15:40
閱讀 2146·2019-08-30 15:56
閱讀 2951·2019-08-30 15:53
閱讀 3548·2019-08-30 11:23
閱讀 1932·2019-08-29 13:54