编辑
2024-02-09
TechNotes
00

目录

基本概念
是什么?
为什么需要?
能干什么?
构建镜像
commit
build
Dockerfile指令
常用指令
FROM
MAINTAINER
LABEL
ENV
RUN
ADD
WORKDIR
VOLUME
EXPOSE
CMD
ENTRYPOINT
拓展指令
ARG
USER
ONBUILD
STOPSIGNAL
HEALTHCHECK
ENTRYPOINT 和 CMD 的用法和区别
ENTRYPOINT
示例 1:使用 ENTRYPOINT 和 CMD 的组合
示例 2:仅使用 ENTRYPOINT
示例 3:仅使用 CMD
总结

基本概念

是什么?

Docker 为我们提供的一个用于自定义构建镜像的一个配置文件:描述如何构建一个对象

利用 Docker 提供的 build 命令,指定 Dockerfile 文件,就可以按照配置的内容将镜像构建出来

为什么需要?

作为开发者需要将自己开发好的项目打包成 Docker 镜像,便于后面直接作为 Docker 容器运行

作为运维人员需要构建更精简的基础设施服务镜像,满足公司的需求以及尽可能减少冗余的功能占用过多的资源

能干什么?

  • 可以自定义镜像内容
  • 构建公共基础镜像减少其他镜像配置
  • 开源程序的快速部署
  • 实现企业内部项目的快速交付

450977-20190512115951746-136143052.png

构建镜像

commit

基于一个现有的容器,构建一个新的镜像

  • 命令:
bash
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
  • 例:
bash
docker commit -a="gyc" -m="first image" centos7 mycentos:7
  • OPTIONS:
    • -a:镜像的作者
    • -c:使用 Dockerfile 指令来构建镜像
    • -m:提交时的描述
    • -p:在 commit 时暂停容器

build

docker build 命令用于从 Dockerfile 构建 Docker 镜像。

  • 基本格式:
bash
docker build [OPTIONS] PATH
  • 常用参数说明:

    • -t--tag:指定镜像的标签(名字),例如 my-image:latest
    • -f--file:指定 Dockerfile 的路径(默认为当前目录下的 Dockerfile)。
    • --no-cache:在构建过程中不使用缓存。
    • --build-arg:设置构建时的变量。
  • 示例:

bash
docker build -t my-image:latest .
  • 这个命令将在当前目录(.)下查找 Dockerfile 并构建镜像,镜像名称为 my-image,标签为 latest

  • 如果你有一个自定义路径的 Dockerfile,可以这样使用:

bash
docker build -t my-image:latest -f /path/to/Dockerfile .
  • 这样 Dockerfile 会从指定路径读取,而构建上下文仍是当前目录。

Dockerfile指令

常用指令

FROM

指定以什么镜像作为基础镜像,在改进项的基础之上构建新的镜像。

如果不想以任何镜像作为基础:FROM scratch

  • 语法:

    • FROM <image>
    • FROM <image>:<tag>
    • FROM <image>:<digest>
  • 以上为三种写法,后两者为指定具体版本,第一种则使用 latest 也就是最新版

MAINTAINER

指定该镜像的作者

  • 语法:
    • MAINTAINER <name>

LABEL

为镜像设置标签,一个 Dockerfile 中可以配置多个 LABEL

  • 语法:

    • LABEL <key>=<value>
  • 如:

    • LABEL "example.label"="Example Label"
    • LABEL label-value="LABEL"
    • LABEL version="1.0.0"
    • LABEL description="可以写成多行,使用 \
    • 符号可以拼接多行的 value"
  • PS:LABEL 指令会继承基础镜像(FROM)中的 LABEL,如果当前镜像 LABEL 的 key 与其相同,则会将其覆盖

ENV

  • 设置容器的环境变量,可以设置多个

  • 语法:

    • ENV <key> <value>
    • ENV <key>=<value> <key>=<value> ...
  • 两种语法的区别为第一种一次只能设置一个环境变量,第二种可以一次设置多个

RUN

构建镜像的过程中要执行的命令

  • 语法:

    • RUN <command>
    • RUN ["executable", "param1", "param2"]
  • 第一种写法就是直接写 Shell 脚本即可

  • 第二种写法类似函数调用,第一个参数为可执行文件,后面的都是参数

