Dockerfile详解

Posted 鱼翔空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dockerfile详解相关的知识,希望对你有一定的参考价值。

什么是Dockerfile?

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

  • 固定格式;
  • 顺序执行(从上到下);
  • 通过docker build -f 来执行文件;
  • ‘#’为Dockerfile中的注释
  • Dockerfile镜像由只读层堆叠起来,每个层代表一个Dockerfile指令;
  • RUN 执行一条指令就新建一层,过多容易导致镜像过大

构建方式

经典构建

# 语法
docker build -f  具体dockerfile文件位置
docker build -t  指定存储新镜像的存储库和标签,-t 可以多个

示例:
# 使用当前目录的Dockerfile文件创建镜像,并打标签为yxkong/ubuntu:v1 
docker build -t yxkong/ubuntu:v1 .

# 使用远程的Dockerfile构建镜像
docker build github.com/creack/docker-firefox 

# 
docker build -f ./Dockerfile .

buildkit构建

18.09开始,docker添加的新的构建指令
构建方式

#在构建前必须设置环境变量
export DOCKER_BUILDKIT=1
# 然后执行build
docker build -f  具体dockerfile文件位置

带来的好处

  • 构建步骤优化(跳过已构建,直接执行未构建的)
  • 高效灵活的缓存(优先考虑缓存)
  • 并行构建独立的构建阶段;
  • 在构建之间仅增量传输构建上下文中已更改的文件;
  • 扩展了Dockerfile语法;

Dockerfile指令与结构

Dockerfile中支持的修改环境变量的指令

  • FROM 指定基准环境
  • ADD 将宿主的某个文件或目录挂到新建的镜像中(支持tar和url)
  • COPY 从宿主复制文件到新创建的镜像文件(主要是本地)
  • ENV 为新建的镜像指定环境变量
  • EXPOSE 设置对外开发的端口
  • LABEL 为新建的镜像添加元数据标签
  • STOPSIGNAL 发送容器退出的调用信号
  • USER 指定执行后续命令的用户和用户组
  • VOLUME 定义匿名数据卷
  • WORKDIR 设置工作目录
  • ONBUILD 用于延迟构建命令的执行

解析器指令

# 解析器指令(可选)主要用来提示解析器进行特殊处理,如果使用必须在第一行,不能重复,与后续必须空一格
# directive=value

#用于定义Dockerfile中的转义符,在windows中推荐用别的替换
#escape=\\

#18.09版本后使用
# 构建时使用什么样的版本镜像构建
# syntax=[remote image reference]
#表示不断更新最新的1.x.x次要和布丁版本
#syntax=docker/dockerfile:1 
#表示不断更新1.2.x的最新吧版本,一但1.3.0版本发布就停止更新
#syntax=docker/dockerfile:1.2
#表示使用固定的1.2.1版本
#syntax=docker/dockerfile:1.2.1

FROM 指令

表示定制的镜像都是以FROM指令指定的镜像作为基准镜像,后续的构建指令运行于此基准镜像。

语法:
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

示例
FROM ubuntu:18.04

ADD 指令

ADD指令从文件、目录或远程文件 URL 复制文件,并将它们添加新构建的镜像中。

  • 可以支持远程操作
  • tar 包的话,会解压
  • src可以指定多个资源
  • 支持Go的filepaht.Match规则;
语法:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

示例:
# 将以hom开头的文件复制到镜像中的mydir目录中
ADD hom* /mydir/
# 将所有匹配到的hom*.txt文件复制到镜像中的mydir目录
ADD hom?.txt /mydir/
# 将test.txt复制到相对路径<WORDDIR>/relativeDir中
ADD test.txt relativeDir/

# 复制到镜像的文件增加权限组或用户,可以是数字也可以是具体的名称
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/

#从远程复制foobar 到容器的/下的foobar目录
ADD http://example.com/foobar /
#如果ADD 后面跟目录,则将这个目录拷贝到容器中
ADD  myapp  /myapp

COPY 指令

COPY指令从文件或目录中复制内容到新镜像指定的中。

  • 本地
  • src 可指定多个资源
  • 支持Go的filepaht.Match规则;
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

和ADD类似

ENV 指令

