RUN和CMD和ENTRYPOINT

前言

Docker有三种命令执行方式

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

RUN

RUN命令一般用来安装一些依赖, 删除缓存等操作.
但是每一次RUN都会产生一层Image Layer, 所以需要尽可能的少用RUN, 尽量一行代码搞定.

1
2
3
4
RUN yum update && yum install -y vim
RUN apt-get update && apt-get install -y \
vim && rm -rf /var/lib/apt/lists/*
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

CMD

CMDcontainer启动时默认执行的命令.
等价于docker run -it [image] /bin/bash.
并且会被覆盖.

  1. 多个CMD只会执行最后一个.
  2. 外部命令会覆盖内部的CMD.

利用外部命令会覆盖内部CMD的特性, 我们可以从外部传入参数.

1
2
3
4
FROM centos
ENTRYPOINT ["/usr/bin/curl"]
# 默认查看curl版本号
CMD ["--version"]

然后执行以下命令

1
2
docker build -t centos-curl .
docker run -it centos-curl --head www.baidu.com

等价于在container中执行/usr/bin/curl --head www.baidu.com.

ENTRYPOINT

ENTRYPOINTcontainer以应用程序或者服务的形式运行.
CMD相比, ENTRYPOINT不会被忽略, 一定会执行.
最佳实践就是写一个shell作为ENTRYPOINT

1
2
COPY docker-entrypoint.sh /usr/local/bin
ENTRYPOINT ["docker-entrypoint.sh"]

参数格式 SHELL 和 EXEC

另外, RUNCMDENTRYPOINT的参数规则有两种, SHELLEXEC.
ENTRYPOINT为例, 这两种ENTRYPOINT的写法是等价的.

1
2
3
4
5
FROM centos
ENV name Ahao
# ENTRYPOINT echo "hello ${Ahao}"
ENTRYPOINT ["/bin/bash", "-c", "echo hello ${Ahao}"]
# ENRTYPOINT [COMMAND] 等价于 ENTRYPOINT ["/bin/bash", "-c", "[COMMAND]"]

总结

  1. 使用RUN安装软件依赖, 并记得删除缓存.
  2. 构建服务时使用Exec格式的ENTRYPOINT.
  3. 默认启动命令使用CMD.