Dockerfile
文章目录
之前总结过 Docker 的使用,讲解了 Docker 的安装、相关概念以及基本使用。里面介绍的都是如何使用别人制作好的镜像,显然是不能满足我们的需要。接下来就来讲讲私人订制自己的镜像。
Dockerfile 简介
简单的说 Dockerfile 是用来告诉 docker 怎么构建镜像用的。
除了使用 Dockerfile 来构建镜像外,还可以使用 docker commit
来构建镜像。使用 docker commit
来构建镜像会把所有执行的操作都会被添加进镜像中。比如:文件改动,目录跳转,编译等一些无关的内容。这些东西存在镜像里就会导致镜像非常臃肿。
使用 Dockerfile 来定制镜像,可以很方便的知道镜像是如何构建的, docker commit
对于其他人来说是一个黑盒操作。另外的好处就是需要改动某条指令的时候,只需要改动 Dockerfile 然后重新构建。 这点 docker commit
做起来就很麻烦了。把 Dockerfile 提供给别人也容易定制成自己想要的。
Dockerfile 指令
了解了 Dockerfile 之后,就来看看 Dockerfile 的指令
FROM
FROM
指令的格式为: FROM <image>:<tag>
tag 是可选项,可以不要
|
|
FROM
用来指定基础镜像,我们使用 Dockerfile 定制镜像,其实就是在一个基础镜像上进行操作。在 Dockerfile 中 FROM
是必需的指令,且一定是第一个指令。
常见的基础镜像有 ubuntu
centos
alpine
nginx
node
golang
等等。
一个特殊的基础镜像是 scratch
,这是一个空白的镜像,实际并不存在,这意味着你不以任何镜像为基础。这种镜像里的程序通常不需要操作系统提供运行支持,一切库都在可执行程序里。这种镜像体积也会很小。大多使用 Go
开发的程序会使用 scratch
作为基础镜像。
COPY
COPY
指令的格式为: COPY <src> <dest>
|
|
COPY
指令的作用是把主机的文件添加到镜像里,有一点需要注意的是 COPY
会对源文件的原数据进行保留。比如:读、写、执行权限。
ADD
ADD
指令的格式为: ADD <src> <dest>
|
|
ADD
与 COPY
类似,也是把主机的文件添加到镜像里。不同的是 ADD
可以是个 URL
,如果源路径是个压缩文件并且不是 URL
,会自动解压到目标路径。官方更建议使用 COPY
,因为 COPY
的语义比较明确就是拷贝文件。
RUN
RUN
指令的格式为: RUN <command>
或者 RUN ["executable","param1","param2"]
|
|
RUN
指令是用来执行命令行命令的。通常我们会用 RUN
来执行 shell
命令来为镜像准备环境。
如果有多条指令,需要使用 &&
连成一条指令。因为每条 RUN
指令都会建立一层存储,而镜像是有层数限制的。
CMD
CMD
指令的格式为: CMD <command>
或者 CMD ["executable","param1","param2"]
或者 CMD ["param1","param2"]
|
|
CMD
指令是容器启动后执行的指令,如果执行 docker run
后面跟了启动命令,这个就会被覆盖掉。需要注意的是 CMD
在 Dockerfile 中只能存在一条,如果有多条,只有最后一条才会生效。 CMD
的命令格式(第一种),其实会被包装成 CMD ["sh", "-c", "echo $PATH"]
。
CMD
的第三种格式,是用来为 ENTRYPOINT
提供默认参数使用的。后面讲到了我们再说。
ENTRYPOINT
ENTRYPOINT
指令的格式为: ENTRYPOINT command
或者 ENTRYPOINT ["executable", "param1", "param2"]
|
|
ENTRYPOINT
与 CMD
类似,也是在容器启动后执行的命令。不同点在于执行 docker run
不会被覆盖,如果需要覆盖可以使用 --entrypoint
来覆盖,这增加了覆盖启动命令的难度。
前面说到 CMD ["param1","param2"]
格式是给 ENTRYPOINT
提供默认参数用的。当 Dockerfile 指定了 ENTRYPOINT
和 CMD
,那么 CMD
就会作为参数传递给 ENTRYPOINT
。
|
|
这两条指令其实就相当于 ls -l -s
这样做的好处是,在运行容器的时候可以把参数传递给 ENTRYPOINT
。举个例子
|
|
在运行容器的时候就可以携带 -l
参数了 docker run myls -l
。这样 -l
就会成为 /usr/bin/ls
的参数了,而不用重新构建一个新的镜像。
ENV
ENV
指令的格式为: ENV <key> <value>
或者 ENV <key1>=<value1> <key2>=<value2>=
|
|
ENV
指令是设置环境变量,很简单的指令,和通常说的环境变量是一个意思。
VOLUME
VOLUME
指令的格式为: VOLUME <path>
或者 VOLUME ["path1", "path2"]
|
|
VOLUME
指令是将主机的目录挂载到容器里。我们希望在容器删掉后,里面的数据还保存着,可以通过 VOLUME
把主机里的目录挂载到容器中。挂载的命令是 docker run -v mydata:/data xxx
EXPOSE
EXPOSE
指令的格式为: <port> [<port>...]
|
|
EXPOSE
只是声明容器使用的端口,并不会与宿主机进行端口映射。可以通过 -p
指令在启动容器的时候进行映射 docker run -p 8080:8080 xxx
。
WORKDIR
WORKDIR
指令的格式为: WORKDIR /path/to/workdir
|
|
WORKDIR
用来设置工作目录,相当于切换目录,也就相当于 cd
。在 Dockerfile 中不能使用 cd
,因为 cd
不在同一个环境中, Linux
中之所以能用是因为 cd
在同一个进程里。
构建镜像
说完了 Dockerfile 的指令,来看看怎么通过 Dockerfile 构建镜像。
在 Dockerfile 目录执行 docker build -t container1:v1 .
最后面有个点 .
,不要漏掉了。这个 .
表示的是 镜像构建上下文 。镜像构建上下文表示的是一个路径。在构建的时候会把 镜像构建上下文 路径里的内容打包传递给 docker 引擎,在执行 COPY
这类指令的时候使用相对路径,其实相对的就是 镜像构建上下文 。
除了把 Dockerfile 写在本地之外,还可以通过 Git Repo 构建、用 tar 包构建、从标准输入中读取 Dockerfile 构建、从标准输入中读取上下文压缩包进行构建。这些用的比较少,所以不再赘述。
总结
Docker 让我们开发部署搭建环境变得轻而易举,我们可以分分钟部署出一个一模一样的环境,这样一来把时间花在重要的开发上,而不是每次换台电脑或者同事使用都需要装半天的软件,配置一大堆参数。所有团队的成员都是一个环境,而不会发生,在我电脑上好好的,怎么到你这就不行了的无奈。
掌握了 Docker 我们还需要学会怎么自己定制我们需要的容器,这样才能很好的驾驭 Docker ,定制属于自己的镜像。
参考
Best practices for writing Dockerfiles | Docker Documentation