linRichielinRichie
前端
Python
Linux
ChatGPT
  • B 站
  • 500px
前端
Python
Linux
ChatGPT
  • B 站
  • 500px
  • Ansible

    • Ansible: 基本操作
    • Ansible: 安装
    • Ansible: 简介
    • YAML: 文件格式
    • Playbook

      • Playbook: 介绍
      • Playbook: 操作
    • 模块

      • Yum模块常用参数
    • 实战

      • Ansible 实战
  • Anaconda

    • Anaconda命令
  • Iptables

    • Iptable: 防火墙
    • iptables 用法
  • Systemd

    • 系统服务配置
    • 系统服务启动文件
    • 性能优化

      • Linux 系统监控
      • Linux 系统性能优化
      • Linux 系统故障诊断
      • Linux 系统日志管理
  • Network

    • 用一张图解释 8 种流行的网络协议
    • 反子网掩码
    • 交换机端口模式
    • eNSP 软件
    • 华为交换机配置命令
    • eNSP静态路由实验
  • Commands

    • 命令别名:alias
    • 多类型资源统计工具: dstat
    • history配置
    • unzip命令
    • Linux用户到期登录时间和随机密码
    • 常用 Command
    • ssh

      • ssh-keygen
      • linux ssh命令
  • CI/CD

    • Jenkins CI/CD 管道
  • Kubernetes

    • Docker系列学习

      • 01. 什么是Docker
      • 02. Docker安装
      • 03. 使用Docker镜像
      • 04. 利用commit理解镜像构成
      • 05. 操作Docker容器
      • 06. 使用Dockerfile定制镜像
      • 07. Dockerfile指令详解
      • 08. Dockerfile多阶段创建
      • 09. 访问仓库
      • 10. 修改docker的启动项
      • 11. Nexus3.x的私有仓库
      • 12. docker-hub加速器
      • 13. 数据管理
      • 14. 使用网络
  • Shell编程

    • Shell 编程基础
    • Shell 脚本执行消耗的时间
    • Shell 自动生成简介

07. Dockerfile指令详解

  • 简介
  • 1. 文件操作指令
    • 1.1 COPY 复制文件
    • 1.2 ADD 高级复制文件
  • 2. 容器运行指令
    • 2.1 CMD 容器启动命令
    • 2.2 ENTRYPOINT 入口点
    • 2.3 ENV 设置环境变量
    • 2.4 VOLUME 定义匿名卷
    • 2.5 EXPOSE 声明端口
    • 2.6 WORKDIR 指定工作目录
    • 2.7 USER指定当前用户
    • 2.8 HEALTHCHECK 健康检查

简介

Dockerfile 是用于构建 Docker 镜像的文本文件,它包含了一系列的指令和参数。本文将详细介绍常用的 Dockerfile 指令,包括 FROM、RUN、COPY、ADD、CMD、ENTRYPOINT、ENV 等。

1. 文件操作指令

1.1 COPY 复制文件

格式:

  • COPY [--chown=<user>:<group>]<源路径>...<目标路径>
  • COPY [--chown=<user>:<group>]["<源路径>",..."<目标路径>"]

COPY 指令将从构建上下文目录中的源路径复制文件/目录到镜像内的目标路径。支持两种格式:命令行格式和函数调用格式。

COPY package.json /usr/src/app/

源路径特性:

  • 支持多个源路径
  • 支持通配符(遵循 Go 的 filepath.Match 规则)
COPY hom* /mydir/
COPY hom?.txt /mydir/

目标路径说明:

  • 支持绝对路径和相对路径(相对于 WORKDIR)
  • 目录会自动创建
  • 保留源文件的元数据(权限、时间戳等)

权限设置: 可以使用 --chown 选项设置文件的所属用户和组:

COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --choen=1 files* /mydir/
COPY --chown=10:11 files* /mydir/

1.2 ADD 高级复制文件

ADD 指令是 COPY 的增强版本,提供了更多功能:

URL 支持:

  • 支持从 URL 下载文件
  • 下载文件权限默认为 600
  • 不推荐使用此功能,建议使用 RUN + wget/curl

自动解压:

  • 支持 tar、gzip、bzip2、xz 格式
  • 自动解压到目标路径

在某些情况下,这个自动解压缩的功能非常有用,比如官方镜像 ubuntu 中:

FROM scratch
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /

注意: 如果只想复制压缩文件而不解压,应使用 COPY 指令

最佳实践:

  • 优先使用 COPY(功能单一,行为明确)
  • 仅在需要自动解压缩时使用 ADD

警告: ADD 指令会使构建缓存失效,可能降低构建速度

权限设置: 同样支持 --chown 选项:

ADD --chown=55:mygroup files* /mydir/
ADD --chown=bin files* /mydir/
ADD --chown=1 files* /mydir/
ADD --chown=10:11 files* /mydir/

2. 容器运行指令

2.1 CMD 容器启动命令

格式:

  • shell 格式:CMD <命令>
  • exec 格式:CMD ["可执行文件", "参数1", "参数2"]

