0


Dockerfile 详解

文章目录

  • 一、Dockerfile(制作镜像脚本化)
    • 1.1 什么是Dockerfile- 1.2 为什么要使用Dockerfile
  • 二、Docker Build 工作原理
  • 三、Dockerfile 常用指令
    • 3.1 FROM- 3.2 MAINTAINER(新版即将废弃)- 3.3 RUN- 3.4 ADD- 3.5 COPY- 3.6 CMD- 3.7 ENTRYPOINT- 3.8 LABEL- 3.9 ENV- 3.10 EXPOSE- 3.11 VOLUME- 3.12 WORKDIR- 3.13 USER- 3.14 ARG- 3.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 [email protected]
    MAINTAINER bertwu <[email protected]>

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 user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER 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:7
ARG parameter
VOLUME /usr/share/nginx
RUN yum -y install $parameter
EXPOSE 80 443
CMD 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 的参数。

镜像制作分为两个阶段:

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

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

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

使用 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-slim
COPY chatgpt-bootstrap/target/*.jar /app/app.jar
WORKDIR /app

ENV TZ=Asia/Shanghai

RUN 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/timezone

EXPOSE 3002
ENTRYPOINT ["sh","-c","java -jar -Xms150m -Xmx150m app.jar"]
标签: docker java linux

本文转载自: https://blog.csdn.net/2301_76154806/article/details/141472961
版权归原作者 繁星-赵老师 所有, 如有侵权,请联系我们删除。

“Dockerfile 详解”的评论:

还没有评论