运维
PythonJava前端数据库
Docker
Docker
  • Docker简介
  • 基本概念
    • 镜像
    • 容器
    • 仓库
  • 安装
  • 使用镜像
    • 获取镜像
    • 列出镜像
    • 删除镜像
    • 导入和导出
  • Dockerfile
    • 构建镜像
    • 多阶段构建
    • 构建多种系统架构支持的镜像
    • Dockerfile 命令介绍
      • COPY 复制文件
      • ADD 更高级的复制
      • CMD 容器启动命令
      • ENTPYPOINT 入口点
      • ENV 设置环境变量
      • ARG 构建参数
      • VOLUME 匿名卷
      • USER 指定当前用户
      • EXPOSE 暴露端口
      • WORKDIR 工作目录
      • SHELL 指令
      • LABEL 为镜像添加源数据
      • ONBUILD 为他人作嫁衣裳
  • 数据管理
    • 数据卷
    • 挂载主机目录
  • 操作容器
    • 启动、停止和删除
    • 进入容器
    • 导入和导出
    • 重启策略
  • 网络配置
    • 基本网络配置
    • 高级网络配置
  • Docker Buildx
    • 使用buildx构建镜像
    • 使用buildx构建多种系统架构镜像
  • Docker Compose
    • 简介
    • 简单使用
    • 多个配置文件
    • Compose网络配置
    • 控制启动服务启动顺序
    • 命令说明
  • Kubernetes
由 GitBook 提供支持
在本页
  • FROM 指定基础镜像
  • 构建镜像
  • 镜像构建上下文(Context)

这有帮助吗?

  1. Dockerfile

构建镜像

上一页Dockerfile下一页多阶段构建

最后更新于2个月前

这有帮助吗?

Dockerfile 是一个文本文件,其中包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM 指定基础镜像

定制镜像,那么一定是有一个镜像作为基础镜像,在其上进行定制。基础镜像是必须指定的。因此在一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。

在 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 、、、、、、 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 、、、、 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。

如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如 、、、、 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。

除了选择现有镜像为基础外,Docker 还存在一个特出的镜像,名为 scratch,这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。

如果你以 scratch 为基础镜像的话,意味着你不移任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

构建镜像

在 Dockerfile 文件所在目录执行:

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
 ---> e43d811ce2f4
Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
 ---> Running in 9cdc27646c7b
 ---> 44aa4490ce2c
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c

从命令的输出结果中,我们可以清晰的看到镜像的构建过程。在 Step 2 中,如同我们之前所说的那样,RUN 指令启动了一个容器 9cdc27646c7b,执行了所要求的命令,并最后提交了这一层 44aa4490ce2c,随后删除了所用到的这个容器 9cdc27646c7b

里我们使用了 docker build 命令进行镜像构建。其格式为:

docker build [选项] <上下文路径/URL/->

在这里我们指定了最终镜像的名称 -t nginx:v3,构建成功后,我们可以像之前运行 nginx:v2 那样来运行这个镜像,其结果会和 nginx:v2 一样。

镜像构建上下文(Context)

我们注意到docker build命令最后有一个.,.通常是表示当前目录,而Dockerfile就在当前目录,因此不少初学者会以为这个路径是在指 Dockerfile 所在的路径,实则不然,通过对应上面的命令格式,我们会发现,这是在指定上下文路径。

当构建的时候,用户会指定构建镜像上下文的路径,docker build命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎,这样 Docker 引擎收到这个上下文包后,展开就会得到构建镜像所需的一切文件。

如果在 Dockerfile 中这么写:

COPY ./package.json /app/

这并不是复制执行docker build命令所在目录下的package.json,也不是Dockerfile所在目录下的packag.json,而是复制上下文目录下的package.json。

因此,COPY这类指令中的源文件的路径都是相对路径。这也是很多初学者为什么 COPY ../package.json /app 或者 COPY /opt/xxx /app 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。

如果观察 docker build 输出,我们其实已经看到了这个发送上下文的过程。

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB

在默认情况下,如果不额外指定 Dockerfile 的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile。实际上 Dockerfile 的文件名也可以是任意名,并且并不要求必须位于上下文目录中,比如可以用-f ../Dockerfile.php 参数指定某个文件作为 Dockerfile。

Docker Hub
nginx
redis
mongo
mysql
httpd
php
tomcat
node
openjdk
python
ruby
golang
ubuntu
debian
centos
fedora
alpine