Dockerfile实战

打印 上一主题 下一主题

主题 829|帖子 829|积分 2487

dockerfile介绍

dockerfile是什么

Dockerfile是一个创建镜像所有命令的文本文件, 包含了一条条指令和说明, 每条指令构建一层, 通过 docker build命令,根据Dockerfile的内容构建镜像,因此每一条指令的内容, 就是描述该层怎样构建.有了 Dockefile, 就可以制定自己的docker镜像规则,只需要在Dockerfile上添加或者修改指令, 就可生成 docker 镜像.
dockerfile办理了什么题目

Dockerfile 包含了镜像制作的完整操纵流程,其他开发者可以通过 Dockerfile 了解并复现制作过程 Dockerfile 中的每一条指令都会创建新的镜像层,这些镜像可以被 Docker Daemon 缓存。再次制作镜 像时,Docker 会尽量复用缓存的镜像层(using cache),而不是重新逐层构建,如许可以节省时间和 磁盘空间 Dockerfile 的操纵流程可以通过docker image history [镜像名称]查询,方便开发者查看变更记录
docker build 构建流程

docker build命令会读取Dockerfile的内容,并将Dockerfile的内容发送给 Docker 引擎,最终 Docker 引擎会解析Dockerfile中的每一条指令,构建出需要的镜像。
第一步,docker build会将 context 中的文件打包传给 Docker daemon。如果 context 中 有.dockerignore文件,则会从上传列表中删除满意.dockerignore规则的文件。留意:如果上下文中有 相称多的文件,可以明显感受到整个文件发送过程 这里有个破例,如果.dockerignore文件中有.dockerignore或者Dockerfile,docker build命令在排除文 件时会忽略掉这两个文件。如果指定了镜像的 tag,还会对 repository 和 tag 进行验证。
第二步,docker build命令向 Docker server 发送 HTTP 哀求,哀求 Docker server 构建镜像,哀求中 包含了需要的 context 信息。
第三步,Docker server 吸取到构建哀求之后,会执行以下游程来构建镜像: 1. 创建一个临时目次,并将 context 中的文件解压到该目次下。 2. 读取并解析 Dockerfile,遍历此中的指令,根据命令类型分发到不同的模块去执行。 3. Docker 构建引擎为每一条指令创建一个临时容器,在临时容器中执行指令,然后 commit 容器, 生成一个新的镜像层。 4. 最后,将所有指令构建出的镜像层合并,形成 build 的最后效果。最后一次 commit 生成的镜像 ID 就是最终的镜像 ID。
为了进步构建效率,docker build默认会缓存已有的镜像层。如果构建镜像时发现某个镜像层已经被缓 存,就会直接使用该缓存镜像,而不消重新构建。如果不希望使用缓存的镜像,可以在执行docker build命令时,指定–no-cache=true参数。
Docker 匹配缓存镜像的规则为:遍历缓存中的底子镜像及其子镜像,检查这些镜像的构建指令是否和当 前指令完全划一,如果不一样,则说明缓存不匹配。对于ADD、COPY指令,还会根据文件的校验和 (checksum)来判断添加到镜像中的文件是否雷同,如果不雷同,则说明缓存不匹配。 这里要留意,缓存匹配检查不会检查容器中的文件。比如,当使用RUN apt-get -y update命令更新了容 器中的文件时,缓存战略并不会检查这些文件,来判断缓存是否匹配。 最后,可以通过docker history命令来查看镜像的构建汗青
关键字

  1. FROM 设置镜像使用的基础镜像
  2. MAINTAINER 设置镜像的作者
  3. RUN 编译镜像时运行的脚步
  4. CMD 设置容器的启动命令
  5. LABEL 设置镜像标签
  6. EXPOSE 设置镜像暴露的端口
  7. ENV 设置容器的环境变量
  8. ADD 编译镜像时复制上下文中文件到镜像中
  9. COPY 编译镜像时复制上下文中文件到镜像中
  10. ENTRYPOINT 设置容器的入口程序
  11. VOLUME 设置容器的挂载卷
  12. USER 设置运行 RUN CMD ENTRYPOINT的用户名
  13. WORKDIR 设置 RUN CMD ENTRYPOINT COPY ADD 指令的工作目录
  14. ARG 设置编译镜像时加入的参数
  15. ONBUILD 设置镜像的ONBUILD 指令
  16. STOPSIGNAL 设置容器的退出信号量
复制代码
dockerfile 实践