ENV指令将环境变量设置为 value 。

#语法
ENV <key>=<value> ...

# 示例:
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\\ The\\ Dog
ENV MY_CAT=fluffy

# run的时候可以更改
docker run --env <key>=<value>。

EXPOSE 指令

EXPOSE指令通知 Docker 容器在运行时侦听指定的网络端口。可以指定端口是监听TCP还是UDP,如果不指定协议,默认为TCP。

#语法
EXPOSE <port> [<port>/<protocol>...]

示例:
EXPOSE 80/tcp
EXPOSE 80/udp
EXPOSE 80 443

docker run -p 80:80/tcp -p 80:80/udp

LABEL 指令

LABEL指令新构建的镜像添加元数据。lable是键值对。要在LABEL值中包含空格,可以在命令行解析中一样使用引号和反斜杠

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

示例:1.10之前可以多个label
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \\
that label-values can span multiple lines."

LABEL multi.label1="value1" multi.label2="value2" other="value3"

LABEL multi.label1="value1" \\
      multi.label2="value2" \\
      other="value3"

USER 指令

USER指令用于为打包的镜像,运行时指定用户名和用户组,主要使用USER场景的指令有RUN/CMD/ENTRYPOINT

语法:
USER <user>[:<group>]
USER <UID>[:<GID>]

示例:
USER www:www

WORKDIR

主要为以下指令(RUN/CMD/ENTRYPOINT/COPY/ADD)设置工作目录,可以是相对路径或绝对路径,如果多个,将继承

语法:
WORKDIR /path/to/workdir

示例:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最终的工作目录为/a/b/c

ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
最终的工作目录是/path/$DIRNAME

ARG 指令

ARG指令用于定义变量,用户可以在docker build时通过–build-arg =传递给构建器。

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

FROM ubuntu
ARG CONT_IMG_VER #(这块可以给默认值)
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER

docker build --build-arg CONT_IMG_VER=v2.0.1 

docker中有一些预定义的ARG变量

  • HTTP_PROXY
  • http_proxy
  • HTTPS_PROXY
  • https_proxy
  • FTP_PROXY
  • ftp_proxy
  • NO_PROXY
  • no_proxy

VOLUME 指令

用于在镜像中创建一个挂载点目录,以挂载宿主机上的目录

  • 在windows中,必须是一个不存在或空的目录,也不能在C盘
  • 挂载可以是JSON格式的
  • 主机目录依赖于主机
语法:
VOLUME ["/data"]

示例:
FROM ubuntu
RUN mkdir /myvol #创建宿主机中挂载的目录
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol #挂载目录

ONBUILD 指令

通过onbuild指令,将一个触发器指令添加到镜像中,以便该镜像作为基础构建下一层时执行。

执行流程

  • 遇到onbuild指令时,build会向正在构建的image的元数据中添加触发器;
  • 构建结束,可以用docker inspect命令检查
  • 当FROM该image时,会触发onbuild添加的触发器,并按照注册顺序执行
  • 执行一次后就清除了
ONBUILD <INSTRUCTION>

示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

RUN 指令

RUN执行命令,并生成一层镜像,生成image提交并用于下一次构建。

  • 每条RUN都是在当前基础镜像执行,并提交新镜像
  • 尽量减少RUN,一个RUN创建一层;
  • 如果有多个RUN,使用 && 符号链接命令,只会创建一层
  • RUN在docker build阶段执行
语法:
RUN <command>(shell形式,命令在 shell 中运行,默认/bin/sh -c在 Linux 或cmd /S /CWindows 上)
RUN ["executable", "param1", "param2"](执行形式,必须用双引号)

示例:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
RUN ["/bin/bash", "-c", "echo hello"]

CMD 指令

类似于RUN命令

  • CMD 在docker run 阶段执行
  • 存在多个CMD,只有最后一个生效
语法:
CMD ["executable","param1","param2"](exec形式,这是首选形式)
CMD ["param1","param2"](作为ENTRYPOINT 的默认参数)
CMD command param1 param2(外壳形式)

编写Dockerfile

