07_Dockerfile

参考资料

Dockerfile是什么?

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

大白话:可用通过代码构建镜像,写的代码文件就是Dockerfile。

  • Dockerfile构建镜像流程:
    • 准备构建镜像需要的材料 -> 编写Dockerfile文件 -> 使用docker build构建镜像。

注:编写Dockerfile需要一定的Linux基础,或者知道一些常用的Linux指令。

常用指令

常用指令表

分类指令说明
构建指令FROM设置基础镜像
WORKDIR指定工作目录(类似cd到指定目录)
LABEL设置元数据
VOLUME定义匿名数据卷
运行指令RUN编译时运行后面的命令(类似在shell中执行命令)
CMD启动时运行后面的命令,会被启动参数覆盖
ENTRYPOINT与CMD类似,但不会被启动时参数覆盖
参数指令ENV设置环境变量
ARG设置局部变量
复制指令COPY拷贝文件,不解压
ADD添加文件,默认解压

常用指令详解

构建指令
FROM

设置基础镜像。有效的Dockerfile必须从FROM指令开始。

  • 语法
FROM [--platform=<platform>] <image> [AS <name>]
# 或
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
# 或
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
  • 示例
# 以centos:latest作为基础镜像
FORM centos
WORKDIR

指定工作目录。

  • 语法
WORKDIR <容器内目录>

说明:WORKDIR可以在Dockerfile中多次使用,如果提供了相对路径,则它将相对于上一条WORKDIR指令的路径。例如:

WORKDIR /a
WORKDIR b
WORKDIR c
# 输出:/a/b/c
RUN pwd
  • 示例
# 设置工作目录
WORKDIR /path/to/workdir

# 输出:/path/to/workdir
RUN pwd
LABEL

标签。将元数据添加到镜像,一个镜像可以包含多个标签。

要查看镜像的标签,请使用docker image inspect命令。可以使用该--format选项仅显示标签。

  • 语法
LABEL <key>=<value> <key>=<value> <key>=<value> ...

说明:在Docker 1.10之前的版本中,为减小镜像大小,尽可能的把多个标签写到一行,新版本会自动合并。

  • 示例
# 添加维护者信息
LABEL maintainer="vv_lin<vv_lin@123.com>"

# 查看标签
docker image inspect --format='' myimage
VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

在启动容器 docker run的时候,我们可以通过 -v 参数修改挂载点。

  • 语法
VOLUME ["<路径1>", "<路径2>"]
# 或
VOLUME <路径1> <路径2>
  • 示例
# 在容器内部创建myvol目录
RUN mkdir /myvol

# 将myvol目录以匿名方式挂载到宿主机
VOLUME /myvol

注意:这里说的匿名挂载是站在宿主机角度看为匿名,容器内部的目录还是具名的。

运行指令
RUN

用于执行后面跟着的命令,只在编译时生效。

  • 语法
# 执行命令,类似打开Linux的/bin/sh(或Window的cmd),并执行命令。
RUN <command>
# 或
RUN ["可执行文件", "参数1", "参数2"]
  • 示例
# 1.使用yum安装wget
RUN yum install wget
# 2.下载tomcat包
RUN wget https://mirrors.cnnic.cn/apache/tomcat/tomcat-8/v8.5.57/bin/apache-tomcat-8.5.57.tar.gz
# 3.解压tomcat
RUN tar -xvf apache-tomcat-8.5.57.tar.gz

# 或
# 执行HelloWorld.sh
# 类似 RUN ./HelloWorld.sh aaa bbb
RUN ["./HelloWorld.sh", "aaa", "bbb"]

注意:Dockerfile 的指令每执行一次都会在 Docker 镜像上新建一层。过多无意义的层,会造成镜像膨胀过大。以 && 符号连接命令,这样执行后,只会创建 1 层镜像。如下:

RUN yum install wget \
	&& wget https://mirrors.cnnic.cn/apache/tomcat/tomcat-8/v8.5.57/bin/apache-tomcat-8.5.57.tar.gz\
	&& tar -xvf apache-tomcat-8.5.57.tar.gz
CMD

类似于 RUN 指令,用于运行程序。

RUNCMD的区别:

  • RUN 是在docker build时运行。
  • CMD 在docker run时运行。

说明:

  • Dockerfile中只能有一条CMD指令,如果有多条,只有最后一条生效
  • CMD 指令参数可被 docker run命令行参数覆盖。
  • 语法
CMD ["可执行文件", "参数1", "参数2"]
# 或
# 该方式作为ENTRYPOINT的默认参数
CMD ["参数1", "参数2"]
# 或
CMD <命令> "参数1", "参数2"

