WORKDIR 指令用于声明当前的工作目录,以后各层的当前目录就被改为指定的目录。格式为 WORKDIR <工作目录路径>。
如该目录不存在,WORKDIR 会帮你建立目录。再次强调!不要以为编写 Dockerfiel 是在写 shell 脚本。
下面是一个错误示例:
RUN cd /app
RUN echo "hello" > world.txt
如果将这个 Dockerfile 进行构建镜像运行后,会发现找不到 /app/world.txt 文件,或者其内容不是 hello。
原因其实很简单,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dockerfile 构建分层存储的概念不了解所导致的错误。
之前说过每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更。
两行 RUN 分别构建了并启动了各自全新的容器。
因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。
FROM alpine
WORKDIR /a/b
RUN touch a_b_f.txt
WORKDIR /a
RUN touch a_f.txt
[root@localhost workdir]# docker run -it alpine:workdir /bin/sh
/a # ls
a_f.txt b
/a # cd b
/a/b # ls
a_b_f.txt
COPY 指令
格式:
- COPY <源路径>... <目标路径>
- COPY ["<源路径1>",... "<目标路径>"]
和 RUN 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。
<目标路径> 可以是容器内的绝对路径,也可以是相对于 WORKDIR 指定的工作目录的相对路径。目标路径不需要事先创建,如果目录不存在会在复制文件前先被创建。
COPY 指令将会从构建的上下文目录中,把源路径的文件或目录复制到新的一层的镜像内的 <目标路径> 位置。比如:
COPY qf.json /usr/src/app/
注意下面是错误的
COPY qf.json /usr/src/app
这样会把 qf.json 拷贝成为 /usr/src/ 目录下的 app 文件
<源路径> 可以是多个,支持通配符,如:
COPY qf* /app/
COPY q?.txt /app/
使用 COPY 指令,源文件的各种元数据都会保留。
比如读、写、执行权限、文件变更时间等。
ADD 指令
ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。
支持自动解压缩,压缩格式支持: gzip, bzip2 以及 xz
官方推荐使用 COPY 进行文件的复制。
ADD 指定会使构建镜像时的缓存失效,导致构建镜像的速度很慢。
COPY 和 ADD 指令中选择的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
ADD qf.tar.gz /
USER 指令
USER 则是改变执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。
这个用户必须是事先在容器内存在(建立好)的,否则无法切换。
如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 su 或者 sudo,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 gosu。