在使用Dockerfile创建image时, 下面三条指令比较容易混淆。
RUN, CMD, ENTRYPOINT, Dockerfile中RUN,CMD和ENTRYPOINT都能够用于执行命令。

主要用途

  • RUN: 执行命令并创建新的Image Layer
  • CMD: 设置容器启动后默认执行的命令和参数
  • ENTRYPOINT: 设置容器启动时执行的命令

Shell 和 Exec 格式

我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,二者在使用上有细微的区别。

Shell 格式

  • 格式
    <instruction> <command>
  • 例子
RUN yum install -y vim  
CMD echo "Hello world"  
ENTRYPOINT echo "Hello world"

Exec 格式

  • 格式
    <instruction> ["executable", "param1", "param2", ...]
  • 例子
RUN ["yum", "install", "-y", "vim"]  
CMD ["/bin/echo", "hello docker"]  
ENTRYPOINT ["/bin/bash","-c", "echo hello docker"]

Shell 和 Exec 格式实践

Dockerfile1(Shell格式)

FROM centos
ENV name docker
ENTRYPOINT echo "hello $name"

构建并执行

docker build -f Dockerfile1 -t diycoder/centos-entrypoint-shell .
docker run -it diycoder/centos-entrypoint-shell

Dockerfile2(Exec格式)

FROM centos
ENV name docker
ENTRYPOINT ["/bin/bash","-c","echo hello $name"]

构建并执行

docker build -f Dockerfile1 -t diycoder/centos-entrypoint-exec .
docker run -it diycoder/centos-entrypoint-exec

CMD

  • 容器启动时默认执行的命令
  • 如果docker run 指定了其他命令,CMD 命令将被忽略
  • 如果定义了多个CMD命令,只有最后一个会执行

Dockerfile

FROM centos
ENV name Docker
CMD echo "hello $name"

构建并执行

docker build -f Dockerfile -t diycoder/centos-cmd-shell .
docker run -it diycoder/centos-cmd-shell /bin/bash

你会发现并没有打印hello docker,因为只有最后面的/bin/bash命令执行了

ENTRYPOINT

  • 让容器以应用程序或者以服务的形式执行
  • 不会被忽略,一定会执行
  • 最佳实践:写一个shell脚本作为entrypoint

写一个shell脚本作为entrypoint,启动一个数据库服务

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 27017
CMD ["mongod"]

再执行我们上面构建成功的image diycoder/centos-entrypoint-shell

docker run -it diycoder/centos-entrypoint-shell /bin/bash

你会发现打印hello docker不会被忽略,一定会执行

文章目录