Dockerfile
Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
Dockerfile指令
FROM
FROM指定基础镜像
FROM basicImage
定制镜像都要以一个镜像为基础,
FROM作用就是指定基础镜像。在
Dockerfile中,FROM是必须的,必须是第一条指令。
特殊空白镜像
Docker存在一个特殊的scratch镜像。这个镜像是虚拟的概念,不实际存在,表示一个空白的镜像。以
scratch为基础镜像的,表示不以任何镜像为基础,所写的指令将作为镜像第一层开始存在。
RUN
RUN表示执行命令
两种格式:
shell格式: RUN <命令>`,如下:
RUN echo '<h1>hello</h1>' > /usr/share/nginx/html/index.html
exec格式:RUN ["可执行文件", "参数1", "参数2"]
WARNING
注意:不要用下面这种写法
FROM basicImage
RUN operation1
RUN operation2
RUN operation3
...
因为Dockerfile中每一个指令都会建立一层镜像,RUN也是,每一个RUN就新建立一层,在其上执行这些命令,执行结束后,commit这一层的修改,构成新的镜像,上面这种写法创建了3层甚至更多镜像,导致镜像层数过多,而我们并不需要这么多层,所以不提倡
推荐写法:
FROM basicImage
RUN yum install -y gcc gcc-c++ make perl-devel \
&& mkdir -p /opt/app/ /opt/source/ \
&& cd /opt/source \
&& 其他操作
WARNING
执行RUN命令的时候,会重写hosts文件,因此在RUN之前修改hosts文件是无效的
COPY
COPY表示复制文件
COPY 源路径 目标路径
COPY ['源路径1','源路径2', ..., '目标路径']
和
RUN指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用COPY指令是从构建上下文目录中的源路径的文件或者目录复制到新一层的镜像内的目标路径。
COPY . ./app
- 可以是
多个源路径,也可以是通配符,只要匹配都会选中
COPY ['xxx*', 'aaa/' '/dir/']
目标路径可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。使用
COPY指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
ADD
ADD:更高级的复制文件ADD和COPY格式以及性质基本一致,在COPY基础上加了一些功能。ADD指令会使镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢ADD具有自动解压缩功能,如果需要自动解压缩功能就使用ADD,否则如果只是单纯复制文件,COPY将是更好的选择。
CMD
CMD容器启动命令
CMD和RUN相似,也是两种格式
- shell格式:
CMD <command>
- exec格式:
CMD ["可执行文件", "参数1", "参数2"...]
使用shell命令,会被包装为sh -c的参数形式进行执行。
例如:
CMD echo $HOME
实际执行中会变为:
CMD ["sh", "-c", "echo $HOME"] # 一定要用双引号
ENTRYPOINT
ENTRYPOINT和CMD一样,都是配置容器启动后执行的命令,ENTRYPOINT可以在docker run的时候通过--ectrypoint传入。ENTRYPOINT和RUN相似,也是两种格式exec格式和shell格式
TIP
当指定了ENTRYPOINT后,CMD的含义就发生了改变,不再是直接的运行其命令,而是将CMD的内容作为参数传给ENTRYPOINT指令。
例如:
FROM centos
RUN yum install ...
...
ENTRYPOINT ["xxx.sh"]
CMD ["aaa"]
如上,aaa就会作为参数传到执行的xxx.sh内
或者是
FROM centos
RUN yum install ...
...
ENTRYPOINT ["xxx.sh"]
比如将这个修改build成demo:v1版本:
docker build -t demo:v1 .
然后在命令行执行
docker run --name demo_server demo:v1 CMD
此时的CMD也会作为参数传递给ENTRYPOINT运行的命令
ENV
ENV设置环境变量指定一个
环境变量,会被后续RUN指令使用,可以在容器内被脚本或者程序调用
有两种格式
ENV key value
#或者
ENV key1=value1 key2=value2 ...
示例
...
ENV VERSION 2.2
...
#或者
...
ENV VERSION=2.2 MY_ENV=hello
...
TIP
如果设置的环境变量中间有空格,那么环境变量记得用双引号("")包裹
例如:
ENV XXX "Hello World"
EXPOSE
EXPOSE暴露端口
EXPOSE 7100
EXPOSE声明容器运行时提供的服务端口,只是一个声明,不会因为这个声明就开启这个端口的服务。EXPOSE和docker run -p <宿主端口>:<容器端口>区别:docker run -p <宿主端口>:<容器端口>:映射宿主端口和容器端口,就是将容器的对应端口服务公开给外界访问EXPOSE:仅仅是决定容器使用什么端口,不会自动在宿主端口进行端口映射
WORKDIR
WORKDIR指定工作目录这个指定的
目录很重要,会影响很多命令执行时所操作的目录,一定要写对WORKDIR为后续的RUN、CMD、ENTRYPOINT指令配置工作目录,以后各层的当前目录就是被指定的目录,如果目录不存在,WORKDIR会帮助我们创建目录
build
- 构建镜像
docker build [OPTIONS] PATH | URL | -
# 例如:
docker build -t nginx:v1 .
镜像构建上下文
docker build命令末尾会指定一个路径,通常为.,这个.的作用就是来指定上下文路径docker build这一构建命令的执行,实际上是使用远程调用形式在服务端(Docker 引擎)完成。在服务端构建时,有可能需要将本地的一些文件复制到镜像里面去,服务器要获取本地需要复制的文件就是要通过这个上下文路径,而这个路径是我们自己在build时指定的路径docker build命令获取到这个路径之后,会将路径下内容打包,传给Docker引擎,这样Docker引擎收到这个上下文包之后,展开就会得到构建镜像所需文件如果所给出的
URL不是个仓库地址,而是个tar压缩包,那么Docker引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建如果标准输入传入的是
文本文件,则将其视为Dockerfile,并开始构建。这种形式由于直接从标准输入中读取Dockerfile的内容,它没有上下文,因此不可以像其他方法那样可以将本地文件COPY进镜像之类的事情