Dockerfile
-
Dockerfile是用于构建docker镜像的文件
-
Dockerfile包含了构建镜像所需要的指令
-
Dockerfile有特定的语法规则
-
通过build命令构建Dockerfile的镜像
build 将Dockerfile构建为镜像
docker build -t 镜像名 Dockerfile的路径(当前目录可以用.代替)
-f 参数可以指定文件,也就是说不使用Dockerfile名称也可以
常用指令
指令 | 功能 |
---|---|
FROM | 构建镜像基于哪个镜像 |
MAINTAINER | 镜像维护者姓名或邮箱地址 |
RUN | 构建镜像时运行的指令 |
CMD | 运行容器时执行的shell环境 |
VOLUME | 指定容器挂载点到宿主机自动生成的目录或其他容器 |
USER | 为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户 |
WORKDIR | 为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录 |
HEALTHCHECH | 健康检查 |
ARG | 构建时指定的一些参数 |
EXPOSE | 声明容器的服务端口(仅仅是声明) |
ENV | 设置容器环境变量 |
ADD | 拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压 |
COPY | 拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能 |
ENTRYPOINT | 运行容器时执行的shell命令 |
Dockerfile是忽略大小写的,但是一般使用大写
RUN
RUN有两个方式,一种是shell形式,一种是exec形式,shell形式相当于直接在shell中执行命令,exec形式一般是需要参数的时使用。
shell形式
RUN 执行的命令
RUN echo "flag{test_flag}" > /flag
在 Shell 形式下,Docker 会使用容器中指定的 shell(默认为/bin/sh -c
)来执行命令。
Shell 形式的优点是可以使用通常在命令行中使用的 Shell 特性,例如管道、重定向等。它可以让你轻松地在容器内运行复杂的命令。但是,它也有一些缺点。由于每个命令都会创建新的 shell 进程,因此可能会增加镜像的层数并导致构建缓慢。
exec形式
RUN ["可执行文件", "参数1", "参数2"]
RUN ["./test.php", "dev", "offline"]
shell形式可以使用\来进行命令间的换行,便于一个RUN指令来执行多条命令,如:
RUN sed -i 's/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/mirrors.tuna.tsinghua.edu.cn\/ubuntu\//g' /etc/apt/sources.list && \
sed -i '/security/d' /etc/apt/sources.list && \
apt-get update -y && \
apt-get -yqq install supervisor mariadb-server apache2 php5 libapache2-mod-php5 \
php5-mysql php5-mcrypt ssh && \
apt-get install php5-gd -y && \
service apache2 restart && \
# config
sed -i "154s/Indexes//" /etc/apache2/apache2.conf && \
sed -i "165s/Indexes//" /etc/apache2/apache2.conf && \
/etc/init.d/apache2 start && \
RUN指令会在当前镜像的顶部添加了一个新的层,为了减小体积,尽量把指令放在一个RUN里面
COPY和ADD
COPY和ADD命令都用于将文件和目录从主机复制到容器中。
区别如下:
- ADD命令支持自动解压缩压缩文件(例如.tar、.gzip、.bz2等)到目标路径,CPOY不支持自动解压
- ADD命令可以从URL下载文件,COPY不支持远程下载
- 相对于COPY命令来讲,ADD功能更多,但是会导致docker构建变慢
对于目录来讲,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身
COPY
COPY <源路径> <目标路径>
COPY html/ /var/www/html/ #将本地html目录的内容复制到/var/www/html目录里面
COPY index.php /var/www/html/index.php #将本地index.php 复制进web目录内
ADD
ADD <源路径> <目标路径>
ADD http://example.com/file.tar.gz /usr/src/ #将file.tar.gz的压缩文件从指定URL下载到容器中的/usr/src/目录,并自动解压缩
ADD html.tar.gz /var/www/ #将html.tar.gz解压缩到/var/www/目录内
WORKDIR
切换工作目录,如果目录不存在,则创建一个新的目录,并且后面执行的操作,都在当前目录内执行。
- 它可以多次在Dockerfile中使用,每次使用将覆盖之前的设置,以最后一次设置为准。
- 如果指定的目录路径不存在,Docker将自动创建它。
WORKDIR
指令可以接受绝对路径或相对于前一个WORKDIR
指令设置的路径。
WORKDIR /app
#这个命令将在容器中设置工作目录为/app。之后的命令将在这个目录下执行
ARG和ENV
ENV指令和ARG指令都用于设置环境变量
ENV
ENV指令用于设置环境变量的值。它的语法如下:
ENV <key>=<value>
ENV <key1>=<value1> <key2>=<value2> ...
其中,<key>
是环境变量的名称,<value>
是环境变量的值。
ENV指令的一些特点:
- 它将在构建镜像的过程中设置环境变量,并在容器运行时可用。
- 可以在Dockerfile中的任何位置使用ENV指令。
- 通过在后续命令中使用
$<key>
的形式,可以引用已设置的环境变量。
ARG
ARG指令用于定义构建参数,它们类似于变量。ARG指令的语法如下:
ARG <key>=<default>
其中,<key>
是参数的名称,<default>
是参数的默认值。
ARG指令的一些特点:
- 它是在构建镜像的过程中传递参数给Docker引擎的一种机制。
- 它可以用于在构建过程中传递临时变量,但不会被包含在最终镜像中。
- 可以在Dockerfile中的任何位置使用ARG指令。
- ARG指令的值可以通过
--build-arg
选项从构建命令行传递。
使用ENV和ARG指令可以灵活地设置环境变量和构建参数,使得Docker镜像的构建过程更加可配置和可重复。ENV指令用于设置环境变量的值,而ARG指令用于传递构建参数给Docker引擎。
CMD
CMD命令用于指定在容器启动时要执行的默认命令,CMD命令的目的是为了设置容器的默认行为。
CMD指令有三个格式
- shell格式
- exec格式
- ENTRYPOINT 结合 CMD
CMD和RUN的区别:
- CMD 在docker run 时运行。
- RUN 是在 docker build。
- CMD只能执行一条,RUN可以执行多条
使用CMD命令时的一些注意事项:
- 如果在Dockerfile中使用了多个CMD命令,只有最后一个CMD命令会生效。
- 如果用户在运行容器时提供了命令行参数,它们将覆盖CMD指定的默认命令。
- CMD命令通常用于指定容器启动时的默认应用程序或服务,但用户仍然可以通过在
docker run
命令中提供命令行参数来覆盖默认行为。
ENTRYPOINT
ENTRYPOINT
是Dockerfile中的一条指令,用于指定容器启动时要执行的命令或可执行文件。与CMD
指令不同,ENTRYPOINT
指令不会被覆盖,而是始终作为容器的入口点
ENTRYPOINT也支持shell格式和exec格式
如果在Dockerfile中同时存在
ENTRYPOINT
和CMD
指令,CMD
指令提供的内容将作为ENTRYPOINT
指令的默认参数。这样,在运行容器时可以通过附加参数来覆盖CMD
指令提供的默认参数
如:
ENTRYPOINT ["echo"]
CMD ["hello Docker!"]
这时cmd的指令的内容会当作ENTRYPOINT 的参数执行,执行的命令为 echo hello Docker!
使用ENTRYPOINT
的一个常见用例是在容器中运行可执行文件,使容器成为一个可执行的应用程序。例如,假设你的镜像中有一个名为myapp
的可执行文件,你可以使用以下方式指定:
ENTRYPOINT ["/path/to/myapp"]
这样,在容器启动时,myapp
将成为容器的入口点,并开始执行。
EXPOSE
这个指令实际上并没啥用,只是声明一下,这个镜像需要哪些端口,如果需要端口映射的话,就是docker run 后面加-p参数
.dockerignore文件
.dockerignore
文件是一个用于指定在构建镜像和上下文传输中要忽略的文件和目录的规则文件,通过在.dockerignore
文件中明确排除不必要的文件和目录,可以减小构建上下文的大小,减少构建传输的数据量,从而提高构建性能和效率,以及保护隐私,
更多参考:http://t.csdn.cn/wcn3P
多阶段构建
dockerfile的多阶段构建是值,一个dockerfile可以有多个from指令,从而在构建过程中使用多个基础镜像,多阶段构建的主要优势是减小镜像的大小,去除构建过程中不必要的依赖和文件。这有助于减少网络传输和存储开销,并提高容器的性能和安全性。
使用多阶段构建时,只有最后一个阶段的镜像将作为最终的Docker镜像。之前的阶段构建的临时文件和依赖将被丢弃,不会包含在最终镜像中,因此可以显著减小镜像的大小。
使用场景:
在不使用多阶段构建的情况下,要么把代码文件提前编译好,放在容器里面运行即可,要么在容器中编译,对于第一种情况来讲,提前打包成二进制文件过于麻烦,也不利于维护,第二种情况,放在容器中编译,但是容器只是负责运行程序,多了一些可以省略的功能(编译代码),镜像体积也会变大,所以使用多阶段构建,可以减小镜像体积的冗余又便于代码维护。
FROM gcc:9.4 AS builder
COPY hello.c /src/hello.c
WORKDIR /src
RUN gcc --static -o hello hello.c
FROM alpine:3.13.5
COPY --from=builder /src/hello /src/hello
ENTRYPOINT [ "/src/hello" ]
CMD []
使用COPY --from=<stage>
指令从之前的构建阶段中复制所需的文件或目录到当前阶段。这样可以选择性地将所需的文件从一个阶段复制到另一个阶段