Dockerfile
Docker 可以通過 Dockerfile 的內容來自動構建鏡像。Dockerfile 是一個包含創建鏡像所有命令的文本文件,通過docker build命令可以根據 Dockerfile 的內容構建鏡像,在介紹如何構建之前先介紹下 Dockerfile 的基本語法結構。
Dockerfile 有以下指令選項:
FROM
MAINTAINER
RUN
CMD
EXPOSE
ENV
ADD
COPY
ENTRYPOINT
VOLUME
USER
WORKDIR
ONBUILD
- FROM
用法:
FROM <image>
或者
FROM <image>
FROM指定構建鏡像的基礎源鏡像,如果本地沒有指定的鏡像,則會自動從 Docker 的公共庫 pull 鏡像下來。
FROM必須是 Dockerfile 中非注釋行的第一個指令,即一個 Dockerfile 從FROM語句開始。
FROM可以在一個 Dockerfile 中出現多次,如果有需求在一個 Dockerfile 中創建多個鏡像。
如果FROM語句沒有指定鏡像標簽,則默認使用latest標簽。
- MAINTAINER
用法:
MAINTAINER <name>
指定創建鏡像的用戶
RUN 有兩種使用方式:
RUN
RUN "executable", "param1", "param2"
每條RUN指令將在當前鏡像基礎上執行指定命令,并提交為新的鏡像,后續的RUN都在之前RUN提交后的鏡像為基礎,鏡像是分層的,可以通過一個鏡像的任何一個歷史提交點來創建,類似源碼的版本控制。
exec 方式會被解析為一個 JSON 數組,所以必須使用雙引號而不是單引號。exec 方式不會調用一個命令 shell,所以也就不會繼承相應的變量,如:
RUN [ "echo", "$HOME" ]
這種方式是不會達到輸出 HOME 變量的,正確的方式應該是這樣的
RUN [ "sh", "-c", "echo", "$HOME" ]
RUN產生的緩存在下一次構建的時候是不會失效的,會被重用,可以使用--no-cache選項,即docker build --no-cache,如此便不會緩存。
- CMD
CMD有三種使用方式:
CMD "executable","param1","param2"
CMD "param1","param2"
CMD command param1 param2 (shell form)
CMD指定在 Dockerfile 中只能使用一次,如果有多個,則只有最后一個會生效。
CMD的目的是為了在啟動容器時提供一個默認的命令執行選項。如果用戶啟動容器時指定了運行的命令,則會覆蓋掉CMD指定的命令。
另外注意不要弄混以下的概念:
CMD會在啟動容器的時候執行,build時不執行,而RUN只是在構建鏡像的時候執行,后續鏡像構建完成之后,啟動容器就與RUN無關了
EXPOSE
EXPOSE <port> [<port>...]
告訴 Docker 服務端容器對外映射的本地端口,需要在 docker run 的時候使用-p或者-P選項生效。ENV
ENV <key> <value>
# 只能設置一個變量
ENV <key>=<value>
... # 允許一次設置多個變量
指定一個環節變量,會被后續RUN指令使用,并在容器運行時保留。
例子:
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
等同于
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
- ADD
ADD <src>... <dest>
ADD復制本地主機文件、目錄或者遠程文件 URLS 從 并且添加到容器指定路徑中 。
支持通過GO的正則模糊匹配,具體規則可參見https://golang.org/pkg/path/filepath/#Match
ADD hom* /mydir/ # adds all files starting with "hom"
ADD hom?.txt /mydir/ # ? is replaced with any single character
路徑必須是絕對路徑,如果 不存在,會自動創建對應目錄
路徑必須是 Dockerfile 所在路徑的相對路徑
如果是一個目錄,只會復制目錄下的內容,而目錄本身則不會被復制
- COPY
COPY <src>... <dest>
COPY復制新文件或者目錄從 并且添加到容器指定路徑中 。用法同ADD,唯一的不同是不能指定遠程文件 URLS。
- ENTRYPOINT
ENTRYPOINT "executable", "param1", "param2"
ENTRYPOINT command param1 param2 (shell form)
配置容器啟動后執行的命令,并且不可被 docker run 提供的參數覆蓋,而CMD是可以被覆蓋的。如果需要覆蓋,則可以使用docker run --entrypoint選項。
每個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最后一個生效。
Exec form ENTRYPOINT 例子
通過ENTRYPOINT使用 exec form 方式設置穩定的默認命令和選項,而使用CMD添加默認之外經常被改動的選項。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
通過 Dockerfile 使用ENTRYPOINT展示前臺運行 Apache 服務
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"]
Shell form ENTRYPOINT 例子
這種方式會在/bin/sh -c中執行,會忽略任何CMD或者docker run命令行選項,為了確保docker stop能夠停止長時間運行ENTRYPOINT的容器,確保執行的時候使用exec選項。
FROM ubuntu
ENTRYPOINT exec top -b
如果在ENTRYPOINT忘記使用exec選項,則可以使用CMD補上:
FROM ubuntu
ENTRYPOINT top -b
CMD --ignored-param1 # --ignored-param2 ... --ignored-param3 ... 依此類推
VOLUME
VOLUME ["/data"]
創建一個可以從本地主機或其他容器掛載的掛載點,后續具體介紹。USER
USER daemon
指定運行容器時的用戶名或 UID,后續的RUN、CMD、ENTRYPOINT也會使用指定用戶。
- WORKDIR
WORKDIR /path/to/workdir
為后續的RUN、CMD、ENTRYPOINT指令配置工作目錄。可以使用多個WORKDIR指令,后續命令如果參數是相對路徑,則會基于之前命令指定的路徑。
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最終路徑是/a/b/c。
WORKDIR指令可以在ENV設置變量之后調用環境變量:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
最終路徑則為 /path/$DIRNAME。
- ONBUILD
ONBUILD [INSTRUCTION]
配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
例如,Dockerfile 使用如下的內容創建了鏡像 image-A:
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
如果基于 image-A 創建新的鏡像時,新的 Dockerfile 中使用 FROM image-A 指定基礎鏡像時,會自動執行 ONBUILD 指令內容,等價于在后面添加了兩條指令。
# Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的鏡像,推薦在標簽中注明,例如 ruby:1.9-onbuild。
- Dockerfile 示例
# Nginx
#
# VERSION 0.0.1
FROM ubuntu
MAINTAINER Victor Vieux <victor@docker.com>
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
# Firefox over VNC
#
# VERSION 0.3
FROM ubuntu
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc", "-forever", "-usepw", "-create"]
# Multiple images example
#
# VERSION 0.1
FROM ubuntu
RUN echo foo > bar
# Will output something like ===> 907ad6c2736f
FROM ubuntu
RUN echo moo > oink
# Will output something like ===> 695d7793cbe4
# You?ll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
# /oink.
- docker build
$ docker build --help
Usage: docker build [OPTIONS] PATH | URL | -
Build a new image from the source code at PATH
--force-rm=false Always remove intermediate containers, even after unsuccessful builds # 移除過渡容器,即使構建失敗
--no-cache=false Do not use cache when building the image # 不實用 cache
-q, --quiet=false Suppress the verbose output generated by the containers
--rm=true Remove intermediate containers after a successful build # 構建成功后移除過渡層容器
-t, --tag="" Repository name (and optionally a tag) to be applied to the resulting image in case of success
Dockerfile的注意點
- cd在Dockerfile中無效,必須使用WORKDIR
- ADD 上傳壓縮包后,不需要解壓(war除外,war需要使用jar命令解壓),也不需要刪除壓縮包,會自動解壓然后刪除原壓縮包