• Docker入门 第二课 镜像构建,Dockerfile解读


     今天聊一聊Dockerfile,docker build,希望通过这篇文章,能让你对docker镜像构建过程有一个认识。

    事情还得从一次Docker镜像创建失败说起。

    问题背景:

    环境VS2017,dotnet 2.1 版本 ,使用默认生成的Dockerfile文件,当我使用docker build命令创建镜像的时候,竟然报错了

    Step 6/16 : ......
    COPY failed: stat /mnt/sda1/var/lib/docker/tmp/docker-builder802544848/EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj: no such file or directory 
    

    错误信息是,第6步,找不到指定的文件或文件夹,由于我执行docker build命令的路径与 项目文件(xxx.csproj)在同一目录下,所以,这个文件找不到也很正常,那到底是哪里出问题了呢?我们来捋一捋。  

    执行docker build命令的路径与项目文件(xxx.csproj)在同一路径。

    docker build 命令如下:

    docker build -t slide-verify:1.0 .
    

    Dockerfile内容如下:

     1 FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
     2 WORKDIR /app
     3 EXPOSE 80
     4 
     5 FROM microsoft/dotnet:2.1-sdk AS build
     6 WORKDIR /src
     7 COPY ["EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj", "EasySlideVerificationDemoServer/"]
     8 RUN dotnet restore "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj"
     9 COPY . .
    10 WORKDIR "/src/EasySlideVerificationDemoServer"
    11 RUN dotnet build "EasySlideVerificationDemoServer.csproj" -c Release -o /app
    12 
    13 FROM build AS publish
    14 RUN dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app
    15 
    16 FROM base AS final
    17 WORKDIR /app
    18 COPY --from=publish /app .
    19 ENTRYPOINT ["dotnet", "EasySlideVerificationDemoServer.dll"]

    Docker镜像生成原理:

    Docker镜像与操作系统镜像本质上是一样的,首先需要一个基础镜像,然后在基础镜像上搭建所需环境,安装软件,最后生成一个新的镜像,新的镜像就可以在Docker中进行部署,生成容器实例,从而开始运行服务。

    Dockerfile中的命令:

    从上面Dockerfile中,我们可以看到有这几个命令:FROM,WORKDIR,EXPOSE,COPY,RUN,ENTRYPOINT,大概了解一下这几个命令的意思。

    FROM:    指定一个基础镜像

    WORKDIR:  在镜像内指定一个目录,作为当前工作目录

    EXPOSE:     指定端口号

    COPY:    从一个目录(这个目录可以是本地目录或中间镜像的目录)中复制文件或者目录到容器里指定路径

    RUN:       在镜像内执行相应命令

    ENTRYPOINT: 入口点,与RUN类似,同样是执行程序命令,表示容器启动时需要执行的命令。

    Dockerfile文件解读: 

    我们来解读一下这个Dockerfile

     1 将镜像 microsoft/dotnet:2.1-aspnetcore-runtime 作为基础镜像 (base)
     2 指定镜像内工作目录为:/app
     3 指定端口号为:80
     4 
     5 将镜像 microsoft/dotnet:2.1-sdk 作为系统构建中间镜像(build)
     6 指定镜像内工作目录为: /src
     7 复制项目文件 "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj" 到镜像目录 "EasySlideVerificationDemoServer/"
     8 执行dotnet restore命令: dotnet restore "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj"
     9 复制当前目录下所有文件到镜像的工作目录(/src)下:COPY . .
    10 指定新的工作目录: "/src/EasySlideVerificationDemoServer"
    11 执行dotnet build命令: dotnet build "EasySlideVerificationDemoServer.csproj" -c Release -o /app
    12 
    13 将构建好的中间镜像(build) 作为发布中间镜像(publish)
    14 执行dotnet publish命令: dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app
    15 
    16 将基础镜像(base)作为最终镜像(final)
    17 指定工作目录: /app
    18 复制发布中间镜像(publish)中的/app目录到工作目录:COPY --from=publish /app .
    19 指定入口点命令:ENTRYPOINT ["dotnet", "EasySlideVerificationDemoServer.dll"] 

    解读完之后,我们了解了这个Dockerfile究竟做了哪些事情。

    镜像构建命令:

    然后看一下Docker镜像构建命令:docker build。

    命令行输入:docker build --help,可查看完整使用方式,此处省略。

    Usage: docker build [OPTIONS] PATH | URL | -

    下面是我使用的构建命令:

    docker build -t slide-verify:1.0 .
    

    -t name:tag   表示给镜像命名,并指定标签(相当于版本号)

    -f Dockerfile  指定Dockerfile文件,默认为'PATH/Dockerfile',即当前目录下的Dockerfile

    PATH     表示本地工作目录(也就是命令最后的 . ,我这里是项目文件夹)

    发现问题:

    到这里不难发现,由于镜像构建命令的执行目录与项目文件所在目录一致,并且命令中PATH指定的是当前目录(.),也就是项目文件所在目录,而Dockerfile中文件复制命令明显是在项目文件的上一级,即解决方案文件夹目录,

    这样问题似乎就容易解决了,将构建命令改成下面的格式,果不其然,构建成功。

    docker build -t slide-verify:1.3 -f Dockerfile ..
    

    然后执行docker run命令,运行构建好的镜像,启动成功,浏览器访问:http://192.168.99.100:5008/  ,项目成功运行。

    docker run -it -p 5008:80 --name slide-verify13 slide-verify:1.3
    

      

      

    使用进阶:

    我们回头再看一下Dockerfile文件,文件中的5到14行命令,包含了源码复制,项目还原(restore),构建(build),发布(publish)几个步骤。

     5 FROM microsoft/dotnet:2.1-sdk AS build
     6 WORKDIR /src
     7 COPY ["EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj", "EasySlideVerificationDemoServer/"]
     8 RUN dotnet restore "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj"
     9 COPY . .
    10 WORKDIR "/src/EasySlideVerificationDemoServer"
    11 RUN dotnet build "EasySlideVerificationDemoServer.csproj" -c Release -o /app
    12 
    13 FROM build AS publish
    14 RUN dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app

    我们知道,.net 中publish本身包含了restore和build,这几个命令理论上是可以合并的,来试一下,将Dockerfile修改为:

     1 FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
     2 WORKDIR /app
     3 EXPOSE 80
     4 
     5 FROM microsoft/dotnet:2.1-sdk AS publish
     6 WORKDIR /src
     7 COPY . .
     8 WORKDIR "/src/EasySlideVerificationDemoServer"
     9 RUN dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app
    10 
    11 FROM base AS final
    12 WORKDIR /app
    13 COPY --from=publish /app .
    14 ENTRYPOINT ["dotnet", "EasySlideVerificationDemoServer.dll"]

    再次构建镜像,果然构建成功

    docker build -t slide-verify:1.4 -f Dockerfile ..

    运行,容器成功启动。

    docker run -it -p 5009:80 --name slide-verify14 slide-verify:1.4

    至此,估计你我对镜像构建,Dockerfile,docker build 有了一个比较清晰的认识。

    更进一步:

    我们看,Dockerfile中主要做了两件事:

    第一,将源码复制到一个中间容器,在容器中编译,打包发布。

    第二,将中间容器中的发布文件复制到目的容器,启动运行。

    仔细想一想,有必要在容器中进行编译,发布吗?在本地编译发布岂不是更方便。(这里不涉及通过gitlib拉取代码,编译发布,那是另一会儿事。)

    于是,我将项目发布,目标运行时为:linux-64,发布到  /bin/Release/netcoreapp2.1/linux 文件夹下,修改Dockerfile如下:

    1 FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
    2 WORKDIR /app
    3 EXPOSE 80
    4 
    5 COPY ./bin/Release/netcoreapp2.1/linux .
    6 
    7 ENTRYPOINT ["dotnet", "EasySlideVerificationDemoServer.dll"]
    docker build -t slide-verify:1.5 .
    

      再次构建,因为减少了编译过程,这次构建更快更顺利。现在Dockerfile只剩下了5行代码,所谓熟能生巧,当是如此。

    总结:

    docker build [OPTIONS] PATH | URL | -

    docker build 命令中,PATH参数很重要,要搞明白。

    读懂了Dockerfile,自己尝试修改,并加以验证,更能加深理解。

  • 相关阅读:
    mysql网文收录
    centos7编译安装memcached
    计算机网络网文
    操作系统网文
    redis网文
    【Leetcode】746. Min Cost Climbing Stairs
    【Leetcode】198. House Robber
    【Leetcode】121. Best Time to Buy and Sell Stock
    【Leetcode】1. Two Sum
    函数的参数 2018-3-27
  • 原文地址:https://www.cnblogs.com/flame7/p/13655249.html
Copyright © 2020-2023  润新知