示例

# 执行HelloWorld.sh
CMD ["./HelloWorld.sh", "aaa", "bbb"]
ENTRYPOINT

类似CMD指令,但正常情况下不会被docker run 的命令行参数所覆盖。

如果非要覆盖,可以使用docker run--entrypoint 选项强制覆盖。

说明:如果 Dockerfile 中如果存在多个ENTRYPOINT 指令,仅最后一个生效

  • 语法
ENTRYPOINT ["可执行文件", "参数1", "参数2"]
# 或
ENTRYPOINT <命令> "参数1", "参数2"
  • 示例
# 假设通过Dockerfile 构建了nginx:test镜像。
# Dockerfile如下:
FROM nginx

# 定参
ENTRYPOINT ["nginx", "-c"]
# 变参
CMD ["/etc/nginx/nginx.conf"]
  1. 不传参运行
# 命令
docker run nginx:test

# =>
# 容器内会默认运行以下命令(从CMD设定的参数取值)
nginx -c /etc/nginx/nginx.conf
  1. 传参运行
# 命令
docker run nginx:test -c /etc/nginx/nginx-custom.conf

# =>
# 容器内会默认运行以下命令(使用外部传递的参数)
nginx -c /etc/nginx/nginx-custom.conf
参数指令
ENV

设置环境变量。

若定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

  • 语法
ENV <key> <value>
# 或
ENV <key>=<value> ...
  • 示例
# 设置JAVA_HOME
ENV JAVA_HOME=/usr/lib/jvm/jdk8

# 使用
ENV PATH=$JAVA_HOME/bin:$PATH
ARG

构建参数,与 ENV类似。

ENVARG对比:

  • ENV在Dockerfile和镜像中均可用;
  • ARG只在Dockerfile中可用。

说明:构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

  • 语法
ARG <name>[=<default value>]
  • 示例
# 设置参数
ARG hello_world=helloWorld!!

# 使用
RUN echo $hello_world
复制指令
COPY

复制,从上下文目录中复制文件或者目录到容器里指定路径。

  • 语法
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
#或
# 包含空格的路径需要使用该形式
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

如果<源路径1>是目录,则将复制目录的整个内容,目录本身不被复制,仅其内容被复制。

<src>可以包含通配符。

注意:--chown仅在用于构建Linux容器的Dockerfiles上受支持,而在Windows容器上不起作用。

  • 示例
# 1. 复制所有以“hom”开头的文件到容器的/mydir/目录下
COPY hom* /mydir/

# 2. "?"被替换为任何单个字符,例如“ home.txt”。
COPY hom?.txt /mydir/

# 3. 复制到相对路径中:<WORKDIR>/relativeDir/
COPY test.txt relativeDir/
ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY),功能也类似。

不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。

  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

  • 语法

