Dockerfile
什么是Dockerfile?
Dockerfile是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
自定义一个镜像
举个栗子,我们需要自定义这么一个镜像:基于Python基础镜像,当容器运行时,会自动打印一些图案。
如何实现呢?
1、首先,编写Dockerfile
文件。
1 | FROM python:alpine |
具体指令含义下文详解,先梳理流程。
2、将Dockerfile
中需要的文件(Dockerfile
、requireents.txt
、fun.py
)放到一个目录下。
1 | [root@VM-0-2-centos docker-demo] ls |
requirements.txt文件内容
1 | cowpy==1.1.0 |
fun.py文件内容
1 | from cowpy import cow |
3、然后,执行命令开始构建镜像。
1 | docker build -t test:v1 . |
构建过程如下:
可以看到,其实构建过程中的每一个step
对应的就是Dockerfile
文件中的一条指令。
4、构建完成后,通过docker images
查看新构建的镜像。
5、启动容器。
执行命令docker run --rm test:v1
启动容器。(加上**–rm**退出容器以后,这个容器就被删除了,方便在临时测试使用)
可以看到,每次启动容器后,都会打印一个图案,这是因为该镜像文件中有一行指令CMD ["python", "fun.py"]
,即当容器启动时,会在命令行中执行python fun.py
,而这个py
文件其实就是应用cowpy
模块执行了一句print(cow.milk_random_cow("Hello, Everyone!"))
来完成图案打印。
ok,构建自定义镜像的整体流程如上,下面来详解Dockerfile
中的常用指令。
FROM
定制的镜像都是基于FROM
的镜像,上文的python:alpine
就是基础镜像。
格式:FROM 镜像名:版本
。
注意两点:
- 如果基础镜像本地没有,会自动去
docker hub
中下载 - 一个
Dockerfile
文件中通常只有一个FROM
指令(多阶段构建除外)
LABEL
LABEL
指定docker中的元数据信息,maintainer
指定当前Dockerfile
文件的作者(维护者),description
指定功能描述信息。
WORKDIR
相当于cd命令,切换到容器中的某个目录,如果指定的目录不存在,那么会自动创建。
COPY
相当于cp命令,将宿主机中的目录或文件复制粘贴到容器中。
1 | COPY requirements.txt ./dir/ |
注意:如果是./dir
会把dir
当做一个文件。
将宿主机当前目录下的requirements.txt
文件复制到容器内的当前目录下的dir
目录下。
- 第一个参数为宿主机中的目录或文件(相对路径或绝对路径)
- 第二个参数为容器中的目录或文件(相对路径或绝对路径)
注:容器内的路径如果不存在,会自动创建。
ADD
跟COPY
功能类似,如果第一个参数为本地的压缩文件,那么会自动解压,将解压之后的文件复制粘贴到容器中;如果是路径,那么会自动下载,将下载后的文件复制粘贴到容器中。
RUN
用于执行RUN
后面跟着的命令,等同于在命令行执行shell
命令。
值得注意的是,RUN
指令越多,构建出来的镜像层级就会很多,镜像尺寸就会很大。
若有多个RUN
指令,可以用&&
连接成一条指令,如:
1 | RUN pip install -i https://pypi.douban.com/simple --no-cache-dir -r requirements.txt && ls / && ls /root && ps aux |
ENV
设置环境变量,定义了环境变量后,后续的指令就可以使用这个环境变量。
1 | ENV username=ancientone |
VOLUME
指定容器运行时,需要映射出去的目录(容器中)。
如
1 | VOLUME /app |
只有在Dockerfile
中指定了VOLUME
映射目录,才能在docker run
时加参数-v映射到宿主机。
EXPOSE
指定容器运行时,需要映射出去的端口号(容器中)。
如
1 | EXPOSE 8088 |
CMD
类似于RUN
指令,用于运行程序,但二者运行的时间点不同:
- CMD在
docker run
时运行,即容器启动时。 - RUN在
docker build
时运行,即镜像构建时。
CMD
指令后面可以跟两种类型的命令:
shell
类型的命令,如CMD python fun.py
、CMD ls /root
exec
类型的命令:[“指令”,”参数1”,”参数2”],为json数组,必须得用双引号,如CMD ["python","fun.py"]
、CMD ["ls","/root"]
注意:
- 如果在容器运行时(docker run)有指定的命令,那么
CMD
会被忽略。 - 如果
Dockerfile
中如果存在多个CMD
指令,仅最后一个生效。
优先使用exec类型的命令,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。
ENTRYPOINT
类似于CMD
命令,区别在于:
CMD
会被docker run
的命令行参数指定的指令所覆盖,而ENTRYPOINT
不会。
如果ENTRYPOINT
和CMD
连用,那么CMD
会作为ENTRYPOINT
的默认参数,如:
1 | ENTRYPOINT ["ping"] |
即当容器运行时,会在shell执行ping 114.114.114.114
。
注意:如果 Dockerfile
中如果存在多个 ENTRYPOINT
指令,仅最后一个生效。