Computer Programming
Monday, July 10, 2023
如何 Debug Dockerfile 文件
在执行 docker build 时一旦 Dockerfile 中存在错误,只会抛出一条错误信息,如何来定位错误呢
很久以前的日本的房屋,房顶是植物的茎做成的

Docker 世界中最常见的两个名词是:镜像(Image)和容器(Container)。我们在执行 docker build 的过程,实际上就是在构建其中的镜像。在镜像构建完毕后,就可以无限创建出容器了。

镜像文件一旦构建完成后状态就完全确定了,所以每次启动容器才能得到同样的结果。其实这个镜像文件不光生成后不再改变,他在构建的过程中,每一级(层)确定了之后都不会变了。

举例来说,Dockerfile文件从上到下执行,其中执行的每一行 COPY,RUN 等操作都会创建一个新层,叠加到前面的结果上。这样做的目的是,减少空间和时间的浪费。

不同的人,在相同的起始位置上,执行同样的 Dockerfile 中的语句,得到的是同样的结果,既然一样,就没必要存多份,缓解了网上 Docker 仓库的存储压力。另一方面节省了时间,在第二次执行 docker build 的时候,如果某一行执行前,它的起始状态和上一次执行到这里时的起始状态是一样的,那么就会直接使用上次计算的结果,从而节约了时间。

也正是因为这个道理,我们只需要获取到 Dockerfile 产生错误的那行执行前的状态,然后检查它有没有问题,就可以改出正确的 Dockerfile了。

具体实现方式是,在 macOS系统下,执行 docker build 前设置一个环境变量 ”DOCKER_BUILDKIT=0“。也可以直接加在 docker build 的前面。

DOCKER_BUILDKIT=0 docker build .
build.sh

执行之后,你可能会看到如下的输出:

Step 11/19 : COPY server/PineHamster .
 ---> d30237b0b4ce
Step 12/19 : WORKDIR "/src/PineHamster/server/PineHamster/Evrane.PineHamster.Web.Admin"
 ---> Running in 78ab8ca07476
Removing intermediate container 78ab8ca07476
 ---> 74365d7ae435
Step 13/19 : RUN dotnet build "Evrane.PineHamster.Web.Admin.csproj" -c Release -o /app/build
 ---> Running in 5279d7917a89
MSBuild version 17.6.3+07e294721 for .NET
  Determining projects to restore...
log.txt

假设最后一行的日志显示了错误,那么你可以从下向上找到第一个写着" ---> xxxxxxxx“ 的地方。然后用这个编号所对应的中间镜像来启动一个容器。

docker run --rm -it 74365d7ae435 bash -il
run.sh

现在就可以在容器内部调查为什么下面那行语句出现问题了。