ADD

  • 复制命令,把 src 的文件复制到镜像的 dest 位置

  • 语法:

    • ADD <src> <dest>
    • ADD ["<src>", "<dest>"]

WORKDIR

设置工作目录,可以简单理解为 cd 到指定目录,如果该目录不存在会自动创建,对 RUN、CMD、ENTRYPOINT、COPY、ADD 生效,可以设置多次 WORKDIR

  • 如:

    • WORKDIR <dir>
  • 表示在容器内创建了 dir 目录,并且当前目录已经是 dir 目录了

VOLUME

设置挂载目录,可以将主机中的指定目录挂载到容器中

  • 语法:

    • VOLUME ["<dir>"]
    • VOLUME <dir>
    • VOLUME <dir> <dir>
  • 以上三种写法都可

EXPOSE

改镜像运行容器后,需要暴露给外部的端口,但仅仅表示该容器想要暴露某些端口,并不会与主机端口有映射关系,如果想将容器暴露的端口与主机映射则需要使用 -p 或 -P 参数来映射,可以暴露多个端口

  • 语法:
    • EXPOSE <port>[/<tcp/udp>]

CMD

该镜像启动容器时默认执行的命令或参数

  • 语法:

    • CMD ["executable", "param1", "param2"]
    • CMD ["param1", "param2"]
    • CMD <command> <param1> <param2>
  • 以上为该命令的三种写法,第三种与普通 Shell 命令类似,第一、二两种都是可执行文件 + 参数的形式,另外数组内的参数必须使用双引号。

  • 案例:

    • 第一种:CMD ["sh", "-c", "echo $HOME"] 等同于 sh -c "echo $HOME"

    • 第二种:CMD ["echo", "$HOME"] 等同于 echo $HOME

ENTRYPOINT

运行容器时的启动命令,感觉与 CMD 命令会很像,实际上还是有很大区别,简单对比一下:

  • 相同点: 在整个 Dockerfile 中只能设置一次,如果写了多次则只有最后一次生效

  • 不同点:

    • ENTRYPOINT 不会被运行容器时指定的命令所覆盖,而 CMD 会被覆盖
  • 如果同时设置了这两个指令,且 CMD 仅仅是选项而不是参数,CMD 中的内容会作为 ENTRYPOINT 的参数(一般不这么做)

  • 如果两个都是完整命令,那么只会执行最后一条

  • 语法:

    • ENTRYPOINT ["executable", "param1", "param2"]
    • ENTRYPOINT command param1 param2

拓展指令

ARG

设置变量,在镜像中定义一个变量,当使用 docker build 命令构建镜像时,带上 --build-arg <name>=<value> 来指定参数值,如果该变量名在 Dockerfile 中不存在则会抛出一个警告

  • 语法:
    • ARG <name>[=<default value>]

USER

设置容器的用户,可以是用户名或 UID,如果容器设置了以 daemon 用户去运行,那么 RUN、CMD 和 ENTRYPOINT 都会以这个用户去运行,一定要先确定容器中有这个用户,并且拥有对应的操作权限。

  • 语法:
    • USER <username>
    • USER <PID>

ONBUILD

表示在构建镜像时做某操作,不过不对当前 Dockerfile 的镜像生效,而是对以当前 Dockerfile 镜像作为基础镜像的子镜像生效

  • 语法:

    • ONBUILD [INSTRUCTION]
  • 例:

    • 当前镜像为 A,设置了如下指令 ONBUILD RUN ls -al

    • 镜像 B:
      FROM 镜像A
      ......
      构建镜像 B 时,会执行 ls -al 命令

STOPSIGNAL

STOPSIGNAL 指令设置将发送到容器的系统调用信号以退出。此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如 9,或 SIGNAME 格式的信号名,例如 SIGKILL。

默认的stop-signal是SIGTERM,在docker stop的时候会给容器内PID为1的进程发送这个signal,通过--stop-signal可以设置自己需要的signal,主要的目的是为了让容器内的应用程序在接收到signal之后可以先做一些事情,实现容器的平滑退出,如果不做任何处理,容器将在一段时间之后强制退出,会造成业务的强制中断,这个时间默认是10s。

bash
STOPSIGNAL \<signal>

HEALTHCHECK