根本语法实践

  1. mkdir example1
  2. cd example1
  3. FROM golang:1.18
  4. ENV env1=env1value
  5. ENV env2=env2value
  6. MAINTAINER nick
  7. # 仅指定镜像元数据内容
  8. LABEL hello 1.0.0
  9. RUN git clone https://gitee.com/nickdemo/helloworld.git
  10. WORKDIR helloworld
  11. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  12. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  13. EXPOSE 80
  14. CMD ["./app","--param1=p1","--param2=p2"]
  15. docker build -t hello:1.0.0 -f Dockerfile .
  16. docker run -p 80:80 -d --name hello hello:1.0.0
复制代码
docker build上下文


  • 素材预备
  1. # 创建一个目录,案例需要
  2. mkdir example2
  3. cd example2
  4. # 下载nginx源码包,作为案例素材
  5. curl https://nginx.org/download/nginx-1.21.6.tar.gz > ./nginx-1.21.6.tar.gz
  6. # 下载app代码
  7. git clone https://gitee.com/nickdemo/helloworld
  8. # ./nginx*
  9. # helloworld
复制代码

  • 没有什么作用的上下文
    1. FROM golang:1.18
    2. ENV env1=env1value
    3. ENV env2=env2value
    4. MAINTAINER nick
    5. # 仅指定镜像元数据内容
    6. LABEL hello 1.0.0
    7. RUN git clone https://gitee.com/nickdemo/helloworld.git
    8. WORKDIR helloworld
    9. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
    10. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
    11. EXPOSE 80
    12. CMD ["./app","--param1=p1","--param2=p2"]
    13. # 调整为不同的上下文,查看不同的效果
    14. docker build -t hello:1.0.0 -f Dockerfile .
    复制代码
  • 上下文的真正作用
    1. FROM golang:1.18
    2. ENV env1=env1value
    3. ENV env2=env2value
    4. MAINTAINER nick
    5. LABEL hello 1.0.0
    6. COPY ./helloworld /go/src/helloworld
    7. WORKDIR /go/src/helloworld
    8. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
    9. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
    10. EXPOSE 80
    11. CMD ["./app","--param1=p1","--param2=p2"]
    12. docker build -t hello:1.0.0 -f Dockerfile .
    复制代码
多阶段构建以及ADD与COPY

多阶段构建

Docker 17.05版本以后,新增了Dockerfile多阶段构建。所谓多阶段构建,实际上是允许一个Dockerfile
中出现多个 FROM 指令。如许做有什么意义呢?
多个 FROM 指令的意义
多个 FROM 指令并不是为了生成多根的层关系,最后生成的镜像,仍以最后一条 FROM 为准,之前的
FROM 会被扬弃,那么之前的FROM 又有什么意义呢?
每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后
一个阶段的效果,但是,可以大概将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意
义。
最大的使用场景是将编译情况和运行情况分离,比如,之前我们需要构建一个Go语言程序,那么就需要
用到go命令等编译情况

  • 素材预备
  1. # 创建一个目录,案例需要
  2. mkdir example3
  3. cd example3
  4. # 下载nginx源码包,作为案例素材
  5. curl https://nginx.org/download/nginx-1.21.6.tar.gz > ./nginx-1.21.6.tar.gz
  6. # 下载app代码
  7. git clone https://gitee.com/nickdemo/helloworld
复制代码

  • 一个最根本的dockerfile
  1. FROM golang:1.18
  2. ENV env1=env1value
  3. ENV env2=env2value
  4. MAINTAINER nick
  5. LABEL hello 1.0.0
  6. COPY ./helloworld /go/src/helloworld
  7. WORKDIR /go/src/helloworld
  8. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  9. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  10. EXPOSE 80
  11. CMD ["./app","--param1=p1","--param2=p2"]
复制代码

  • 多阶段构建dockerfile
  1. FROM golang:1.18
  2. ADD ./helloworld /go/src/helloworld/
  3. WORKDIR /go/src/helloworld
  4. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  5. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  6. FROM alpine:latest
  7. ENV env1=env1value
  8. ENV env2=env2value
  9. MAINTAINER nick
  10. LABEL hello 1.0.0
  11. WORKDIR /app/
复制代码
4.通过as关键词,为构建阶段指定别名,可以进步可读性
  1. FROM golang:1.18 as stage0
  2. ADD ./helloworld /go/src/helloworld/
  3. WORKDIR /go/src/helloworld
  4. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  5. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  6. FROM alpine:latest
  7. ENV env1=env1value
  8. ENV env2=env2value
  9. MAINTAINER nick
  10. LABEL hello 1.0.0
  11. WORKDIR /app/
  12. COPY --from=stage0 /go/src/helloworld/app ./
  13. EXPOSE 80
  14. CMD ["./app","--param1=p1","--param2=p2"]
