mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-11 04:14:38 +00:00
style: apply global formatting fixes (struct, spacing, zhlint)
This commit is contained in:
@@ -2,17 +2,17 @@
|
||||
|
||||
从刚才的 `docker commit` 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
|
||||
|
||||
Dockerfile 是一个文本文件,其内包含了一条条的 **指令(Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
|
||||
Dockerfile 是一个文本文件,其内包含了一条条的**指令 (Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
|
||||
|
||||
### 使用 docker init 快速创建(推荐)
|
||||
### 使用 docker init 快速创建 (推荐)
|
||||
|
||||
Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Dockerfile、.dockerignore 和 compose.yaml 文件:
|
||||
Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Dockerfile、。dockerignore 和 compose.yaml 文件:
|
||||
|
||||
```bash
|
||||
$ docker init
|
||||
```
|
||||
|
||||
该命令会交互式地询问项目类型(如 Go、Node.js、Python、Rust 等),并生成符合最佳实践的配置文件。对于新项目,这是推荐的起步方式。
|
||||
该命令会交互式地询问项目类型 (如 Go、Node.js、Python、Rust 等),并生成符合最佳实践的配置文件。对于新项目,这是推荐的起步方式。
|
||||
|
||||
### 手动创建 Dockerfile
|
||||
|
||||
@@ -37,7 +37,7 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
|
||||
### FROM 指定基础镜像
|
||||
|
||||
所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 `nginx` 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 `FROM` 就是指定 **基础镜像**,因此一个 `Dockerfile` 中 `FROM` 是必备的指令,并且必须是第一条指令。
|
||||
所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 `nginx` 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 `FROM` 就是指定**基础镜像**,因此一个 `Dockerfile` 中 `FROM` 是必备的指令,并且必须是第一条指令。
|
||||
|
||||
在 [Docker Hub](https://hub.docker.com/search?q=&type=image&image_filter=official) 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 [`nginx`](https://hub.docker.com/_/nginx/)、[`redis`](https://hub.docker.com/_/redis/)、[`mongo`](https://hub.docker.com/_/mongo/)、[`mysql`](https://hub.docker.com/_/mysql/)、[`httpd`](https://hub.docker.com/_/httpd/)、[`php`](https://hub.docker.com/_/php/)、[`tomcat`](https://hub.docker.com/_/tomcat/) 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 [`node`](https://hub.docker.com/_/node)、[`openjdk`](https://hub.docker.com/_/openjdk/)、[`python`](https://hub.docker.com/_/python/)、[`ruby`](https://hub.docker.com/_/ruby/)、[`golang`](https://hub.docker.com/_/golang/) 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
|
||||
|
||||
@@ -52,7 +52,7 @@ FROM scratch
|
||||
|
||||
如果你以 `scratch` 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
|
||||
|
||||
不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 `FROM scratch` 会让镜像体积更加小巧。使用 [Go 语言](https://golang.google.cn/) 开发的应用很多会使用这种方式来制作镜像,这也是有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
|
||||
不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 `FROM scratch` 会让镜像体积更加小巧。使用 [Go 语言](https://golang.google.cn/)开发的应用很多会使用这种方式来制作镜像,这也是有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
|
||||
|
||||
### RUN 执行命令
|
||||
|
||||
@@ -72,9 +72,9 @@ Dockerfile 中每一个指令都会建立一层,`RUN` 也不例外。每一个
|
||||
>
|
||||
> 每一个 `RUN` 指令都会产生一个新的镜像层。为了减少镜像体积和层数,我们通常会将多个命令合并到一个 `RUN` 指令中执行。
|
||||
>
|
||||
> 更多关于 `RUN` 指令的详细用法、最佳实践(如清理缓存、使用 pipefail 等)及 `Union FS` 的层数限制等内容,请参阅 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)**中的**[RUN 指令](../07_dockerfile/7.1_run.md)** 小节。
|
||||
> 更多关于 `RUN` 指令的详细用法、最佳实践 (如清理缓存、使用 pipefail 等) 及 `Union FS` 的层数限制等内容,请参阅**[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)**中的** [RUN 指令](../07_dockerfile/7.1_run.md)**小节。
|
||||
|
||||
要想编写优秀的 `Dockerfile`,必须了解每一条指令的作用和副作用。在 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)** 中,我们将对 `COPY`, `ADD`, `CMD`, `ENTRYPOINT` 等指令进行详细讲解。
|
||||
要想编写优秀的 `Dockerfile`,必须了解每一条指令的作用和副作用。在**[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)**中,我们将对 `COPY`,`ADD`,`CMD`,`ENTRYPOINT` 等指令进行详细讲解。
|
||||
|
||||
### 构建镜像
|
||||
|
||||
@@ -104,11 +104,11 @@ docker build [选项] <上下文路径/URL/->
|
||||
|
||||
在这里我们指定了最终镜像的名称 `-t nginx:v3`,构建成功后,我们可以像之前运行 `nginx:v2` 那样来运行这个镜像,其结果会和 `nginx:v2` 一样。
|
||||
|
||||
### 镜像构建上下文(Context)
|
||||
### 镜像构建上下文
|
||||
|
||||
如果注意,会看到 `docker build` 命令最后有一个 `.`。`.` 表示当前目录,而 `Dockerfile` 就在当前目录,因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定 **上下文路径**。那么什么是上下文呢?
|
||||
如果注意,会看到 `docker build` 命令最后有一个 `.`。`.` 表示当前目录,而 `Dockerfile` 就在当前目录,因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定**上下文路径**。那么什么是上下文呢?
|
||||
|
||||
首先我们要理解 `docker build` 的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 [Docker Remote API](https://docs.docker.com/develop/sdk/),而如 `docker` 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 `docker` 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
|
||||
首先我们要理解 `docker build` 的工作原理。Docker 在运行时分为 Docker 引擎 (也就是服务端守护进程) 和客户端工具。Docker 的引擎提供了一组 REST API,被称为 [Docker Remote API](https://docs.docker.com/develop/sdk/),而如 `docker` 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 `docker` 功能,但实际上,一切都是使用的远程调用形式在服务端 (Docker 引擎) 完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
|
||||
|
||||
当我们进行镜像构建的时候,并非所有定制都会通过 `RUN` 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 `COPY` 指令、`ADD` 指令等。而 `docker build` 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?
|
||||
|
||||
@@ -120,7 +120,7 @@ docker build [选项] <上下文路径/URL/->
|
||||
COPY ./package.json /app/
|
||||
```
|
||||
|
||||
这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`,也不是复制 `Dockerfile` 所在目录下的 `package.json`,而是复制 **上下文(context)** 目录下的 `package.json`。
|
||||
这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`,也不是复制 `Dockerfile` 所在目录下的 `package.json`,而是复制**上下文 (context)** 目录下的 `package.json`。
|
||||
|
||||
因此,`COPY` 这类指令中的源文件的路径都是*相对路径*。这也是初学者经常会问的为什么 `COPY ../package.json /app` 或者 `COPY /opt/xxxx /app` 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。
|
||||
|
||||
@@ -146,6 +146,8 @@ Sending build context to Docker daemon 2.048 kB
|
||||
|
||||
### 其它 `docker build` 的用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 直接用 Git repo 进行构建
|
||||
|
||||
或许你已经注意到了,`docker build` 还支持从 URL 构建,比如可以直接从 Git repo 中构建:
|
||||
|
||||
Reference in New Issue
Block a user