当前位置:首页 » 《关于电脑》 » 正文

Dockerfile 详解

1 人参与  2024年09月24日 17:20  分类 : 《关于电脑》  评论

点击全文阅读


文章目录

一、Dockerfile(制作镜像脚本化)1.1 什么是Dockerfile1.2 为什么要使用Dockerfile 二、Docker Build 工作原理三、Dockerfile 常用指令3.1 FROM3.2 MAINTAINER(新版即将废弃)3.3 RUN3.4 ADD3.5 COPY3.6 CMD3.7 ENTRYPOINT3.8 LABEL3.9 ENV3.10 EXPOSE3.11 VOLUME3.12 WORKDIR3.13 USER3.14 ARG3.15 ONBUILD 四、制作镜像

一、Dockerfile(制作镜像脚本化)

1.1 什么是Dockerfile

Dockerfile 是一个文本文件,包含一系列用于构建镜像的指令(Instructions)。每条指令都会构建一层镜像,指令的内容描述了该层镜像应如何构建。

Dockerfile 用于指导 docker image build 命令自动构建镜像它是一个纯文本文件

示例:

docker build -f /path/Dockerfile

1.2 为什么要使用Dockerfile

问题:Docker Hub 官方提供了许多满足我们服务需求的镜像,为什么还需要自定义镜像?

核心作用:用户可以将自己的应用打包成镜像,从而让应用在容器中运行。还可以对官方镜像进行扩展,打包成适合生产环境的应用镜像

完整镜像的结构图:

在这里插入图片描述

Dockerfile的格式

包含两种类型的行:

以 # 开头的注释行以专用"指令(Instruction)"开头的指令行

Image Builder 按顺序执行各指令,从而完成镜像构建
在这里插入图片描述

二、Docker Build 工作原理

在这里插入图片描述

docker build [选项] <上下文路径/URL/->

docker build 命令后的 . 表示当前目录,同时也指定了上下文路径。

上下文:

Docker 运行时分为 Docker 引擎(服务端守护进程)和客户端工具。Docker 引擎提供了一组 REST API,称为 Docker Remote API。客户端工具(如 docker 命令)通过这组 API 与 Docker 引擎交互,完成各种功能。

虽然表面上我们似乎在本机执行各种 Docker 功能,但实际上,一切都是通过远程调用在服务端(Docker 引擎)完成的。这种客户端/服务器设计使得操作远程服务器上的 Docker 引擎变得简单易行。

镜像构建过程中,不是所有定制都通过 RUN 指令完成。我们经常需要将本地文件复制进镜像,比如使用 COPY 或 ADD 指令。docker build 命令构建镜像时,实际上是在服务端(Docker 引擎)中进行的。那么,在这种客户端/服务端架构中,如何让服务端获得本地文件呢?

这就引入了上下文的概念。构建时,用户指定构建镜像的上下文路径,docker build 命令会将该路径下的所有内容打包并上传给 Docker 引擎。Docker 引擎收到并展开这个上下文包后,就能获得构建镜像所需的全部文件。

为什么有人误以为 . 是指定 Dockerfile 所在目录呢?这是因为默认情况下,如果不额外指定 Dockerfile,系统会将上下文目录下名为 Dockerfile 的文件作为 Dockerfile。

实际上,Dockerfile 的文件名不必是 “Dockerfile”,也不必位于上下文目录中。例如,可以用 -f …/Dockerfile 参数指定其他文件作为 Dockerfile。

不过,人们通常会沿用默认的文件名 Dockerfile,并将其放在镜像构建的上下文目录中。

三、Dockerfile 常用指令

官方 build 参考

在这里插入图片描述

3.1 FROM

指定基础镜像,必须为第一个命令

格式:    FROM <image>    FROM <image>:<tag>    FROM <image>@<digest>示例:    FROM mysql:5.6注:    tag 或 digest 是可选的,如果不指定,将使用 latest 版本的基础镜像

3.2 MAINTAINER(新版即将废弃)

维护者信息

格式:    MAINTAINER <name>示例:    MAINTAINER bertwu    MAINTAINER xxx@163.com    MAINTAINER bertwu <xxx@163.com>

3.3 RUN

构建镜像时执行的命令

RUN 用于在构建镜像时执行命令,有以下两种执行方式:shell 执行格式:    RUN <command>exec 执行格式:    RUN ["executable", "param1", "param2"]示例:    RUN ["executable", "param1", "param2"]    RUN apk update    RUN ["/etc/execfile", "arg1", "arg2"]注:RUN 指令创建的中间镜像会被缓存,并在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定 --no-cache 参数,如:docker build --no-cache

