WORKDIR

指令

WORKDIR <工作目录路径>

描述

使用 WORKDIR 指令来指定工作目录(或者称为当前目录、当前路径)。以后各层指令操作的 “当前目录” 就被改为 WORKDIR 指定的目录,如该目录不存在会自动创建该目录。这个目录也是登录容器后默认的”当然路径目录”。

一些初学者常犯的错误是把 Dockerfile 等同于 Shell 脚本来书写,这种错误的理解还可能会导致出现下面这样的错误:

RUN cd /data
RUN echo "112233" >test.txt

如果将这个 Dockerfile 进行构建镜像运行后,会发现找不到 /data/test.txt 文件。原因其实很简单,在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器,执行命令环境信息是完全独立的。这就是对 Dockerfile 的 RUN 指令构建分层存储的概念不了解所导致的错误。

这里每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 RUN cd /data 的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。

因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。

如上示例可以写成

WORKDIR /data
RUN echo "112233" >test.txt

这样就会生成一个文件 /data/test.txt 。这里首先指定了了一个工作目录 /data ,后续的 RUN 指令都是切换到这个工作目录后才开始执行命令。在一些场景中使用的非常普遍,例如 Tomcat 容器的 Dockerfile

FROM openjdk:14-jdk-oracle
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
......

在 Tomcat 的 Dockerfile中 首先定义了一个变量 CATALINA_HOME ,然后将这里路径添加到系统的环境变量PATH中,其次创建该目录,然后将这个目录设置为工作目录

WORKDIR $CATALINA_HOME

因此,后续的指令、配置、服务运行都是在这个目录中执行,以及用户exec登录容器也是这个 工作目录 。