Dockerfile是一个文本文件,它包含了一系列用于创建Docker镜像的指令。每一条指令都会在镜像中创建一个新的层,这样在构建镜像时可以利用Docker的层缓存来加速构建过程。通过Dockerfile,我们可以定义一个自动化的过程来定制我们的镜像,包括安装需要的软件包,配置系统设置,复制应用代码等等。
FROM:是Dockerfile里的第一条且只能是除了首行注释之外的第一条指令。用于指定基础镜像。格式为:
FROM <image>
# 或
FROM <image>:<version>
# 示例:
FROM ubuntu:24.04
LABEL:指定镜像的一些信息,比如作者信息、版本、描述信息等。这里需要注意的是,填入的字符串,尽量使用双引号,特别是当在字符串中使用环境变量时。格式为:
LABEL <key>=<value> <key>=<value>...
# 示例:
LABEL author="hynever" version="1.0"
LABEL description="hy ubuntu image"
WORKDIR:切换工作目录(相当于cd命令),可以使用多次,后续命令如果参数是相对路径,则会基于之前命令指定的路径。为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。格式为:
WORKDIR /path/to/workdir
# 示例
WORKDIR /home/ubuntu
RUN:在构建镜像时执行的命令。该指定可以有多条。格式为:
# shell模式
RUN <command>
# exec模式
RUN ["executable", "param1", "params2",...]
# 示例
RUN echo "hello" > hell.txt
RUN apt update
EXPOSE:设置Docker容器运行时对外暴露的端口号。在使用-P参数(随机端口映射)时,会在宿主机产生一个随机端口,与EXPOSE指令指定的端口进行映射。注意EXPOSE指令并不是真正把这个端口公开,而是作为一个构建镜像的人和运行容器的人之间的一个文档或桥梁。格式为:
EXPOSE <PORT1> <PORT2>...
# 示例:
EXPOSE 80 8000
# 运行
# 指定端口映射
docker run -dit -p 8000:80 hyubuntu
# 随机端口映射
docker run -dit -P hyubuntu
VOLUME:指定挂载点。这样只要通过该镜像创建的容器都有挂载点。格式为:
VOLUME ["容器中的挂载点"]
VOLUME "容器中的挂载点"
# 示例,会自动创建一个数据卷对象,将/var/lib/docker/volumes/下的某个目录,与容器中的/data目录进行映射
VOLUME ["/data"]
# 或
VOLUME /data
CMD:指定容器运行完后立即被执行的指令,或者给ENTRYPOINT指定默认参数。整个Dockerfile中只能有一个CMD指令,如果存在多个,则以最后一个为准。推荐使用exec的方式。CMD与RUN的区别为,RUN命令是在构建镜像时就会执行,而CMD和ENTRYPOINT命令只有在将镜像运行成容器时才执行。格式为:
# shell模式
CMD command arg1, arg2,...
# exec模式
CMD ["command", "arg1", "arg2"]
# 或者是只有参数的情况
CMD ["arg1", "arg2"]
# 示例1
CMD ["echo", "hello"]
# 示例2
CMD ["hello"]
ENTRYPOINT ["echo"]
ENTRYPOINT:在运行这个容器时会自动执行的命令,可以使用CMD指令指定默认参数。格式为:
# shell模式
ENTRYPOINT command param1, param2,...
# exec模式
ENTRYPOINT ["executable", "param1", "param2",...]
# 示例
ENTRYPOINT ["echo", "hello"]
ADD:将src指定的文件复制到容器中的指定位置,src只能是和Dockerfile相同路径下的。格式为:
# shell模式
ADD <src> <dest>
# exec模式
ADD ["<src>", "<dest>"]
如果src是一个目录,那么ADD只会将该目录下的所有文件拷贝到dest的位置,而不会将目录本身拷贝到dest中。如果想要拷贝目录,那么可以先将目录打包:tar -cvf project.tar project。
如果源文件是压缩文件,则docker会自动解压到容器指定位置。ADD的src可以为URL。
COPY:将宿主机中的某个文件拷贝到容器中的指定位置。格式为:
# shell模式
COPY <src> <dest>
# exec模式
COPY ["<src>", "<dest>"]
COPY与ADD有以下几点区别:
ADD的src可以为URL,而COPY只能是宿主机的文件。在需求相同时,docker推荐使用COPY指令。
如果src是一个压缩文件,ADD会自动在dest路径下解压该文件,而COPY不会。
COPY的dest路径末尾建议加斜杠,如果不加斜杠,那么被拷贝进来的文件将会覆盖dest路径的文件。比如:
# dest末尾没有加斜杠,那么/home/ubuntu会被hello.txt给覆盖了,导致ubuntu性质发生变化
COPY hello.txt /home/ubuntu
# 正确用法是
COPY hello.txt /home/ubuntu/
ENV:设置环境变量,可以在任何需要这个环境变量的指令之前定义。使用ENV创建的环境变量,在镜像构建完成后依然能够使用。格式为:
ENV <key> <value>
# 或
ENV <key>=<value>
ARG:也是设置环境变量。使用ARG创建的环境变量只能在镜像构建过程中生效。格式为:
ARG <key> <value>
ARG指令有一个好处,就是可以在Dockerfile中指定环境变量的名称,而不指定其具体的值,可以延迟到在使用build命令构建镜像的时候再指定其值,这对一些敏感数据(比如密码)特别有用。
# Dockerfile
ARG PASSWORD
RUN ["sh", "-c","echo $PASSWORD"]
# 构建命令
docker build -t hy --build-arg PASSWORD=123 .
将Dockerfile尽量放在空目录中。然后执行以下指令格式:
docker build -t [新的镜像名]:[版本号] [Dockerfile所在路径]
命令会自动在Dockerfile所在路径中寻找Dockerfile文件,然后构建新的镜像。