赞
踩
前言:Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
在一个文件夹中,如果有一个名字为 Dockfile 的文件,其内容满足语法要求,在这个文件夹路径下执行命令:docker build --tag name:tag .
,就可以按照描述构建一个镜像了。name 是镜像的名称,tag 是镜像的版本或者是标签号,不写的话默认为 lastest。注意后面有一个空格和点。
FROM
指令用于指定其后构建新镜像所使用的基础镜像。FROM
指令必是 Dockerfile
文件中的首条命令,启动构建流程后,Docker
将会基于该镜像构建新镜像,FROM
后的命令也会基于这个基础镜像。FROM <image>
# 或
FROM <image>:<tag>
# 或
FROM <image>:<digest>
FROM
指定的镜像,可以是任何有效的基础镜像。FROM
有以下限制:
FROM
必须 是 Dockerfile
中第一条非注释命令。Dockerfile
文件中创建多个镜像时,FROM
可以多次出现。只需在每个新命令 FROM
之前,记录提交上次的镜像 ID。tag
或 digest
是可选的,如果不使用这两个值时,会使用 latest
版本的基础镜像。RUN
指令在镜像的构建过程中执行特定的命令,并生成一个中间镜像。shell
格式:
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
exec
格式:
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
RUN
命令将在当前 image
中执行任意合法命令并提交执行结果。命令执行提交后,就会自动执行 Dockerfile
中的下一个指令。RUN
指令和生成提交是符合 Docker
核心理念的做法。它允许像版本控制那样,在任意一个点,对 image
镜像进行定制化构建。RUN
指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定 --no-cache
参数,如:docker build --no-cache
。注意:
Dockerfile
的指令每执行一次都会在 docker
上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum -y install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz
如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
参数说明:
[--chown=<user>:<group>]
:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>
:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
<目标路径>
:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。补充说明:
COPY
和 RUN
指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。COPY
指令将从构建上下文目录中 <源路径>
的文件/目录复制到新的一层的镜像内的 <目标路径>
位置。比如:
COPY package.json /usr/src/app/
<源路径>
可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则,如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
<目标路径>
可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
此外,还需要注意一点,使用 COPY
指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。
ADD
指令和 COPY
的格式和性质基本一致(同样需求下,官方推荐使用 COPY
)。但是在 COPY
基础上增加了一些功能。比如 <源路径>
可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径>
去。
在构建镜像时,复制上下文中的文件到镜像内,语法格式如下:
ADD <源路径1>... <目标路径>
ADD ["<源路径1>",... "<目标路径>"]
ADD
的优点:在执行 <源文件>
为 tar
压缩文件的话,压缩格式为 gzip, bzip2
以及 xz
的情况下,会自动复制并解压到 <目标路径>
。ADD
的缺点:在不解压的前提下,无法复制 tar
压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。docker
发现文件内容被改变,则接下来的指令都不会再使用缓存。关于复制文件时需要处理的/,基本跟正常的 copy 一致。类似于 RUN
指令,用于运行程序,但二者运行的时间点不同:
CMD
在 docker run
时运行,在构建时不进行任何操作。RUN
是在 docker build
,并生成一个新的镜像。作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD
指令指定的程序可被 docker run
命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile
中如果存在多个 CMD
指令,仅最后一个生效。
语法格式如下(有三种格式):
CMD <shell 命令>
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh
。
ENTRYPOINT
用于给容器配置一个可执行程序。也就是说,每次使用镜像创建容器时,通过 ENTRYPOINT
指定的程序都会被设置为默认程序。
类似于 CMD
指令,但其不会被 docker run
的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT
指令指定的程序。
但是,如果运行 docker run
时使用了 --entrypoint
选项,将覆盖 ENTRYPOINT 指令指定的程序。
优点:在执行 docker run
的时候可以指定 ENTRYPOINT
运行所需的参数。
注意:如果 Dockerfile
中如果存在多个 ENTRYPOINT
指令,仅最后一个生效。
语法格式如下:
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
可以搭配 CMD
命令使用:一般是变参才会使用 CMD
,这里的 CMD
等于是在给 ENTRYPOINT
传参,下面的示例会提到。
假设已通过 Dockerfile
构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
1、不传参运行
$ docker run nginx:test
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
2、传参运行
$ docker run nginx:test -c /etc/nginx/new.conf
容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
语法格式如下(有两种格式):
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
RUN
,还是运行时的应用,都可以直接使用这里定义的环境变量。ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
这个例子中演示了如何换行,以及对含有空格的值用双引号括起来的办法,这和 Shell 下的行为是一致的。
ENV
作用一致。不过作用域不一样。ARG
设置的环境变量仅对 Dockerfile
内有效,也就是说只有 docker build
的过程中有效,构建好的镜像内不存在此环境变量。docker build
中可以用 --build-arg <参数名>=<值>
来覆盖。ARG <参数名>[=<默认值>]
例如,通过 ARG
指定两个变量:
ARG site
ARG build_user=IT笔录
以上我们指定了 site
和 build_user
两个变量,其中 build_user
指定了默认值。在使用 docker build
构建镜像时,可以通过 --build-arg <varname>=<value>
参数来指定或重设置这些变量的值。
docker build --build-arg site=itiblu.com -t itbilu/test .
这样我们构建了 itbilu/test
镜像,其中 site
会被设置为 itbilu.com
,由于没有指定 build_user
,其值将是默认值 IT 笔录。
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
语法格式如下:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
在启动容器 docker run
的时候,我们可以通过 -v
参数修改挂载点。
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
VOLUME 让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。
docker run -P
时,会自动随机映射 EXPOSE
的端口。EXPOSE <port> [<port>...]
EXPOSE
指令并不会让容器监听 host
的端口,如果需要,需要在 docker run
时使用 -p
、-P
参数来发布容器端口到 host
的某个端口上。WORKDIR
指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR
会帮你建立目录。docker build
构建镜像过程中的,每一个 RUN
命令都是新建的一层。只有通过 WORKDIR
创建的目录才会一直存在。WORKDIR <工作目录路径>
WORKDIR
设置工作目录后,Dockerfile
中其后的命令 RUN、CMD、ENTRYPOINT、ADD、COPY 等命令都会在该目录下执行。例如,使用 WORKDIR
设置工作目录:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
在以上示例中,pwd 最终将会在 /a/b/c
目录中执行。在使用 docker run
运行容器时,可以通过 -w
参数覆盖构建时所设置的工作目录。
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
语法格式如下:
USER <用户名>[:<用户组>]
USER
指定用户时,可以使用用户名、UID 或 GID,或是两者的组合。以下都是合法的指定:USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
USER
指定用户后,Dockerfile
中其后的命令 RUN、CMD、ENTRYPOINT 都将使用该用户。镜像构建完成后,通过 docker run 运行容器时,可以通过 -u
参数来覆盖所指定的用户。HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
ONBUILD
用于设置镜像触发器。ONBUILD <其它指令>
如,当镜像被使用时,可能需要做一些处理:
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
LABEL
用于为镜像添加元数据(metadata),元数以键值对的形式指定。LABEL <key>=<value> <key>=<value> <key>=<value> ...
使用 LABEL
指定元数据时,一条 LABEL
指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条 LABEL
指令指定,以免生成过多的中间镜像。
例如,通过 LABEL
指定一些元数据:
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
指定后可以通过 docker inspect
查看:
docker inspect itbilu/test
"Labels": {
"version": "1.0",
"description": "这是一个Web服务器",
"by": "IT笔录"
},
STOPSIGNAL
用于设置停止容器所要发送的系统调用信号。STOPSIGNAL signal
所使用的信号必须是内核系统调用表中的合法的值,如:SIGKILL。
SHELL
用于设置执行命令(shell式)所使用的的默认 shell
类型。SHELL ["executable", "parameters"]
SHELL
在 Windows 环境下比较有用,Windows 下通常会有 cmd
和 powershell
两种 shell
,可能还会有 sh
。这时就可以通过 SHELL
来指定所使用的 shell
类型:FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
Dockerfile
文件,然后创建一个 Dockerfile
文件。命令如下:mkdir mydocker
cd mydocker
touch Dockerfile
命令如下:
sudo vim Dockerfile
注意:
有的虚拟机可能没有安装 vim
,导致会出现下面这样的错误:
sudo: vim: command not found
此时,可以输入下面这条命令进行下载:
sudo apt-get install vim-gtk
进入文件后的界面如下:
补充:文件编辑好之后如何进行退出?
Esc
,然后输入:q
,按回车键即可退出。无法退出,则在 :q
加入一个叹号 !
,再按回车键就行了,即 !q!
。Esc
,输入 :wq
,按回车键即可退出。强制保存退出,则输入 :wq!
。nano
开头编辑文件的要退出】:按 Ctrl+x
,回车键。如要保存的,则先按 Ctrl+o
,再按 x
退出。#基础镜像
FROM ubuntu
#维护者信息
MAINTAINER carson carson@email.com
#镜像的操作指令
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
#容器启动时的执行命令
CMD /user/sbin/nginx
补充:在 Dockerfile
中添加维护者信息是可选的,它用于指定镜像的作者或维护人员。维护者信息可以帮助其他人了解镜像的来源和相关信息。以下是在 Dockerfile
中添加维护者信息的语法和示例:
MAINTAINER <作者或维护者的姓名和邮箱>
FROM ubuntu:latest
MAINTAINER John Doe <john.doe@example.com>
# 添加其他指令
...
在示例中,我们使用 FROM
指令指定基础镜像为最新版本的 Ubuntu
。然后,使用 MAINTAINER
指令指定了维护者的姓名和邮箱地址。
注意:从 Docker 1.13
版本开始,MAINTAINER
指令已经被标记为过时(deprecated)。推荐使用 LABEL
指令来添加维护者信息和其他元数据。下面是使用 LABEL
指令的示例:
FROM ubuntu:latest
LABEL maintainer="John Doe <john.doe@example.com>"
# 添加其他指令
...
使用 LABEL
指令的好处是可以添加多个标签,包括维护者信息和其他自定义元数据,使镜像更丰富和可理解。
总结起来,可以选择使用 MAINTAINER
或 LABEL
指令来添加维护者信息,具体选择取决于使用的 Docker
版本和个人偏好。
Dockerfile
后使用 docker build
指令生成镜像。命令如下:docker build -t myngix .
运行该命令后的截图:
输入以下命令:
# 普通用户涉及权限问题,在该命令之前加上 sudo 即可
docker images
由上面的截图可知,镜像生成成功!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。