侧边栏壁纸
博主头像
爱探索

行动起来,活在当下

  • 累计撰写 42 篇文章
  • 累计创建 11 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

docker-DockerFile详解

jelly
2024-07-08 / 0 评论 / 0 点赞 / 48 阅读 / 0 字

DockerFile详解

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明

1. docker 语法与构建

  1. 由一行行命令语句组成

  2. 执行是从上到下顺序执行

  3. 并且支持已 # 开头的注释行

  4. 该指令不区分大小写。然而,惯例是让他们 大写,以便更轻松地将它们与参数区分开来。

  5. 格式

    INSTRUCTION arguments

  6. 关于空格

    一般来说指令前面的空格将被忽略,但是指令参数中的空格不会

    # 下面的是等效的
    
          RUN echo hello
    RUN echo world
    
    RUN echo hello
    RUN echo world
    
    # 下面参数中空格不会被忽略
    RUN echo "\
    hello\
    world"
    
    

1.1. 命令大全

指令说明
ADD添加本地或远程文件和目录。
ARG使用构建时变量。
CMD指定默认命令。
COPY复制文件和目录。
ENTRYPOINT指定默认可执行文件。
ENV设置环境变量。
EXPOSE描述应用程序正在侦听的端口。
FROM从基础映像创建新的生成阶段。
HEALTHCHECK在启动时检查容器的运行状况。
LABEL向图像添加元数据。
MAINTAINER指定图像的作者。
ONBUILD指定在生成中使用映像的说明。
RUN执行构建命令。
SHELL设置映像的默认 shell。
STOPSIGNAL指定退出容器的系统调用信号。
USER设置用户和组 ID。
VOLUME创建卷装载。
WORKDIR更改工作目录。

1.2. build

docker buildx build [OPTIONS] PATH | URL | -

参数 / 参数缩写描述
--add-host添加自定义的主机到 IP 映射(格式:"host:ip")
--allow允许额外的特权授权(例如:"network.host", "security.insecure")
--annotation向镜像添加注解
--attest证明参数(格式:"type=sbom,generator=image")
--build-arg设置构建时变量
--build-context额外的构建上下文(例如:name=path)
--builder覆盖配置的构建实例(默认 "default")
--cache-from外部缓存源(例如:"user/app:cache", "type=local,src=path/to/dir")
--cache-to缓存导出目的地(例如:"user/app:cache", "type=local,dest=path/to/dir")
--call设置评估构建的方法("check", "outline", "targets")(默认 "build")
--cgroup-parent设置 "RUN" 指令期间的父 cgroup
--check简写为 "--call=check"
-f, --fileDockerfile 的名称(默认:"PATH/Dockerfile")
--iidfile将镜像 ID 写入文件
--label为镜像设置元数据
--load简写为 "--output=type=docker"
--metadata-file将构建结果元数据写入文件
--network设置 "RUN" 指令期间的网络模式(默认 "default")
--no-cache构建镜像时不使用缓存
--no-cache-filter指定不缓存的阶段
-o, --output输出目的地(格式:"type=local,dest=path")
--platform设置构建的目标平台
--progress设置进度输出类型("auto", "plain", "tty", "rawjson")
--provenance简写为 "--attest=type=provenance"
--pull始终尝试拉取所有引用的镜像
--push简写为 "--output=type=registry"
-q, --quiet抑制构建输出并在成功时打印镜像 ID
--sbom简写为 "--attest=type=sbom"
--secret暴露给构建的秘密(格式:"id=mysecret[,src=/local/secret]")
--shm-size构建容器的共享内存大小
--ssh暴露给构建的 SSH 代理套接字或密钥(格式:"default or < id >[=< socket >、< key > [,< key >]]")
-t, --tag名称和可选的标签(格式:"name:tag")
--target设置要构建的目标构建阶段
--ulimitUlimit 选项(默认 [])

2. 指令说明

2.1 FORM

有以下3中形式

  1. FROM [--platform=< platform >] < image > [AS < name >]

  2. FROM [--platform=< platform >] < image >[:< tag >] [AS < name >]

  3. FROM [--platform=< platform >] < image >[@< digest >] [AS < name >]

参数说明:

  • --platform: **这是一个可选参数,用于指定要构建的镜像的平台。**这可以是操作系统和架构的组合,例如 linux/amd64 或 windows/amd64。如果未指定,Docker 将使用构建上下文的平台。
  • image: 这是基础镜像的名称,可以是 Docker Hub 上的镜像名称,也可以是本地镜像的名称。此外,它还可以是一个完整的 URL 指向一个私有仓库的镜像。
  • AS < name >: 这也是一个可选参数,用于给基础镜像指定一个别名。这个别名可以在 Dockerfile 中的其他指令中使用,以引用这个特定的镜像。

示例:

# 1. 使用官方的 Ubuntu 镜像作为基础镜像
FROM ubuntu:latest

