Dockerfile詳解
利用Dockerfile文件,可以構建docker的image鏡像
命令使用
通過-f參數指定Dockerfile路徑,進行構建image
docker build -f /path/to/a/Dockerfile .
或者,Dockerfile在當前目錄,使用
docker build .
使用-t參數,指定image名稱
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
Dockerfile說明
內容大小寫不敏感
指令是按順序執行
第一條指令是FROM
'#'后面跟的是說明內容
FROM 指令
關於FROM命令說明
必須指定且需要在Dockerfile其他指令的前面。后續的指令都依賴於該指令指定的image。FROM指令指定的基礎image可以是官方遠程倉庫中的,也可以位於本地倉庫。
1.FROM必需是除了注釋語句外的第一行
2.可以用多個FROM命令,用來創建多個image
3.tag or digest是可選的,如果不輸入,則默認使用latest
4.如果找不到tag或者digest則返回錯誤
命令格式如下:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
ENV環境變量
構建指令,在image中設置一個環境變量。
設置了后,后續的RUN命令都可以使用,container啟動后,可以通過docker inspect查看這個環境變量,也可以通過在docker run --env key=value時設置或修改環境變量。
ENV <key> <value>
ENV <key>=<value> ...
eg:示例
ENV foo /bar
WORKDIR ${foo} # WORKDIR /bar
ADD . $foo # ADD . /bar
COPY \$foo /quux # COPY $foo /quux
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
以上命令def = hello, ghi=bye
$變量可被以下命令使用
ADD
COPY
ENV
EXPOSE
LABEL
USER
WORKDIR
VOLUME
STOPSIGNAL
.dockerignore 文件
作用:排除某些文件或文件夾不包含在構建的image中
內容格式如下
*/temp* #For example, the plain file /somedir/temporary.txt is excluded, as is the directory /somedir/temp.
*/*/temp* #For example, /somedir/subdir/temporary.txt is excluded.
temp? #For example, /tempa and /tempb are excluded.
以下是除了README.md外,其他所有的md文件都不包含進去
*.md
!README.md
以下所有的README文件將被包含,其他md文件不包含,其中第二行無效,因為第三行會匹配第二行
*.md
README-secret.md
!README*.md
MAINTAINER 指令
維護人員信息說明,用於將image的制作者相關的信息寫入到image中。當我們對該image執行docker inspect命令時,輸出中有相應的字段記錄該信息。
MAINTAINER <name>
RUN 指令
RUN命令用於執行一些命令,如安裝軟件等
RUN可以運行任何被基礎image支持的命令。如基礎image選擇了ubuntu,那么軟件管理部分只能使用ubuntu的命令。
RUN命令的結果會被緩存,供下一個指令使用
如果不需要緩存,使用docker build --no-cache=true
有2種RUN格式
shell模式
RUN <command> (shell form, the command is run in a shell - /bin/sh -c)
使用用\換行
RUN /bin/bash -c 'source $HOME/.bashrc ;\
echo $HOME'
等價於
RUN /bin/bash -c 'source $HOME/.bashrc ; echo $HOME'
exec模式
使用的是JSON array格式,必需使用雙引號
Note: To use a different shell, other than ‘/bin/sh’, use the exec form passing in the desired shell. For example, RUN ["/bin/bash", "-c", "echo hello"]
RUN ["executable", "param1", "param2"] (exec form)
RUN ["/bin/bash", "-c", "echo hello"]
RUN [ "sh", "-c", "echo", "$HOME" ]
(命令及參數使用雙引號)
CMD 指令
只能有一個CMD指令,如果有多個,最后一個將被生效
When used in the shell or exec formats, the CMD instruction sets the command to be executed when running the image.
CMD使用shell,或者exec方式,則運行容器的時候將運行命令
The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well.
一個CMD的主要目的是為執行容器提供默認值。這些設置可以包括一個可執行文件,也可以不執行,在這種情況下,您必須指定一個入口指令以及。
CMD指令有3種使用方式
exec方式,優先
CMD ["executable","param1","param2"]
如果不想用shell方式執行命令,必需采用 exec json arrayy方式(命令及參數使用雙引號),如:
CMD ["/usr/bin/wc","--help"]
為ENTRYPOINT傳遞參數
當Dockerfile指定了ENTRYPOINT,那么使用下面的格式:
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
ENTRYPOINT指定的是一個可執行的腳本或者程序的路徑,該指定的腳本或者程序將會以param1和param2作為參數執行。所以如果CMD指令使用上面的形式,那么Dockerfile中必須要有配套的ENTRYPOINT。
shell方式
CMD command param1 param2 (shell form)
使用以下CMD命令,將以/bin/sh -c 方式運行命令
CMD echo "This is a test." | wc -
如果使用docker run 指定了參數,將重寫CMD的默認值
注意:不要混淆RUN 命令和 CMD
RUN 會運行命令,並提交結果在構建IMAGE時
CMD不會在構建時執行,在啟動IMAGE時執行
LABEL 指令
指定image標簽,如版本,說明等
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
如果有多個標簽,推薦使用單一的LABEL來說明
LABEL multi.label1="value1" multi.label2="value2" other="value3"
或者
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
使用docker inspect查看label
EXPOSE 指令
設置指令,該指令會將容器中的端口映射成宿主機器中的某個端口。當你需要訪問容器的時候,可以不是用容器的IP地址而是使用宿主機器的IP地址和映射后的端口。要完成整個操作需要兩個步驟,首先在Dockerfile使用EXPOSE設置需要映射的容器端口,然后在運行容器的時候指定-p選項加上EXPOSE設置的端口,這樣EXPOSE設置的端口號會被隨機映射成宿主機器中的一個端口號。也可以指定需要映射到宿主機器的那個端口,這時要確保宿主機器上的端口號沒有被使用。EXPOSE指令可以一次設置多個端口號,相應的運行容器的時候,可以配套的多次使用-p選項。
EXPOSE <port> [<port>...]
映射一個端口
EXPOSE port1
相應的運行容器使用的命令
docker run -p port1 image
映射多個端口
EXPOSE port1 port2 port3
相應的運行容器使用的命令
docker run -p port1 -p port2 -p port3 image
還可以指定需要映射到宿主機器上的某個端口號
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
對於一個運行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID來查看該端口號在宿主機器上的映射端口。
ADD指令
構建指令,所有拷貝到container中的文件和文件夾權限為0755,uid和gid為0;如果是一個目錄,那么會將該目錄下的所有文件添加到container中,不包括目錄;如果文件是可識別的壓縮格式,則docker會幫忙解壓縮(注意壓縮格式);如果
COPY指令
指令說明:從src拷備文件或目錄到容器中的dest路徑
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
注意事項說明:
1.可以使用多個COPY指令
2.每個< SRC >可以包含通配符
COPY hom* /mydir/ # adds all files starting with "hom"
COPY hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
3.src> 是相對被構建的源目錄的相對路徑,可以是文件或目錄的路徑,也可以是一個遠程的文件url;
不能使用如../路徑
COPY ../something /something
4.dest 必需是容器中的絕對路徑,或者相對於WORKDIR的路徑,如
COPY test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
COPY test /absoluteDir/ # adds "test" to /absoluteDir/
5.如果是一個目錄,那么會將該目錄下的所有文件添加到container中,不包括目錄本身
6.如果
7.如果
8.如果src使用了通配符,則dest必需是以/結尾的目錄
ENTRYPOINT指令
指令格式:
ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
ENTRYPOINT command param1 param2 (shell form)
指令說明:設置指令,指定容器啟動時執行的命令,可以多次設置,但是只有最后一個有效。
該指令的使用分為兩種情況,一種是獨自使用,另一種和CMD指令配合使用。
當獨自使用時,如果你還使用了CMD命令且CMD是一個完整的可執行的命令,那么CMD指令和ENTRYPOINT會互相覆蓋只有最后一個CMD或者ENTRYPOINT有效。
# CMD指令將不會被執行,只有ENTRYPOINT指令被執行
CMD echo “Hello, World!”
ENTRYPOINT ls -l
另一種用法和CMD指令配合使用來指定ENTRYPOINT的默認參數,這時CMD指令不是一個完整的可執行命令,僅僅是參數部分;ENTRYPOINT指令只能使用JSON方式指定執行命令,而不能指定參數。
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
Command line arguments to docker run will be appended after all elements in an exec form ENTRYPOINT, and will override all elements specified using CMD. This allows arguments to be passed to the entry point, i.e., docker run
-d will pass the -d argument to the entry point. You can override the ENTRYPOINT instruction using the docker run --entrypoint flag.
docker run image命令的參數,將會追加到ENTRYPOINT命令以exec方式的參數之后,並且會覆蓋所有CMD指令的參數,可以使用--entrypoint參數覆蓋ENTRYPOINT命令的參數
The shell form prevents any CMD or run command line arguments from being used, but has the disadvantage that your ENTRYPOINT will be started as a subcommand of /bin/sh -c, which does not pass signals. This means that the executable will not be the container’s PID 1 - and will not receive Unix signals - so your executable will not receive a SIGTERM from docker stop
如果使用shell方式執行,則所有的CMD命令,還有以docker run 方式傳遞的參數無效,這樣有一個缺點,ENTRYPOINT將會以子命令/bin/sh -c方式啟動,無法接收Unix信號,意味着無法使用docker stop <container>
方式停止容器
Understand how CMD and ENTRYPOINT interact
Both CMD and ENTRYPOINT instructions define what command gets executed when running a container. There are few rules that describe their co-operation.
Dockerfile should specify at least one of CMD or ENTRYPOINT commands.
ENTRYPOINT should be defined when using the container as an executable.
CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container.
CMD will be overridden when running the container with alternative arguments.
The table below shows what command is executed for different ENTRYPOINT / CMD combinations:
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_cmd p1_cmd exec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”, “p2_cmd”] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd 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 /bin/sh -c exec_cmd p1_cmd exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd
VOLUME指令
指令格式
VOLUME ["/data"]
VOLUME /var/log
VOLUME /var/log /var/db
設置指令,使容器中的一個目錄具有持久化存儲數據的功能,該目錄可以被容器本身使用,也可以共享給其他容器使用。我們知道容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉后,所有的更改都會丟失。當容器中的應用有持久化數據的需求時可以在Dockerfile中使用該指令。
USER指令
指令格式:
USER daemon
USER UID
指令說明
設置指令,設置啟動容器的用戶,默認是root用戶。
設置容器以什么用戶運行,RUN,CMD,ENTRYPOINT相關命令會以該用戶運行
The USER instruction sets the user name or UID to use when running the image and for any RUN, CMD and ENTRYPOINT instructions that follow it in the Dockerfile.
WORKDIR指令
指令格式
WORKDIR /path/to/workdir
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if its not used in any subsequent Dockerfile instruction.
It can be used multiple times in the one Dockerfile. If a relative path is provided, it will be relative to the path of the previous WORKDIR instruction. For example:
設置指令,可以多次切換(相當於cd命令),對RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在會創建
可以設置多次,每次設置相對於上次路徑,如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最終pwd結果是/a/b/c
WORKDIR指令也可以使用環境變量的值
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
最終pwd結果是/path/$DIRNAME
ARG指令
設置變量,在docker build創建IMAGE時用--build-arg參數,指定一些參數,如
FROM busybox
USER ${user:-some_user}
ARG user
USER $user
使用如下指令后,user=what_user,默認user=some_user,
$ docker build --build-arg user=what_user Dockerfile