作用:

  • 指定容器启动时的默认命令
  • 可以被 docker run 命令行参数覆盖
  • 每个 Dockerfile 只能有一个 CMD

使用示例:

# 默认命令
CMD ["nginx", "-g", "daemon off;"]

# 带参数的 ENTRYPOINT
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]

最佳实践:

  • 使用 exec 格式 (["command", "param1", "param2"])
  • 避免使用 shell 格式 (command param1 param2)
  • 确保应用程序在前台运行

注意: Docker 容器中的应用应该以前台方式运行,而不是作为后台服务

2.2 ENTRYPOINT 入口点

格式:

  • exec 格式:ENTRYPOINT ["可执行文件", "参数1", "参数2"]
  • shell 格式:ENTRYPOINT command param1 param2

作用:

  • 配置容器启动时运行的命令
  • 不会被 docker run 的命令行参数覆盖
  • 可以接收 CMD 指令或运行参数

使用场景:

  • 需要固定的启动命令
  • 需要处理命令行参数
  • 作为可执行程序使用

示例:

# 固定的入口点
ENTRYPOINT ["nginx"]

# 可以在运行时添加参数
docker run myimage -g "daemon off;"

2.3 ENV 设置环境变量

格式:

  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2>...

作用:

  • 设置环境变量
  • 可被后续指令使用
  • 在容器运行时仍然有效

示例:

ENV VERSION=1.0 DEBUG=on \
    NAME="Happy Feet"

支持的指令: ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD

最佳实践:

  • 使用环境变量增加构建灵活性
  • 一个 Dockerfile 可通过不同环境变量构建不同镜像

2.4 VOLUME 定义匿名卷

格式:

  • VOLUME ["<路径1>", "<路径2>"]
  • VOLUME <路径>

作用:

  • 声明容器数据持久化目录
  • 避免向容器存储层写入数据
  • 运行时可被显式挂载覆盖

示例:

# 声明匿名卷
VOLUME /data

# 运行时覆盖匿名卷
docker run -d -v mydata:/data image_name

2.5 EXPOSE 声明端口

格式:

EXPOSE <端口1> [<端口2>...]

作用:

  • 声明容器对外提供的服务端口
  • 帮助镜像使用者理解端口用途
  • 配合 docker run -P 实现随机端口映射

注意: EXPOSE 仅作为文档说明使用,不会自动开启端口,需要 -p 参数映射端口

2.6 WORKDIR 指定工作目录

格式:

WORKDIR <工作目录路径>

作用:

  • 设置工作目录
  • 影响后续指令的工作路径
  • 不存在的目录会被自动创建

最佳实践:

  • 使用绝对路径
  • 避免使用 RUN cd 命令
  • 每个 RUN 指令都在独立的容器中执行

2.7 USER指定当前用户

格式:

USER <用户名>[:<用户组>]

作用:

  • 指定后续命令的执行用户
  • 影响 RUN、CMD 和 ENTRYPOINT 指令
  • 用户必须预先创建

示例:

RUN groupadd -r redis && useradd -r -g redis redis 
USER redis
RUN ["redis-server"]

最佳实践:

  • 避免使用 root 用户运行应用
  • 使用 gosu 代替 su/sudo 切换用户
  • 在构建阶段创建所需用户

使用 gosu 示例:

# 建立redis用户,并使用gosu换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \
    && chmod +X /usr/local/bin/gosu \
    $$ gosu nobody true
# 设置CMD,并以另外的用户执行
CMD ["exec","gosu","redis","redis-server"]

2.8 HEALTHCHECK 健康检查

格式:

  • HEALTHCHECK [选项] CMD <命令>: 设置检查容器健康状态的命令
  • HEALTHCHECK NONE: 禁用基础镜像中的健康检查指令

作用:

  • 定期检查容器服务状态
  • 发现服务异常(如死锁、死循环)
  • 支持容器自动调度和故障转移

状态变化:

  • starting: 初始状态
  • healthy: 检查成功
  • unhealthy: 连续检查失败

支持的选项:

  • --interval=<间隔> : 两次健康检查的间隔,默认为30秒
  • --timeout=<时长> : 康检查命令运行超时时间,如果超过这个时间,本次健康检查被视为失败,默认30秒
  • --retries=<次数> : 当连续时报指定次数后,则将容器状态视为unhealthy,默认3次

返回值:

  • 0: 检查成功
  • 1: 检查失败
  • 2: 保留值,不要使用

示例:检查 Web 服务

# Dockerfile
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s  --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
# 说明:这里我们设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),如果健康检查命令超过 3 秒没响应就视为失败,并且使用 curl -fs http://localhost/ || exit 1 作为健康检查命令

运行示例:

docker build -t myweb:v1 .  #构建镜像
docker run -d --name web -p 80:80 myweb:v1  #启动容器
docker container ls         #查看容器状态

查看健康状态:

docker inspect --format '{{json .State.Health}}' web | python -m json.tool

参考文档:Dockerfile官当文档
Dockerfile实践文档
Docker官方镜像

最近更新时间:
Prev
06. 使用Dockerfile定制镜像
Next
08. Dockerfile多阶段创建