3.4 ADD

将本地文件添加到容器中,tar 类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似 wget

格式:    ADD <src>... <dest>    ADD ["<src>",... "<dest>"] 用于支持包含空格的路径示例:    ADD hom* /mydir/          # 添加所有以"hom"开头的文件    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

3.5 COPY

功能类似 ADD,但不会自动解压文件,也不能访问网络资源

3.6 CMD

构建镜像后调用,也就是在容器启动时才进行调用。

格式:    CMD ["executable","param1","param2"] (执行可执行文件,优先)    CMD ["param1","param2"] (设置了 ENTRYPOINT,则直接调用 ENTRYPOINT 添加参数)    CMD command param1 param2 (执行 shell 内部命令)示例:    CMD echo "This is a test." | wc -l    CMD ["/usr/bin/wc","--help"]注:CMD 不同于 RUN,CMD 用于指定容器启动时要执行的命令,而 RUN 用于指定镜像构建时要执行的命令。

3.7 ENTRYPOINT

配置容器,使其可执行化。配合 CMD 可省去"application",只使用参数。

格式:    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件,优先)    ENTRYPOINT command param1 param2 (shell 内部命令)示例:    FROM ubuntu    ENTRYPOINT ["ls", "/usr/local"]    CMD ["/usr/local/tomcat"]之后,docker run 传递的参数,都会先覆盖 CMD,然后由 CMD 传递给 ENTRYPOINT,实现灵活应用注:ENTRYPOINT 与 CMD 非常类似,不同的是通过 docker run 执行的命令不会覆盖 ENTRYPOINT,而 docker run 命令中指定的任何参数,都会被当做参数再次传递给 CMD。Dockerfile 中只允许有一个 ENTRYPOINT 命令,多次指定时会覆盖前面的设置,而只执行最后的 ENTRYPOINT 指令。通常情况下,ENTRYPOINT 与 CMD 一起使用,ENTRYPOINT 写默认命令,当需要参数时使用 CMD 传参

3.8 LABEL

用于为镜像添加元数据

格式:    LABEL <key>=<value> <key>=<value> <key>=<value> ...示例:    LABEL version="1.0" description="这是一个 Web 服务器" by="IT 笔录"注:    使用 LABEL 指定元数据时,一条 LABEL 指定可以指定一或多条元数据,指定多条元数据时不同元数据    之间通过空格分隔。推荐将所有的元数据通过一条 LABEL 指令指定,以免生成过多的中间镜像。

3.9 ENV

设置环境变量

格式:    ENV <key> <value>  # <key> 之后的所有内容均会被视为其 <value> 的组成部分,因此,一次只能设置一个变量    ENV <key>=<value> ...  # 可以设置多个变量,每个变量为一个 "<key>=<value>" 的键值对,如果 <key> 中包含空格,可以使用 \ 来进行转义,也可以通过 "" 来进行标示;另外,反斜线也可以用于续行示例:    ENV myName John Doe    ENV myDog Rex The Dog    ENV myCat=fluffy

3.10 EXPOSE

指定与外界交互的端口

格式:    EXPOSE <port> [<port>...]示例:    EXPOSE 80 443    EXPOSE 8080    EXPOSE 11211/tcp 11211/udp注:EXPOSE 并不会让容器的端口访问到主机。要使其可访问,需要在 docker run 运行容器时通过 -p 来发布这些端口,或通过 -P 参数来发布 EXPOSE 导出的所有端口如果没有暴露端口,后期也可以通过 -p 8080:80 方式映射端口,但不能通过 -P 形式映射

3.11 VOLUME

用于指定持久化目录(指定此目录可以被挂载出去)

格式:    VOLUME ["/path/to/dir"]示例:    VOLUME ["/data"]    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:1. 卷可以在容器间共享和重用2. 容器并不一定要和其它容器共享卷3. 修改卷后会立即生效4. 对卷的修改不会对镜像产生影响5. 卷会一直存在,直到没有任何容器在使用它

3.12 WORKDIR

工作目录,类似于 cd 命令

格式:    WORKDIR /path/to/workdir示例:    WORKDIR /a  (这时工作目录为 /a)    WORKDIR b  (这时工作目录为 /a/b)    WORKDIR c  (这时工作目录为 /a/b/c)注:  通过 WORKDIR 设置工作目录后,Dockerfile 中其后的命令 RUN、CMD、ENTRYPOINT、ADD、COPY  等命令都会在该目录下执行。在使用 docker run 运行容器时,可以通过 -w 参数覆盖构建时所设置的工作目录。

3.13 USER