复制代码
ADD 与 COPY


  • ADD 与 COPY 不能拷贝上下文以外的文件
  • COPY 命令语法格式
  1. COPY <src> <dest> //将上下文中源文件,拷贝到目标文件
  2. COPY prefix* /destDir/ //将所有prefix 开头的文件拷贝到 destDir 目录下
  3. COPY prefix?.log /destDir/ //支持单个占位符,例如 : prefix1.log、prefix2.log 等
复制代码

  • 对于目次而言,COPY 和 ADD 命令具有雷同的特点:只复制目次中的内容而不包含目次自身
  • COPY 区别于ADD在于Dockerfile中使用multi-stage
  1. FROM golang:1.18 as stage0
  2. ADD ./helloworld /go/src/helloworld/
  3. WORKDIR /go/src/helloworld
  4. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  5. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  6. FROM alpine:latest
  7. ENV env1=env1value
  8. ENV env2=env2value
  9. MAINTAINER nick
  10. LABEL hello 1.0.0
  11. WORKDIR /app/
  12. COPY --from=stage0 /go/src/helloworld/app ./
  13. EXPOSE 80
  14. CMD ["./app","--param1=p1","--param2=p2"]
复制代码

  • ADD 命令语法
  1. ADD <src> <dest>
复制代码

  • ADD 案例
  1. # 下载nginx tar.gz包作为素材
  2. curl https://nginx.org/download/nginx-1.21.6.tar.gz > ./nginx-1.21.6.tar.gz
  3. FROM golang:1.18 as stage0
  4. # ADD ./helloworld /go/src/helloworld/
  5. COPY ./helloworld /go/src/helloworld/
  6. WORKDIR /go/src/helloworld
  7. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  8. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  9. FROM alpine:latest
  10. ENV env1=env1value
  11. ENV env2=env2value
  12. MAINTAINER nick
  13. LABEL hello 1.0.0
  14. ADD https://nginx.org/download/nginx-1.21.6.tar.gz /soft/
  15. COPY nginx-1.21.6.tar.gz /soft/copy/
  16. ADD nginx-1.21.6.tar.gz /soft/add/
  17. WORKDIR /app/
  18. COPY --from=stage0 /go/src/helloworld/app ./
  19. EXPOSE 80
  20. CMD ["./app","--param1=p1","--param2=p2"]
  21. docker build -t hello:1.0.0 -f Dockerfile .
  22. # 运行容器
  23. docker run -d --name hello hello:1.0.0
  24. # 查看add和copy的文件
  25. docker exec -it hello /bin/sh
复制代码
CMD

CMD 指令有三种格式
  1. # shell 格式
  2. CMD <command>
  3. # exec格式,推荐格式
  4. CMD ["executable","param1","param2"]
  5. # 为ENTRYPOINT 指令提供参数
  6. CMD ["param1","param2"]
复制代码

  • CMD 指令提供容器运行时的默认值,这些默认值可以是一条指令,也可以是一些参数。
  • 一个dockerfile中可以有多条CMD指令,但只有最后一条CMD指令有用。
  • CMD参数格式是在CMD指令与ENTRYPOINT指令共同时使用,CMD指令中的参数会添加到
    ENTRYPOINT指令中。
  • 使用shell 和exec 格式时,命令在容器中的运行方式与RUN 指令雷同。不同在于,RUN指令在构
    建镜像时执行命令,并生成新的镜像。
  • CMD指令在构建镜像时并不执行任何命令,而是在容器启动时默认将CMD指令作为第一条执行的
    命令。如果在命令行界面运行docker run 命令时指定命令参数,则会覆盖CMD指令中的命令。
  1. FROM golang:1.18 as stage0
  2. ADD ./helloworld /go/src/helloworld/
  3. WORKDIR /go/src/helloworld
  4. RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
  5. RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
  6. FROM alpine:latest
  7. ENV env1=env1value
  8. ENV env2=env2value
  9. MAINTAINER nick
  10. LABEL hello 1.0.0
  11. WORKDIR /app/
  12. COPY --from=stage0 /go/src/helloworld/app ./
  13. EXPOSE 80
  14. CMD ["./app","--param1=p1","--param2=p2"]
  15. docker build -t hello:1.0.0 .# 指定启动命令和参数docker run -d -p 80:80 hello:1.0.0 ./app --param1=1 --param2=2# 指定启动命令为shdocker run -dit -p 80:80 hello:1.0.0 shcurl http://localhost/print/startup
复制代码
Linux C/C++开发学习资料

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

飞不高

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表