以下是关于 Dockerfile 常用指令的解析,包括 WORKDIR
、ENV
和后续的 USER
指令。这些指令是 Dockerfile 中的重要部分,分别用于设置工作目录、定义环境变量以及指定运行容器时的用户权限。
1. WORKDIR 指令
作用:
-
WORKDIR
用于指定 Docker 容器内的工作目录。 - 它会影响后续所有层的运行环境,因为每个
RUN
、CMD
或ENTRYPOINT
指令都会在指定的WORKDIR
目录中执行。 - 如果指定的目录不存在,Docker 会自动创建它。
语法:
WORKDIR /path/to/directory
特点:
- 必须是绝对路径。
- 一旦设置,会对后续的指令生效。
- 如果在多层构建中需要某个目录始终存在,可以通过
WORKDIR
创建它。
示例:
FROM ubuntu:latest
# 设置工作目录
WORKDIR /app
# 将主机目录下的文件复制到容器的工作目录中
COPY . .
# 在 /app 目录中安装依赖
RUN apt-get update && apt-get install -y net-tools
CMD ["bash"]
关键点:
- 不需要提前手动创建目录。
- 使用
WORKDIR
设置的目录会贯穿后续构建。
执行测试:
- 构建容器
docker build -t ubuntu-new1 .
- 启动容器的几种方式:
临时运行容器,推出后自动清理
docker run --rm -it ubuntu-new1
给容器命名
docker run --name ubuntu-newtest -it ubuntu-new1
后台运行容器
docker run -itd ubuntu-new1
- 退出容器的方式:
在 Ubuntu 容器的终端中,可以通过以下方式退出:
输入 exit 或按 Ctrl+D:容器会停止运行。
如果想让容器在后台继续运行,可以按 Ctrl+P 再按 Ctrl+Q。
2. ENV 指令
作用:
-
ENV
用于定义环境变量,设置的变量会在容器的运行环境中生效。 - 它可以用于后续的
RUN
、CMD
或ENTRYPOINT
指令中。
语法:
ENV key=value
或
ENV key value
特点:
- 可以引用之前定义的环境变量。
- 定义的变量可以在容器运行时被覆盖,比如通过
docker run -e
参数。
示例:
FROM node:16
# 设置环境变量
ENV NODE_VERSION=16.13.0 APP_ENV=production
# 使用环境变量
RUN echo "Node.js version is $NODE_VERSION"
# 使用环境变量执行命令
CMD ["node", "-v"]
优点:
- 方便管理和更新,比如在构建镜像时只需要更改环境变量值。
- 避免硬编码,增强可维护性。
实际应用:
- 定义应用程序版本号:
ENV APP_VERSION=1.0.0
- 定义运行环境:
ENV ENVIRONMENT=production
- 在
RUN
指令中引用:
RUN curl -o app.tar.gz http://example.com/download/app-$APP_VERSION.tar.gz
3. USER 指令
作用:
-
USER
用于设置运行容器时的用户身份(UID 或用户名)。 - 默认情况下,容器中的应用程序以
root
用户身份运行,这可能会带来安全风险。USER
指令可以切换到非特权用户。
语法:
USER username
或
USER uid
特点:
-
USER
指令会影响所有后续的RUN
、CMD
和ENTRYPOINT
。 - 使用非
root
用户运行容器可以提高安全性,避免潜在的权限滥用。
示例:
FROM ubuntu:latest
# 创建一个非 root 用户
RUN groupadd -r mygroup && useradd -r -g mygroup myuser
# 切换到新用户
USER myuser
WORKDIR /app
CMD ["bash"]
关键点:
- 在基于
Debian
或Ubuntu
的镜像中,可以使用useradd
添加新用户。 - 在基于
Alpine
的镜像中,可以使用adduser
添加新用户。
总结和最佳实践
WORKDIR
的最佳实践:
- 始终使用
WORKDIR
设置工作目录,而不是依赖RUN mkdir
创建目录,因为前者更易读。 - 示例:
WORKDIR /app
ENV
的最佳实践:
- 尽可能使用
ENV
定义版本号、运行环境等变量,避免硬编码。 - 示例:
ENV NODE_VERSION=16.13.0
USER
的最佳实践:
- 除非必要,尽量避免以
root
用户运行容器。创建一个专门的非特权用户运行应用程序。 - 示例:
RUN useradd -m myuser
USER myuser
迷茫的人生,需要不断努力,才能看清远方模糊的志向!