# 2. 指定构建目标平台为 linux/amd64
FROM --platform=linux/amd64 ubuntu:20.04

# 3. 使用官方的 Python 镜像,并给它一个别名 "python"
FROM python:3.8-slim AS python

2.2. ENV

2.1.1. 设置环境变量

  1. 设置单个环境变量

    ENV < key > = < value >

  2. 设置多个环境变量

    ENV < key1 > = < value1 > < key2 > < value2 > ...

  3. 设置多个值的列表
    ENV < key > = < value1 value2 value3 ... >

2.1.2. 使用环境变量

  1. 使用环境变量

${KEY}

2.1.3. 继承环境变量

使用 ENV 指令来覆盖基础镜像中已经设置的环境变量,新设置的值将在构建的镜像中生效

2.1.4. 示例


# 设置单个环境变量
ENV MY_VAR="my_value"

# 设置多个环境变量
ENV MY_VAR1="value1" MY_VAR2="value2"

# 设置多个值的列表
ENV MY_VAR="value1 value2 value3"

#使用环境变量的值
RUN echo ${MY_VAR}

2.3. ADD

ADD 指令用于将文件、目录、远程文件URL 或者 tar 压缩文件从一个或多个源复制到容器的文件系统。这个指令非常有用,因为它不仅可以复制本地文件,还可以从远程源拉取文件。

  1. 将本地文件或目录复制到容器中的指定路径

    ADD < src > < dest >

  2. 从远程 URL 复制文件到容器中的指定路径

    ADD < remote > < dest >

2.3.1. 示例


# 将当前目录下的 config.txt 文件复制到容器的 /etc/config 目录
ADD config.txt /etc/config/

# 将当前目录下的 data 目录复制到容器的 /data 目录
ADD data/ /data/

# 从指定的 URL 下载文件并复制到容器的 /tmp 目录
ADD http://example.com/remotefile.tar.gz /tmp/

# 将本地的 tar 文件自动解压到容器的 /app 目录
ADD archive.tar.gz /app/

2.4. WORKDIR

指令用于设置容器内的当前工作目录,相当于 shell 中的 cd 命令。这个指令对于容器内的命令非常重要,因为它定义了执行命令时的当前目录。

注:

  1. 如果指定的目录不存在,WORKDIR 指令会创建所有需要的中间目录。
  2. 在 Dockerfile 中,每个 WORKDIR 指令都会影响后续指令的执行环境。

示例

# 1. 设置工作目录

WORKDIR /app

# 2. 使用相对路径

WORKDIR /app
WORKDIR src

在设置了 /app 为工作目录之后,第二个 WORKDIR 指令将工作目录更改为 /app/src。

# 3. 与其他指令结合使用

WORKDIR /app
COPY . /app
RUN make /app

在这个例子中,首先设置了工作目录为 /app,然后将当前目录(构建上下文中的)中的所有文件复制到容器的 /app 目录中,最后在 /app 目录下执行 make 命令。

2.5. RUN

它用于执行任何所需的命令行命令,并将其结果(如安装的软件包或文件)作为镜像的一部分保存下来。RUN 指令可以视为构建过程中的一个独立步骤,每个步骤都会创建一个新的镜像层

语法

  • shell 形式:RUN <命令>

    使用 shell 语法执行命令。默认情况下,shell 形式使用 /bin/sh -c 作为 shell。

  • exec 形式:RUN ["可执行文件", "参数1", "参数2", ...]

    明确指定命令和参数,通常用于需要明确区分命令和参数的情况,或者使用像 /bin/bash 这样的特定 shell。