指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用 USER 指定用户时,可以使用用户名、UID 或 GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

格式:USER userUSER user:groupUSER uidUSER uid:gidUSER user:gidUSER uid:group示例:    USER www注:    使用 USER 指定用户后,Dockerfile 中其后的命令 RUN、CMD、ENTRYPOINT 都将使用该用户。    镜像构建完成后,通过 docker run 运行容器时,可以通过 -u 参数来覆盖所指定的用户。

3.14 ARG

用于指定传递给构建运行时的变量(给 Dockerfile 传参),相当于构建镜像时可以在外部为里面传参

格式:    ARG <name>[=<default value>]示例:    ARG site    ARG build_user=www
From centos:7ARG parameterVOLUME /usr/share/nginxRUN yum -y install $parameterEXPOSE 80 443CMD nginx -g "daemon off;"# 可以这样灵活传参docker build --build-arg=parameter=net-tools -t nginx:01 .

3.15 ONBUILD

用于设置镜像触发器

格式:    ONBUILD [INSTRUCTION]示例:    ONBUILD ADD . /app/src    ONBUILD RUN /usr/local/bin/python-build --dir /app/src注:    ONBUILD 后面跟指令,当当前的镜像被用做其它镜像的基础镜像时,该镜像中的触发器将会被触发

四、制作镜像

如果有多个 RUN 指令,它们会自上而下依次执行,每次执行都会形成新的层。建议使用 && 将多个命令合并到一行中执行。如果有多个 CMD 指令,只有最后一个会生效。如果有多个 ENTRYPOINT 指令,只有最后一个会生效。如果 CMD 和 ENTRYPOINT 共存,只有 ENTRYPOINT 会执行,且最后的 CMD 会作为 ENTRYPOINT 的参数。

镜像制作分为两个阶段:

docker build 阶段:基于 Dockerfile 制作镜像(RUN 指令用于此阶段的命令执行)docker run 阶段:基于镜像运行容器(CMD 指令用于容器启动时需要运行的命令)docker build 阶段(基于现有镜像):当他人以你的镜像为基础制作新镜像时(ENTRYPOINT 或 ONBUILD 指令在此阶段执行)

以下示例中的注释已被移除

FROM openjdk:8-jreWORKDIR /appADD demo-0.0.1-SNAPSHOT.jar app.jarEXPOSE 8081ENTRYPOINT ["java", "-jar"]CMD ["app.jar"]
创建 Dockerfile 文件,粘贴如下内容:
FROM openjdk:8WORKDIR /rootADD springbootdemo3-0.0.1-SNAPSHOT.jar springboot.jarEXPOSE 9999ENTRYPOINT ["java", "-jar"]CMD ["springboot.jar"]
将你的 jar 包复制到与 Dockerfile 文件同级目录下进入 Dockerfile 所在目录,执行命令:docker build . -t 自定义镜像名称使用命令启动容器:docker run --name yourboot -d -p 端口映射 自定义镜像名称测试是否可以访问,记得在阿里云上开放相应端口

使用 uname -a 命令查看当前操作系统发行版本

使用 apt search name 命令搜索软件包

自制一个 OpenJDK 8 镜像:

FROM ubuntu:18.04RUN apt update -y && \    apt install -y openjdk-8-jre

根据 Dockerfile 构建镜像的命令:

docker build . -t 镜像名称

FROM openjdk:17-jdk-slimCOPY chatgpt-bootstrap/target/*.jar /app/app.jarWORKDIR /appENV TZ=Asia/ShanghaiRUN echo > /etc/apt/sources.list && \    sed -i "1ideb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib" /etc/apt/sources.list && \    sed -i "2ideb-src https://mirrors.aliyun.com/debian/ bullseye main non-free contrib" /etc/apt/sources.list && \    sed -i "3ideb https://mirrors.aliyun.com/debian-security/ bullseye-security main" /etc/apt/sources.list && \    sed -i "4ideb-src https://mirrors.aliyun.com/debian-security/ bullseye-security main" /etc/apt/sources.list && \    sed -i "5ideb https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib" /etc/apt/sources.list && \    sed -i "6ideb-src https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib" /etc/apt/sources.list && \    sed -i "7ideb https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib" /etc/apt/sources.list && \    sed -i "8ideb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib" /etc/apt/sources.list && \    apt-get update -y && \    apt-get install -y fontconfig && \    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneEXPOSE 3002ENTRYPOINT ["sh","-c","java -jar -Xms150m -Xmx150m app.jar"]

点击全文阅读


本文链接:http://zhangshiyu.com/post/164093.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1