指南和建议

  • Use multi-stage builds 使用多阶段构建
  • 不要安装不必要的包
  • 解耦应用程序
  • 尽量减少层数 (RUN/COPY/ADD会创建image层)
  • 对多行参数进行排(避免重复)
  • 利用构建缓存

v1版本


https://hub.docker.com/_/centos?tab=tags&page=1&ordering=last_updated

#基于centos7安装nginx
# Base images 基础镜像
FROM centos:7

#MAINTAINER 维护者信息
MAINTAINER yxkong 5ycode@sina.com 

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  文件放在当前目录下,拷过去会自动解压
ADD nginx-1.16.1.tar.gz /usr/local/  
ADD epel-release-latest-7.noarch.rpm /usr/local/  

#RUN 执行以下命令 
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm && yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all && useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.8.0 

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install && echo "daemon off;" >> /etc/nginx.conf
# 可以设置环境变量,对外可以直接使用nginx
ENV PATH /usr/local/nginx/sbin:$PATH
#EXPOSE 映射端口
EXPOSE 80

#CMD 运行以下命令
CMD ["nginx"]

执行目录文件
Dockerfile
epel-release-latest-7.noarch.rpm
nginx-1.16.1.tar.gz

docker yxk$ docker build -f ./Dockerfile -t yxkong/nginx:v1 .
[+] Building 31.3s (11/11) FINISHED                                                                                           
 => [internal] load build definition from Dockerfile                                                                     0.0s
 => => transferring dockerfile: 1.08kB                                                                                   0.0s
 => [internal] load .dockerignore                                                                                        0.0s
 => => transferring context: 2B                                                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:7                                                              2.8s
 => [1/6] FROM docker.io/library/centos:7@sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e        0.0s
 => [internal] load build context                                                                                        0.0s
 => => transferring context: 444B                                                                                        0.0s
 => CACHED [2/6] ADD nginx-1.16.1.tar.gz /usr/local/                                                                     0.0s
 => CACHED [3/6] ADD epel-release-latest-7.noarch.rpm /usr/local/                                                        0.0s
 => CACHED [4/6] RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm && yum install -y wget lftp gcc gcc-c++ make   0.0s
 => [5/6] WORKDIR /usr/local/nginx-1.16.1                                                                                0.0s
 => [6/6] RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make   27.5s
 => exporting to image                                                                                                   0.8s
 => => exporting layers                                                                                                  0.8s
 => => writing image sha256:df0f9bd5c26a2c825e610db1c19cd157afe7bb78bc0cfd926b93855a0402df1c                             0.0s 
 => => naming to docker.io/yxkong/nginx:v1                         0.0s

#通过images查看
docker yxk$ docker images
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
yxkong/nginx   v1        df0f9bd5c26a   10 minutes ago   369MB
#通过inspect命令查看
docker yxk$ docker inspect df0f9bd5c26a
[
    {
        "Id": "sha256:df0f9bd5c26a2c825e610db1c19cd157afe7bb78bc0cfd926b93855a0402df1c",
        "RepoTags": [
            "yxkong/nginx:v1"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "buildkit.dockerfile.v0",
        "Created": "2021-07-12T07:48:37.0883337Z",
        "Container": "",
        "ContainerConfig": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": null,
            "Cmd": null,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "DockerVersion": "",
        "Author": "yxkong 5ycode@sina.com",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/nginx/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "nginx"
            ],
            "ArgsEscaped": true,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "/usr/local/nginx-1.16.1",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201113",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 369358118,
        "VirtualSize": 369358118,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/jvg0utv0k2o8a6g8xkc3s1vzb/diff:/var/lib/docker/overlay2/wk2x19rfkes9mfbysl8s9r2kj/diff:/var/lib/docker/overlay2/91w8e42eapjzhhj0fvj65tf5z/diff:/var/lib/docker/overlay2/zkdux7by7x4sfj7jiud88frwm/diff:/var/lib/docker/overlay2/8429756e5d996a34977fd2bef5936a34b25c3afffd98b51d62f16081ec9d8f4f/diff",
                "MergedDir": "/var/lib/docker/overlay2/ukaikrf2j0hz2z7n956x40wgt/merged",
                "UpperDir": "/var/lib/docker/overlay2/ukaikrf2j0hz2z7n956x40wgt/diff",
                "WorkDir": "/var/lib/docker/overlay2/ukaikrf2j0hz2z7n956x40wgt/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
                "sha256:ebad2bdc79dce1588044a87b646407fb40e6ed4ffb92a6aae3b1c45a8679123a",
                "sha256:0bfcb95f76d8fb541c874ca3d205a37075bcf0c3dce65e80b976e38364a41ba7",
                "sha256:69dcde0bdd1ee35d1b18fa2c83772db09af04282f113867bcd507c346f2e2310",
                "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
                "sha256:af7571d28fc377a90dabf6f400675b7e8a30292dbfafd658dd6157e894d0b7b7"
            ]
        },
        "Metadata": {
            "LastTagTime": "2021-07-12T07:48:37.932162Z"
        }
    }
]