注意事项:

  1. RUN 指令执行的命令会在新的层上执行,这意味着每个 RUN 指令都会创建一个新的镜像层,可能导致镜像体积变大。因此,应尽量合并多个命令到单个 RUN 指令中,以减少层数。

  2. 使用 && 连接多个命令时,它们会在同一层上顺序执行。例如,RUN apt-get update && apt-get install -y curl 只会创建一个层。

  3. 如果需要执行的命令较长或包含多个行,可以使用反引号 ` 或者 $() 来包围命令,例如:

    RUN apt-get update && \
    apt-get install -y \
    curl \
    git
    
  4. 使用 RUN 指令时,应避免使用交互式命令,因为 Docker 容器默认不应该运行交互式进程。

2.5.1. 示例


# 安装软件包
RUN apt-get update && apt-get install -y curl


# 执行简单的命令:
RUN echo 'Hello, Docker!'

# 使用 exec 形式
RUN ["/bin/bash", "-c", "echo 'Using exec form'"]

2.6. EXPOSE

暴漏端口

示例

# 1.暴露单个端口:
EXPOSE 80

# 2. 暴露多个端口:
EXPOSE 80 443

# 3. 使用协议指定端口:
EXPOSE tcp://80 udp://53

#4. 暴露端口范围:
EXPOSE 3000-3005

2.7 CMD

用于指定容器启动时默认执行的命令。如果 Dockerfile 中没有 CMD 指令,Docker 容器将不知道执行什么命令,可能会返回错误或简单地退出。

  • CMD ["executable", "param1", "param2"...]
  • CMD command param1 param2 ...

# 执行简单的命令:
CMD ["echo", "Hello, World!"]
# 启动一个服务:
CMD ["apache2", "-D", "FOREGROUND"]
# 使用 shell 形式:
CMD echo "The container is running"
# 传递环境变量:
CMD ["sh", "-c", "echo $MY_ENV_VAR"]
# 结合其他指令:
FROM ubuntu
RUN apt-get update && apt-get install -y nginx
CMD ["nginx", "-g", "daemon off;"]

3. 示例创建一个tomcat镜像

准备:

  1. 下载apache-tomcat-9.0.91.tar.gz包放在Dockerfile包下
  2. 下载jdk-11.0.2_linux-x64_bin.tar.gz包放在Dockerfile包下

# 使用debian做基础镜像
FROM debian 

# 设置作者名与邮箱
LABEL maintainer="jelly<xxxxx@qq.com>"

# 添加Tomcat
ADD ./apache-tomcat-9.0.91.tar.gz /usr/local/tomcat

# 添加javajdk
ADD ./jdk-11.0.2_linux-x64_bin.tar.gz /usr/local/jdk_11


# 配置java环境变量
ENV JAVA_HOME=/usr/local/jdk_11/jdk-11.0.2
ENV CLASSPATH=${JAVA_HOME}lib/dt.jar:${JAVA_HOME}lib/tools.jar

# 设置一个Tomcat环境变量
ENV CAT_HOME=/usr/local/tomcat/apache-tomcat-9.0.91

ENV PATH=$PATH:${JAVA_HOME}/bin:${CAT_HOME}/lib:${CAT_HOME}/bin

# 设置工作目录
WORKDIR ${CAT_HOME}

# #安装VIM
# RUN apt update && \
# apt-get install vim 

#配置端口
EXPOSE 8080

# 启动tomcat
ENTRYPOINT [ "catalina.sh","run" ]

CMD ["/bin/bash"]

开始build

root@jelly-linux:/home/jelly/test docker build . -t mytomcat:1.0  
[+] Building 0.2s (9/9) FINISHED                                                                                                                                  docker:default
 => [internal] load build definition from Dockerfile                                                                                                                        0.0s
 => => transferring dockerfile: 776B                                                                                                                                        0.0s
 => [internal] load metadata for docker.io/library/debian:latest                                                                                                            0.0s
 => [internal] load .dockerignore                                                                                                                                           0.0s
 => => transferring context: 2B                                                                                                                                             0.0s
 => [1/4] FROM docker.io/library/debian:latest                                                                                                                              0.0s
 => [internal] load build context                                                                                                                                           0.0s
 => => transferring context: 104B                                                                                                                                           0.0s
 => CACHED [2/4] ADD ./apache-tomcat-9.0.91.tar.gz /usr/local/tomcat                                                                                                        0.0s
 => CACHED [3/4] ADD ./jdk-11.0.2_linux-x64_bin.tar.gz /usr/local/jdk_11                                                                                                    0.0s
 => CACHED [4/4] WORKDIR /usr/local/tomcat/apache-tomcat-9.0.91                                                                                                             0.0s
 => exporting to image                                                                                                                                                      0.0s
 => => exporting layers                                                                                                                                                     0.0s
 => => writing image sha256:b0936fce56f463ad483551274b514454b987780cccc178a437d0a6bac922645c                                                                                0.0s
 => => naming to docker.io/library/mytomcat:1.0  

创建容器并启动


docker run -it -d --name mytomcat_test -p 8080:8080 mytomcat:1.0 
9dfd35be48d2ecbf5e09715fc9be2b3d4f7470bb7169de36d02bf8e3b99c42d8

3.1 遇到的问题

  1. dockerfile文件名称问题

    • 名字为Dockerfile(官方默认文件名称)时可以直接 "docker build . -t mytomcat:1.0" 其中文件名称可以忽略
    • 文件名称不是官方默认名称时使用-f指定文件名称。例如:文件名称为TomcatDockerfiledocker build -f TomcatDockerfile . -t mytomcat:1.0
  2. 容器启动后会自动关闭

    • dockerfile 文件中有ENTRYPOINT或CMD执行命令发生错误,可以通过docker logs 容器名称/id 来查看日志定位问题
    • 一个docker容器同时只能管理一个进程,这个进程退出后,容器也就退出了。例如上述例子中奖ENTRYPOINT [ "catalina.sh","run" ] 改为ENTRYPOINT [ "startup.sh","run" ]就会导致这个镜像所创建的容器启动后会关闭。因为这个容器管理了startup.sh启动进程,当这个教程执行完成,进程关闭,随后容器也关闭。
0

评论区