指令 | 說明 | 備註 |
---|---|---|
FROM | 指定所建立鏡像的基礎鏡像 | 第一條指令必須爲 FROM 指令。格式爲 FROM <image> 或FROM <image>:<tag> 。 |
MAINTAINER | 指定維護者信息 | 格式爲 MAINTAINER <name> |
RUN | RUN 指令一般用於安裝應用和軟件包。 | 在鏡像中要執行的命令,格式爲 RUN <command> 或 RUN ["executable", "param1", "param2"] 。前者默認將在 shell 終端中運行命令,即 /bin/bash -c ;後者則使用 exec 執行。指定使用其它終端能夠經過第二種方式實現,例如 RUN [「/bin/bash」, 「-c」,」echo hello」] 。每條RUN指令將在當前鏡像的基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可使用換行。例如:RUN apt-get update \&& apt-get install -ylibsnappy-dev zliblg-dev libbz2-dev \&& rm -rf /var/cache/apt |
CMD | 指定啓動容器時默認執行的命令 | 支持三種格式:1. CMD["executable","param1","param2"] 使用 exec 執行,推薦方式;2. CMD command param1 param2 在 /bin/bash 中執行,提供給須要交互的應用;3. CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數; |
LABEL | 指定生成鏡像的元數據標籤信息 | |
EXPOSE | 聲明鏡像內服務所監聽的端口 | 指定容器要打開的端口 |
ENV | 指定環境變量 | 格式爲 ENV <key> <value> 。 指定一個環境變量,會被後續 RUN 指令使用,並在容器運行時保持。 |
ADD | 賦值指定的路徑下的內容到容器中的路徑下,能夠爲URL;若是爲tar文件,會自動解壓到路徑下 | 至關於 COPY ,可是比 COPY 功能更強大 |
COPY | 賦值本地主機的路徑下的內容到容器中的路徑下;通常狀況下推薦使用COPY 而不是ADD |
複製本地主機的 (爲 Dockerfile 所在目錄的相對路徑)到容器中的。用法同ADD,惟一的不一樣是不能指定遠程文件 URLS。 |
VOLUME | 建立數據掛載點 | 掛載目錄,格式爲VOLUME ["/data"] |
USER | 指定運行容器時的用戶名或UID | |
WORKDIR | 配置工做目錄 | 指定當前工做目錄,至關於 cd |
ARG | 指定鏡像內使用的參數(例如版本號信息等) | |
ONBUILD | 配置當前所建立的鏡像做爲其餘鏡像的基礎鏡像時,所執行的建立操做的命令 | |
STOPSIGNAL | 容器退出的信號 | |
HEALTHCHECK | 如何進行健康檢查 | |
CMD、ENTRYPOINT | 容器啓動時執行指令 | 配置容器啓動後執行的命令,而且不可被 docker run 提供的參數覆蓋,而CMD是能夠被覆蓋的。若是須要覆蓋,則可使用docker run --entrypoint 選項。每一個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最後一個生效。 |
每條RUN指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像,後續的RUN都在以前RUN提交後的鏡像爲基礎,鏡像是分層的,能夠經過一個鏡像的任何一個歷史提交點來建立,相似源碼的 版本控制 。php
exec 方式會被解析爲一個 JSON 數組,因此必須使用雙引號而不是單引號。exec 方式不會調用一個命令 shell,因此也就不會繼承相應的變量,如:html
RUN [ "echo", "$HOME" ]
這種方式是不會達到輸出 HOME 變量的,正確的方式應該是這樣的python
RUN [ "sh", "-c", "echo", "$HOME" ]
RUN產生的緩存在下一次構建的時候是不會失效的,會被重用,可使用--no-cache選項,即docker build --no-cache
,如此便不會緩存。
注意:apt-get update
和 apt-get install
被放在一個 RUN 指令中執行,這樣可以保證每次安裝的是最新的包。若是 apt-get install 在單獨的 RUN 中執行,則會使用 apt-get update 建立的鏡像層,而這一層多是好久之前緩存的。mysql
CMD "executable","param1","param2" CMD "param1","param2" CMD command param1 param2 (shell form)
CMD指定在 Dockerfile 中只能使用一次,若是有多個,則只有最後一個會生效。nginx
CMD的目的是爲了在啓動容器時提供一個默認的命令執行選項。若是用戶啓動容器時指定了運行的命令,則會覆蓋掉CMD指定的命令。c++
CMD會在啓動容器的時候執行,build 時不執行,而RUN只是在構建鏡像的時候執行,後續鏡像構建完成以後,啓動容器就與RUN無關了,這個初學者容易弄混這個概念,這裏簡單註解一下。
通常的,Dockerfile
分爲四部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時執行指令。’#’ 爲 Dockerfile 中的註釋。先看下面一個小例子:redis
# This my first nginx Dockerfile # Version 1.0 # Base images 基礎鏡像 FROM centos #MAINTAINER 維護者信息 MAINTAINER tianfeiyu #ENV 設置環境變量 ENV PATH /usr/local/nginx/sbin:$PATH #ADD 文件放在當前目錄下,拷過去會自動解壓 ADD nginx-1.8.0.tar.gz /usr/local/ ADD epel-release-latest-7.noarch.rpm /usr/local/ #RUN 執行如下命令 RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all RUN useradd -s /sbin/nologin -M www #WORKDIR 至關於cd WORKDIR /usr/local/nginx-1.8.0 RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install RUN echo "daemon off;" >> /etc/nginx.conf #EXPOSE 映射端口 EXPOSE 80 #CMD 運行如下命令 CMD ["nginx"]
vim Dockerfilesql
FROM alpine:latest MAINTAINER troy CMD echo "Hello Workd!"
docker build -t hello_world .
docker run hello_world
1.表示當前用戶使用的shell是/bin/bash,所謂的shell你能夠理解爲操做系統和人之間交互的平臺。例如windows系統的桌面環境就是一個shell。
bin目錄中基本上都是可執行的命令。docker
啓動容器並啓動bash(交互方式
):
$docker run -i -t <image_name/continar_id> /bin/bash
2.保存對容器的修改(commit) 當你對某一個容器作了修改以後(經過在容器中運行某一個命令),能夠把對容器的修改保存下來,這樣下次能夠從保存後的最新狀態運行該容器。
$docker commit ID new_image_name
固然若是在保存成新鏡像的時候想添加新的 dockerfile命令,好比,啓動進入新的目錄。
docker commit -c "WORKDIR /usr/bin" 07c5f9ed32b0 test-images
固然你也能夠在舊鏡像的基礎上寫一個新的dockerfile,用dockerfile生成新的鏡像。
Note: image至關於類,container至關於實例,不過能夠動態給實例安裝新軟件,而後把這個container用commit命令固化成一個image。
Dockerfile文件的每條指令生成鏡像的一層(注:一個鏡像不能超過127層
)。Dockerfile中的指令被一條條地執行。每一步都建立一個新的容器,在容器中執行指令並提交修改。當全部指令執行完畢後,返回最終的鏡像id。
前臺運行:
CMD 指令就是用於指定默認的容器主進程的啓動命令的。提到 CMD 就不得不提容器中應用在前臺執行和後臺執行的問題。這是初學者常出現的一個混淆。
Docker 不是虛擬機,容器中的應用都應該之前臺執行,而不是像虛擬機、物理機裏面那樣,用 upstart/systemd 去啓動後臺服務,容器內沒有後臺服務的概念。
一些初學者將 CMD 寫爲:
CMD service nginx start
而後發現容器執行後就當即退出了。甚至在容器內去使用 systemctl 命令結果卻發現根本執行不了。這就是由於沒有搞明白前臺、後臺的概念,沒有區分容器和虛擬機的差別,依舊在以傳統虛擬機的角度去理解容器。
對於容器而言,其啓動程序就是容器應用進程,容器就是爲了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出,其它輔助進程不是它須要關心的東西。
而使用 service nginx start 命令,則是但願 upstart 來之後臺守護進程形式啓動 nginx 服務。而剛纔說了 CMD service nginx start 會被理解爲
CMD [ "sh", "-c", "service nginx start"],
所以主進程其實是 sh。那麼當 service nginx start 命令結束後,sh 也就結束了,sh 做爲主進程退出了,天然就會令容器退出。
正確的作法是直接執行 nginx 可執行文件,而且要求之前臺形式運行。好比:
CMD ["nginx", "-g", "daemon off;"] ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]
爲何要這麼作呢?由於Docker容器僅在它的1號進程(PID爲1)運行時,會保持運行。若是1號進程退出了,Docker容器也就退出了。
咱們可用兩種方式指定 RUN、CMD 和 ENTRYPOINT 要運行的命令:Shell 格式和 Exec 格式,兩者在使用上有細微的區別。
Shell 格式
<instruction> <command>
例如:
RUN apt-get install python3 CMD echo "Hello world" ENTRYPOINT echo "Hello world"
當指令執行時,shell 格式底層會調用 /bin/sh -c <command> 。
例以下面的 Dockerfile 片斷:
ENV name Cloud Man ENTRYPOINT echo "Hello, $name"
執行 docker run <image> 將輸出:
Hello, Cloud Man
注意環境變量 name 已經被值 Cloud Man 替換。
下面來看 Exec 格式。
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
例如:
RUN ["apt-get", "install", "python3"] CMD ["/bin/echo", "Hello world"] ENTRYPOINT ["/bin/echo", "Hello world"]
當指令執行時,會直接調用 <command>,不會被 shell 解析。
例以下面的 Dockerfile 片斷:
ENV name Cloud Man ENTRYPOINT ["/bin/echo", "Hello, $name"]
運行容器將輸出:
Hello, $name
注意環境變量「name」沒有被替換。
若是但願使用環境變量,照以下修改
ENV name Cloud Man ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
運行容器將輸出:
Hello, Cloud Man
CMD 和 ENTRYPOINT 推薦使用 Exec 格式,由於指令可讀性更強,更容易理解。RUN 則兩種格式均可以。
一句話:docker-compose 是用來作docker 的多容器控制,是一個用來把 docker 自動化的東西。有了 docker-compose 你能夠把全部繁複的 docker 操做全都一條命令,自動化的完成。
docker-compose up -d nginx 構建建啓動nignx容器 docker-compose exec nginx bash 登陸到nginx容器中 docker-compose down 刪除全部nginx容器,鏡像 docker-compose ps 顯示全部容器 docker-compose restart nginx 從新啓動nginx容器 docker-compose run --no-deps --rm php-fpm php -v 在php-fpm中不啓動關聯容器,並容器執行php -v 執行完成後刪除容器 docker-compose build nginx 構建鏡像 。 docker-compose build --no-cache nginx 不帶緩存的構建。 docker-compose logs nginx 查看nginx的日誌 docker-compose logs -f nginx 查看nginx的實時日誌 docker-compose config -q 驗證(docker-compose.yml)文件配置,當配置正確時,不輸出任何內容,當文件配置錯誤,輸出錯誤信息。 docker-compose events --json nginx 以json的形式輸出nginx的docker日誌 docker-compose pause nginx 暫停nignx容器 docker-compose unpause nginx 恢復ningx容器 docker-compose rm nginx 刪除容器(刪除前必須關閉容器) docker-compose stop nginx 中止nignx容器 docker-compose start nginx 啓動nignx容器
在使用 Compose 時,最大的好處就是少打啓動命令,可是通常項目容器啓動的順序是有要求的,若是直接從上到下啓動容器,必然會由於容器依賴問題而啓動失敗。
例如在沒啓動數據庫容器的時候啓動了應用容器,這時候應用容器會由於找不到數據庫而退出,爲了不這種狀況咱們須要加入一個標籤,就是 depends_on,這個標籤解決了容器的依賴、啓動前後的問題。
例以下面容器會先啓動 redis 和 db 兩個服務,最後才啓動 web 服務:
version: '2' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
注意的是,默認狀況下使用 docker-compose up web 這樣的方式啓動 web 服務時,也會啓動 redis 和 db 兩個服務,由於在配置文件中定義了依賴關係。
還記得上面的depends_on吧,那個標籤解決的是啓動順序問題,這個標籤解決的是容器鏈接問題,與Docker client的--link同樣效果,會鏈接到其它服務中的容器。
格式以下:
links: - db - db:database - redis
使用的別名將會自動在服務容器中的/etc/hosts裏建立。例如:
172.12.2.186 db 172.12.2.186 database 172.12.2.187 redis
相應的環境變量也將被建立。
掛載一個目錄或者一個已存在的數據卷容器,能夠直接使用 [HOST:CONTAINER] 這樣的格式,或者使用 [HOST:CONTAINER:ro] 這樣的格式,後者對於容器來講,數據卷是隻讀的,這樣能夠有效保護宿主機的文件系統。
Compose的數據卷指定路徑能夠是相對路徑,使用 . 或者 .. 來指定相對目錄。
數據卷的格式能夠是下面多種形式:
volumes: // 只是指定一個路徑,Docker 會自動在建立一個數據卷(這個路徑是容器內部的)。 - /var/lib/mysql // 使用絕對路徑掛載數據卷 - /opt/data:/var/lib/mysql // 以 Compose 配置文件爲中心的相對路徑做爲數據卷掛載到容器。 - ./cache:/tmp/cache // 使用用戶的相對路徑(~/ 表示的目錄是 /home/<用戶目錄>/ 或者 /root/)。 - ~/configs:/etc/configs/:ro // 已經存在的命名的數據卷。 - datavolume:/var/lib/mysql
若是你不使用宿主機的路徑,你能夠指定一個volume_driver。
volume_driver: mydriver
從其它容器或者服務掛載數據卷,可選的參數是 :ro或者 :rw,前者表示容器只讀,後者表示容器對數據卷是可讀可寫的。默認狀況下是可讀可寫的。
volumes_from: - service_name - service_name:ro - container:container_name - container:container_name:rw
參考文檔:1. docker與dockerfile教程
2. Docker系列教程22-docker-compose.yml經常使用命令
3. Shell 和 Exec 格式