启动容器:
docker run -d -p9000:80 yxkong/nginx:v1 nginx -g "daemon off;"

#查看nginx,启动成功了
docker yxk$ curl 127.0.0.1:9000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

v2版本

#基于centos7安装nginx
# Base images 基础镜像
FROM centos:7

#MAINTAINER 维护者信息
MAINTAINER yxkong 5ycode@sina.com 

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  文件放在当前目录下,拷过去会自动解压
ADD nginx-1.16.1.tar.gz /usr/local/  
ADD epel-release-latest-7.noarch.rpm /usr/local/  

#RUN 执行以下命令 
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm && yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all && useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.8.0 

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install && echo "daemon off;" >> /etc/nginx.conf
# 可以设置环境变量,对外可以直接使用nginx
ENV PATH /usr/local/nginx/sbin:$PATH
#EXPOSE 映射端口
EXPOSE 80

#CMD 运行以下命令
CMD /bin/sh -c 'nginx -g "daemon off;"'

重新构建

docker yxk$ docker build -t yxkong/nginx:v2 .
[+] Building 2.9s (11/11) FINISHED                                                                                            
 => [internal] load build definition from Dockerfile                                                                     0.0s
 => => transferring dockerfile: 1.13kB                                                                                   0.0s
 => [internal] load .dockerignore                                                                                        0.0s
 => => transferring context: 2B                                                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:7                                                              2.7s
 => [internal] load build context                                                                                        0.0s
 => => transferring context: 444B                                                                                        0.0s
 => [1/6] FROM docker.io/library/centos:7@sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e        0.0s
 => CACHED [2/6] ADD nginx-1.16.1.tar.gz /usr/local/                                                                     0.0s
 => CACHED [3/6] ADD epel-release-latest-7.noarch.rpm /usr/local/                                                        0.0s
 => CACHED [4/6] RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm && yum install -y wget lftp gcc gcc-c++ make   0.0s
 => CACHED [5/6] WORKDIR /usr/local/nginx-1.16.1                                                                         0.0s
 => CACHED [6/6] RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre &&  0.0s
 => exporting to image                                                                                                   0.0s
 => => exporting layers                                                                                                  0.0s
 => => writing image sha256:0db1941cd714d545807ab3a8b9ffa22901f846a568d6f04c89c3ddb792dff598                             0.0s
 => => naming to docker.io/yxkong/nginx:v2                                                                               0.0s

docker yxk$ docker images
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
yxkong/nginx   v2        0db1941cd714   3 hours ago    369MB
yxkong/nginx   v1        df0f9bd5c26a   3 hours ago    369MB

docker yxk$ docker run -d -p:9002:80 yxkong/nginx:v2
a81aad49e53c2c4342d781ef29f1f1447dafec5f7a87f83d257e7997e6ea4a2c
docker yxk$ docker ps -l
CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                  NAMES
a81aad49e53c   yxkong/nginx:v2   "/bin/sh -c '/bin/sh…"   6 seconds ago   Up 5 seconds   0.0.0.0:9002->80/tcp   interesting_kalam

如果觉得对你有帮助,请关注公众号:5ycode,后续会不断更新哦

公众号图片

以上是关于Dockerfile详解的主要内容,如果未能解决你的问题,请参考以下文章

Dockerfile使用方法详解

Dockerfile详解

dockerfile详解

Dockerfile详解

Dockerfile详解

Dockerfile文件详解