容器健康状况检查,可以指定周期检查容器当前的健康状况,该命令只能出现一次,如果有多次则只有最后一次生效。

  • 语法:

    • HEALTHCHECK [OPTIONS] CMD command
    • HEALTHCHECK NONE
  • 第一种:在容器内部按照指定周期运行指定命令来检测容器健康状况

  • 第二种:取消在基础镜像

  • OPTIONS 选项:

    • --interval=DURATION 两次检查的间隔时间,默认30s
    • --timeout=DURATION 命令执行的超时时间,默认30s
    • --retries=N 当连续失败指定次数,容器会被认定为不健康,默认为3次
    • 返回参数:
    • 0:success => 健康状态
    • 1:unhealthy => 不健康状态
    • 2:reserved => 保留值

ENTRYPOINT 和 CMD 的用法和区别

ENTRYPOINT

  • 定义ENTRYPOINT 指定了容器启动时要执行的主要命令,并且这个命令不能被覆盖。
  • 用途:适用于需要确保容器启动时始终执行特定命令的情况。
  • 用法
    • Exec 格式(推荐):
      Dockerfile
      ENTRYPOINT ["executable", "param1", "param2"]
    • Shell 格式
      Dockerfile
      ENTRYPOINT executable param1 param2

CMD

  • 定义CMD 提供了容器启动时的默认参数,这些参数可以被 docker run 命令行中指定的参数覆盖。
  • 用途:适用于提供默认参数或命令,并允许在启动容器时覆盖它们的情况。
  • 用法
    • Exec 格式(推荐):
      Dockerfile
      CMD ["param1", "param2"]
    • Shell 格式
      Dockerfile
      CMD executable param1 param2

使用示例

示例 1:使用 ENTRYPOINTCMD 的组合

假设您要创建一个容器,它启动时会运行一个 Python 脚本,并且您希望能够覆盖脚本的参数。

Dockerfile
# Dockerfile FROM python:3.9-slim # 将 Python 脚本复制到容器中 COPY script.py /usr/src/app/script.py # 设置 ENTRYPOINT ENTRYPOINT ["python", "/usr/src/app/script.py"] # 提供默认参数 CMD ["default_arg1", "default_arg2"]

解释

  • ENTRYPOINT 指定了容器启动时始终运行 python /usr/src/app/script.py
  • CMD 提供了默认参数 default_arg1default_arg2,这些参数可以在 docker run 命令中被覆盖。

运行

  • 使用默认参数:

    bash
    docker run myimage

    这将运行 python /usr/src/app/script.py default_arg1 default_arg2

  • 使用自定义参数:

    bash
    docker run myimage custom_arg1 custom_arg2

    这将运行 python /usr/src/app/script.py custom_arg1 custom_arg2

示例 2:仅使用 ENTRYPOINT

如果您希望容器总是执行一个固定的命令,并且不希望在 docker run 中覆盖该命令,可以仅使用 ENTRYPOINT

Dockerfile
# Dockerfile FROM ubuntu:latest # 设置 ENTRYPOINT ENTRYPOINT ["/bin/echo", "Hello"]

运行

  • 运行容器:
    bash
    docker run myimage World
    这将输出 Hello WorldENTRYPOINT 中的 /bin/echo 是固定的,而 docker run 中提供的 World 是传递给 echo 命令的参数。

示例 3:仅使用 CMD

如果您不需要指定固定的命令,只是提供默认参数,可以仅使用 CMD

Dockerfile
# Dockerfile FROM ubuntu:latest # 设置 CMD CMD ["echo", "Hello World"]

运行

  • 使用默认命令:

    bash
    docker run myimage

    这将输出 Hello World

  • 使用自定义命令:

    bash
    docker run myimage "Custom Message"

    这将输出 Custom Message

总结

  • ENTRYPOINT:用于指定容器启动时始终执行的主要命令。如果 ENTRYPOINTCMD 都定义了,CMD 提供的参数将作为 ENTRYPOINT 中命令的默认参数。
  • CMD:用于提供容器启动时的默认参数,这些参数可以被 docker run 命令中的参数覆盖。

选择使用 ENTRYPOINTCMD 还是两者结合取决于您是否需要固定的执行命令或提供默认参数并允许覆盖。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:GYC

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!