ADD [--chown=<user>:<group>] <源路径1>... <目标路径>
# 或
# 包含空格的路径需要使用该形式
ADD [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

如果<源路径1>是目录,则将复制目录的整个内容,目录本身不被复制,仅其内容被复制。

<src>可以包含通配符。

注意:

  • --chown仅在用于构建Linux容器的Dockerfiles上受支持,而在Windows容器上不起作用。
  • ADD可以通过远程文件URL添加文件。
  • 示例
# 1. 复制所有以“hom”开头的文件到容器的/mydir/目录下
ADD hom* /mydir/

# 2. "?"被替换为任何单个字符,例如“ home.txt”。
ADD hom?.txt /mydir/

# 3. 复制到相对路径中:<WORKDIR>/relativeDir/
ADD test.txt relativeDir/

小试牛刀

通过Dockerfile构建一个最简单的镜像

  1. 通过Dockerfile构建一个最简单的镜像。
# 1. 编写Dockerfile文件
vim Dockerfile

# Dockerfile
FROM centos
RUN echo "Hello World!!" > hello_world.txt
  1. 根据Dockerfile构建镜像。
# 参数说明(注意后面有个“.”):
# -t mycentos:test 指定构建镜像的名称和标签
# . 指定镜像构建过程中的上下文环境的目录
docker build -t mycentos:test .

# 输出
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 0d120b6ccaa8
Step 2/2 : RUN echo "Hello World!!" > hello_world.txt
 ---> Running in f78e091a6c89
Removing intermediate container f78e091a6c89
 ---> efa3df984c1c
Successfully built efa3df984c1c
Successfully tagged mycentos:test
  1. 启动镜像。
# 查看所有镜像
docker images
# 使用交互模式运行镜像
docker run -it --name mycentos mycentos:test bash

# 在容器中查看目录结构
ls
# 输出结果,能看到hellow_world.txt
bin  dev  etc  hello_world.txt	home  lib  lib64  lost+found  media  mnt  opt  proc  root  run	sbin  srv  sys	tmp  usr  var

# 查看文件内容
[root@a5b50d7fa748 /]# cat hello_world.txt
# 输出结果
Hello World!!

构建镜像参数后面的".",的意思

参考资料

当构建的时候,由用户指定构建镜像的上下文路径,而docker build会将这个路径下所有的文件都打包上传给 Docker引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了。

比如:

Dockerfile中的COPY ./package.json /project,其实拷贝的并不是本机目录下的package.json文件,而是Docker引擎中展开的构建上下文中的文件,所以如果拷贝的文件超出了构建上下文的范围,Docker引擎 是找不到那些文件的。

.dockerignore 文件的作用

参考资料:

《.dockerignore 文件的作用》

.dockerignore 文件中指定在传递给 docker引擎 时需要忽略掉的文件或文件夹。

比如:

在前端项目中,node_modules 文件夹在构建镜像过程中如果用不到,但是又异常庞大,那么向 docker引擎 传递其实是并没有必要的,这个时候就可以将 node_modules 文件夹加入 .dockerignore 文件中。

通过Dockerfile构建Tomcat

  1. 使用vim编写Dockerfile
vim Dockerfile
# Dockerfile
# jdk + tomcat
FROM centos

# 添加标记
LABEL maintainer="vv_lin<vv_lin@123.com>"

# 创建目录
RUN mkdir -p /usr/local/java \
	&& mkdir -p /usr/local/tomcat

# 设置工作空间
WORKDIR /usr/local

# 添加jdk
ADD jdk-8u202-linux-x64.tar.gz /usr/local/java/

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

# 设置环境变量
# 设置java环境变量
ENV JAVA_HOME=/usr/local/java/jdk1.8.0_202
ENV CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
# 设置tomcat环境变量
ENV CATALINA_HOME=/usr/local/tomcat/apache-tomcat-8.5.57
# 追加到PATH中
ENV PATH=$CATALINA_HOME/bin:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH

# 挂载匿名磁盘
VOLUME ["/usr/local/tomcat/apache-tomcat-8.5.57/logs", "/usr/local/tomcat/apache-tomcat-8.5.57/webapps"]

# 声明端口
EXPOSE 8080

# 启动
ENTRYPOINT ["catalina.sh", "run"]
  1. 编译成镜像
# 注意后面的“.”
docker build -t mytomcat .
# 或
docker build -f Dockerfile -t mytomcat:latest .
# 或
docker build -f Dockerfile -t mytomcat .

说明:docker build默认读取名为Dockerfile,如果是其他名称,则需要使用-f <Dockerfile文件名>指定文件名。

  1. 启动镜像
docker run -it --name mytomcat -p 8080:8080 mytomcat bash
  1. 通过浏览器访问,发现正常
  2. 查看挂载的目录
# 1. 查看所有挂载的目录
docker volume ls

# 输出
DRIVER              VOLUME NAME
local               0ea11ee5a377263e6a62a61afdd554f12f3f61e0e69fb603794363637668f270
local               1c2c7f656fdea4a16471e9c066353d7b3423614f4dc6b9abfd3e8a0e6f163b5b
local               28ad647f7dc23b3a04c96f8ba8eeca08c0766a1b2669bc42162e43ddcd585164
local               85a5ba99cf1ca1a52e745685bede94be81f6d79e44ef108192d2d27817460331
local               9438df2f42126d5ac47a63916ae888f6c2d0dfb65e65634df6916c55ad231e0d
local               26817b63add34160593e512468510fbfa0e1d3326ef826c01f8d4a1a3d10ce8c
local               testvolume

# 2. 查看挂载目录的元数据
docker volume inspect 1c2c7f656fdea4a16471e9c066353d7b3423614f4dc6b9abfd3e8a0e6f163b5b

# 输出
[
    {
        "CreatedAt": "2020-08-19T17:00:07+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/1c2c7f656fdea4a16471e9c066353d7b3423614f4dc6b9abfd3e8a0e6f163b5b/_data",
        "Name": "1c2c7f656fdea4a16471e9c066353d7b3423614f4dc6b9abfd3e8a0e6f163b5b",
        "Options": null,
        "Scope": "local"
    }
]

# 4. 查看挂载目录的内容
ls /var/lib/docker/volumes/1c2c7f656fdea4a16471e9c066353d7b3423614f4dc6b9abfd3e8a0e6f163b5b/_data

# 输出
docs  examples  host-manager  manager  ROOT
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值