Dockerfile不等同于Shell脚本

初学者常常以为Dockerfile等同于Shell脚本

举个例子

  1. RUN cd /app
  2. RUN echo "hello" > world.txt

如果将这个Dockerfile进行构建镜像运行之后,会发现找不到/app/world.txt文件,或者这个文件的内容不是hello

  • 在Shell中,连续两行是在同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令
  • 而在Dockerfile中,这两行RUN命令的执行环境根本不同,是两个完全不同的容器。这就是对Dockerfile构建分层存储概念不了解所导致的错误

RUN不能分开写

关于RUN需要注意的是

  1. RUN命令尽量写少点!可以使用&&简化指令
    1. Dockerfile中的每一个指令都会建立一层,RUN也一样。所以要避免镜像的臃肿
    2. Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层
  2. 每一层构建的最后一定要清理掉无关文件

例如:编译、安装 redis 可执行文件

  • 没有必要建立很多层,只用一层就可以了
  • 最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件 ```dockerfile FROM debian:stretch

RUN set -x; buildDeps=’gcc libc6-dev make wget’ \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz “http://download.redis.io/releases/redis-5.0.3.tar.gz“ \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis —strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y —auto-remove $buildDeps ```