07_Dockerfile

2021-05-09  本文已影响0人  单v纯微笑

参考资料

Dockerfile是什么?

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

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

注:编写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的区别:

说明:

  • 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对比:

说明:构建命令 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 [--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
上一篇下一篇

猜你喜欢

热点阅读