Dockerfile 的 RUN 和 CMD、ENTRYPOINT
在创建Dockerfile的时候,RUN和CMD都是很重要的命令。它们各自的作用分别如下:
RUN
RUN命令是创建 Docker 镜像(image)的步骤,RUN命令对Docker 容器 ( container)造成的改变是会被反映到创建的Docker镜像上的。一个Dockerfile中可以有许多个RUN命令。
CMD
CMD命令是当Docker镜像被启动后Docker容器将会默认执行的命令。一个Dockerfile仅仅最后一个CMD起作用。通过执行
docker run ????? other_command
启动镜像可以重载CMD命令。
Docker的CMD指令: The main purpose of a CMD is to provide defaults for an executing container.
CMD在容器运行的时候提供一些命令及参数,用法如下:
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
第一种用法:运行一个可执行的文件并提供参数。 第二种用法:为ENTRYPOINT指定参数。 第三种用法(shell form):是以”/bin/sh -c”的方法执行的命令。 如你指定:
CMD ["/bin/echo", "this is a echo test"]
build后运行(假设镜像名为ec):
docker run ec
就会输出: this is a echo test
是不是感觉很像开机启动项,你可以暂时这样理解。
注意点:
docker run命令如果指定了参数会把CMD里的参数覆盖: 这里说明一下,如:
docker run -it ubuntu /bin/bash
命令的参数是指 /bin/bash 而非 -it ,-it只是docker 的参数,而不是容器的参数。 同样是上面的ec镜像启动:
docker run ec /bin/echo hello
就不会输出:this is a echo test,因为CMD命令被”/bin/bash”覆盖了。
ENTRYPOINT
CMD
和
ENTRYPOINT
这两个指令用于在
Dockerfile
和
Docker Compose files
里配置容器的运行命令。这篇博文将会解释这两者之间的不同之处以及如何在Dockerfiles中更好的使用它们。
Entrypoint
Entrypoint
指令用于设定容器启动时第一个运行的命令及其参数
。
任何使用
docker run <image>
命令传入的参数都会附加在
entrypoint
指令之后,并且用此命令传入的参数会覆盖在Dockerfile中使用
CMD
指令设定的值。比如
docker run <image> bash
命令会将
bash
命令附加在
entrypoint
指令设定的值的后面。
Dockerfile ENTRYPOINT
Dockerfiles使用
entrypoint
全大写的形式来标识此指令。有如下几种不同的方式来定义它。
The exec syntax
使用
exec
形式时,你需要将命令和其参数以JSON数组的格式书写。这意味着你需要使用双引号,例如:
ENTRYPOINT ["executable", "param1", "param2"]
使用这种语法,Docker不会使用shell来运行。这意味着通常的shell处理过程不会发生。如果你需要在shell环境中运行,那么你可以这样做:
ENTRYPOINT [ "sh", "-c", "echo $HOME" ]
Using an entrypoint script
另外一种形式是使用一个脚本作为
ENTRYPOINT
的值。按照惯例来说,脚本名中通常包含
entrypoint
关键字。在这个脚本中,你可以做相关的配置,设置环境变量等,例如下面代码:
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["postgres"]
例如,下面就是
Postgres官方镜像
中的
ENTRYPOINT
脚本中的内容:
#!/bin/bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
exec gosu postgres "$@"
exec "$@"
Docker Compose entrypoint
在docker compose中使用entrypoint指令的方法与在Dockerfiles中一样,唯一不同的是在compose中
entrypoint
使用全小写的形式。
你也可以在
docker-compose.yml
文件中以列表的形式来定义它的值:
entrypoint:
- php
- zend_extension=/usr/local/lib/php/xdebug.so