Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions docs/Ch08/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ icon: simple/docker

Docker 能够利用 Linux 内核的容器特性,隔离出一个轻便的环境来运行程序。这有什么意义呢?试想以下这些情况:

- 你运行的 Linux 发行版很老,而你需要运行一个更新版本的 Linux 发行版,或者完全不同的 Linux 发行版设计的程序。
- 你运行的 Linux 发行版很老,而你需要运行一个更新版本的 Linux 发行版,或者完全不同的 Linux 发行版设计的程序。基于 Docker 的实现方式,与虚拟机(VM)不同,它们都共用同一个 Linux 内核(虚拟机是完全的虚拟化,包括内核和用户空间)。
- 你和朋友在设计一个大型的程序,而因为你们配置的环境不同,有时候在某个人的机器上正常运行的程序,在另一台机器上没法正常运行。
- 你希望在多台服务器上部署一个项目,但是项目需要非常复杂的配置,一个一个配置服务器的成本非常大。
- …………

Docker 就可以帮助解决这些问题。它可以快速配置不同的环境(比如说,通过 Docker,你可以在 Ubuntu 上使用 CentOS 的环境),部署应用。
Docker 就可以帮助解决这些问题。它可以快速配置不同的环境(比如说,通过 Docker,你可以在 Ubuntu 发行版上使用 CentOS 发行版的环境),部署应用。

## 安装 Docker {#install-docker}

Expand Down Expand Up @@ -70,7 +70,7 @@ Docker 可以在 Windows, Linux 和 macOS 上安装。下面我们讨论内容
$ sudo adduser 用户名 docker
```

将需要使用 Docker 的用户[加入](../Ch05/index.md#adduser) `docker` 用户组。**注意:`docker` 用户组中的用户拥有与 root 等效的权限。**
将需要使用 Docker 的用户[加入](../Ch05/index.md#adduser) `docker` 用户组,以便使用命令行方式操作 Docker。**注意:`docker` 用户组中的用户拥有与 root 等效的权限。**

### 配置 Registry Mirror(可选,推荐) {#setup-registry-mirror}

Expand Down Expand Up @@ -115,13 +115,13 @@ For more examples and ideas, visit:

### 在 Ubuntu 容器中使用 shell {#use-ubuntu-bash}

- `docker run -it --rm --name ubuntu-container ubuntu:20.04`
- `docker run -it --rm --name ubuntu-container ubuntu:latest`

这里,`--rm` 代表容器停止运行(退出)之后,会被立刻删除;`--name` 参数代表给容器命名,如果没有加这个参数,那么 docker 会给容器随机起一个格式类似于 gracious_brahmagupta 的名字。

`-it` 是为了获得可交互的 Shell 所必须的。`-i` 会将容器的 init(主进程,这里是 `/bin/bash`)的标准输入与 `docker` 这个程序的标准输入相连接;而 `-t` 会告知主进程输入为终端(TTY)设备。

在执行以上命令之后,你会获得一个 Ubuntu 20.04 的容器环境,退出 Shell 之后容器就会被销毁。
在执行以上命令之后,你会获得一个 Ubuntu(版本为 `latest` 即最新的 LTS;如果需要指定版本,可以使用类似 `20.04` 的版本号替换 `latest`,推荐在生产环境中这么做,因为 `latest` 指定的最新版本可能随时间变化)的容器环境,退出 Shell 之后容器就会被销毁。

如果没有加上 `--rm`,退出后可以使用 `docker ps -a` 查看系统中所有的容器。

Expand Down Expand Up @@ -191,6 +191,27 @@ $ sudo docker rm ubuntu-container

## 构建自己的 Docker 镜像 {#build-docker-image}

### Docker 的关键概念

在继续之前,我们来梳理一下 Docker 中的几个关键概念:**容器(container)**、**镜像(image)**、**镜像仓库(registry)**。

- **镜像仓库**是存储镜像的地方
- **镜像**是 Docker 容器内文件系统的一份快照
- **Dockerfile** 包含生成镜像的指令序列,可以理解为构建镜像的脚本
- **容器**是一个(隔离)的运行环境

它们之间的关系可以用下图表示,其中括号中的命令是查看相应对象列表的命令。

```mermaid
flowchart TD
Registry -->|pull| Image["Image (images)"]
Image -->|run| Container["Container (ps)"]
Container -->|commit| Image
Image -->|push| Registry["Registry (search)"]

Dockerfile -->|build| Image
```

### 手工构建镜像 {#build-manually}

`docker commit` 命令可以从当前运行的容器新建镜像。以下是一个简单的例子:
Expand Down Expand Up @@ -246,7 +267,7 @@ CMD ["fish"]
sudo docker build -t riscv-cross:example .
```

`-t riscv-cross:example` 代表为这个镜像打上 `riscv-cross:example` 的标签。构建完成后,使用 `docker run` 执行即可:
`-t riscv-cross:example` 代表为这个镜像打上 `riscv-cross:example` 的标签,`.` 表示从当前目录下寻找 Dockerfile 并以当前目录作为构建过程的“工作路径”。构建完成后,使用 `docker run` 执行即可:

```console
$ sudo docker run -v ${PWD}/workspace:/workspace -it riscv-cross:example
Expand Down Expand Up @@ -303,7 +324,7 @@ Docker 在根据 Dockerfile 构建时,会从上到下执行这些指令,每
RUN yum clean all
```

当然,这不等于说必须要把所有命令都写在一条 `RUN` 里面。对于执行时间很长的命令,可以考虑放在 Dockerfile 的开头,并且使用单独的 `RUN` 运行,因为 Docker 在构建镜像时,可以重复使用之前构建好的层。这么做可以节约构建与调试 Dockerfile 的时间。
当然,这不等于说必须要把所有命令都写在一条 `RUN` 里面。对于执行时间很长的命令,可以考虑放在 Dockerfile 的开头,并且使用单独的 `RUN` 运行,因为 Docker 在构建镜像时,**可以重复使用之前构建好的层**。这么做可以节约构建与调试 Dockerfile 的时间。

#### 在生产环境中运行使用 Flask 编写的简单网站 {#flask-production-example}

Expand Down