Docker (简体中文) - ArchWiki

Jump to content

这篇文章或章节的翻译不反映原文。

原因：Out of sync with the English page.（在 Talk:Docker (简体中文)# 中讨论）
翻译状态：本文是 Docker 的翻译。上次翻译日期：2018-10-22。如果英文版本有所更改，则您可以帮助同步翻译。

相关文章

- systemd-nspawn
- Linux Containers
- Vagrant

Docker 是一种打包、传输和运行任何程序作为轻量级容器的实用工具.

## 安装

安装 docker 包 或者，对于开发版本，选择docker-gitAUR 包. 下一步 启动 `docker.service` 然后验证操作:

    # docker info

注意, 如果你有一个活动的 VPN 连接, 那么 docker 服务的启动可能失败, 因为 VPN 和 Docker 的网桥 IP 冲突以及网络覆盖. 如果发生了这种事, 尝试在启动 docker 服务之前断开 VPN 连接. 你可以在之后立刻重连 VPN. You can also try to deconflict the networks.

如果你想以普通用户身份运行docker的话，添加你自己到 `docker` 用户组，重新登录并重启`docker.service`

警告： 任何加入到 `docker` 组的用户都和root用户等价，因为他们可以通过`# docker run --privileged`来以root权限启动容器。 查阅更多信息可访问 这里 和 这里.

## 配置

### 存储驱动程序

docker存储驱动 (或者是显卡驱动) 对性能有巨大影响. 它的工作是高效存储容器镜像层，也就是许多镜像共享一个层时只有一个层使用磁盘空间。作为兼容选项, `devicemapper` 提供了次优性能, 这在机械硬盘上是非常糟糕的. 例外, `devicemapper` 不建议在生产中使用.

随着arch Linux发布新的内核，没有必要使用兼容选项了。一个好的现代选择是 `overlay2`.

想看现在的存储驱动, 运行 `# docker info | head`; 现代docker安装应该已经默认使用 `overlay2` 了.

想设置你自己的存储驱动选项, 编辑 `/etc/docker/daemon.json` (如果不存在就自己创建):

    /etc/docker/daemon.json

    {
      "storage-driver": "overlay2"
    }

然后, 重启 docker.

更多的选项信息能在 用户指南查阅. 更多的 `daemon.json` 选项查阅 docker 文档.

### 远程 API

手动打开远程 API 端口 `4243` , 运行:

    # /usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock

`-H tcp://0.0.0.0:4243` 部分是用来打开远程 API的.

`-H unix:///var/run/docker.sock` 部分是通过终端连接主机的.

#### 用systemd打开远程API

如果要用docker守护进程开启远程API, 创建一个 Drop-in snippet ，内容如下:

    /etc/systemd/system/docker.service.d/override.conf

    [Service]
    ExecStart=
    ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock

### 守护进程socket配置

docker 守护进程默认监听 Unix socket .如果要监听特定端口的话, 创建一个 Drop-in snippet ，内容如下:

    /etc/systemd/system/docker.socket.d/socket.conf

    [Socket]
    ListenStream=0.0.0.0:2375

### 代理

代理配置分为两部分。一部分是主机docker守护进程的配置，另一部分是让容器检测到代理的配置

#### 代理配置

创建一个 Drop-in snippet 内容如下:

    /etc/systemd/system/docker.service.d/proxy.conf

    [Service]
    Environment="HTTP_PROXY=192.168.1.1:8080"
    Environment="HTTPS_PROXY=192.168.1.1:8080"

注意： 这假定 `192.168.1.1` 是你的代理服务器，不要使用 `127.0.0.1`.

确定配置被加载了:

    # systemctl show docker --property Environment

    Environment=HTTP_PROXY=192.168.1.1:8080 HTTPS_PROXY=192.168.1.1:8080

#### 容器配置

在 `docker.service` 文件里的设置并不会进入到容器里. 要实现这样的话必须设置 `ENV` 变量在你的 `Dockerfile` 里:

    FROM base/archlinux
    ENV http_proxy="http://192.168.1.1:3128"
    ENV https_proxy="https://192.168.1.1:3128"

Docker 提供了配置的细节信息，通过Dockerfile的 `ENV` .

### 配置 DNS

默认的，docker会让容器里的 `resolv.conf` 和主机里的 `/etc/resolv.conf` 匹配, 并过滤掉本地地址 (e.g. `127.0.0.1`). 如果这产生了一个空文件, 那么 Google DNS servers 就会被使用. 如果你用的是 dnsmasq (简体中文) 一样的服务来提供域名解析的话, 你可能需要在 `/etc/resolv.conf` 添加入口给docker网络接口让它不被过滤掉.

### 在systemd-networkd用手动定义的网络运行Docker

如果你是手动配置的网络，用的是 systemd-networkd 版本 220 或者更高, 你运行的容器可能无法连接网络. 从版本 220开始, 对于给定网络 (`net.ipv4.conf.<interface>.forwarding`) 的转发设置默认是 `off`. 这个设置阻止了IP转发. 它会与在容器里启用了 `net.ipv4.conf.all.forwarding` 设置的docker冲突

一个解决办法是编辑 在`/etc/systemd/network/`里的`<interface>.network`文件 , 添加 `IPForward=kernel` 到docker主机:

    /etc/systemd/network/<interface>.network

    [Network]
    ...
    IPForward=kernel
    ...

这项设置像预期一样允许来自容器的IP转发.

### 镜像位置

默认，docker镜像放置在 `/var/lib/docker`. 他们可以被移动到其他分区. 首先, 停止 the `docker.service`.

如果你正在运行docker镜像，你必须确定镜像被完全解除挂载。一旦这个完成后，你就可以把镜像从 `/var/lib/docker` 移动到你的目标地点.

然后为`docker.service`添加 Drop-in snippet，加入 `-g` 参数到 `ExecStart`:

    /etc/systemd/system/docker.service.d/docker-storage.conf

    [Service]
    ExecStart=
    ExecStart=/usr/bin/dockerd --data-root=/path/to/new/location/docker -H fd://

### 不安全的注册

如果你想用自签名的证书, docker会拒绝它直到你定义你相信它. 为`docker.service`添加 Drop-in snippet, 添加 `--insecure-registry`参数到 `dockerd`:

    /etc/systemd/system/docker.service.d/override.conf

    [Service]
    ExecStart=
    ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry my.registry.name:5000

## 镜像

### Arch Linux

下面的命令会拉取 archlinux x86_64 image.这是一个arch内核的剥离版本，没有网络等等.

    # docker pull archlinux

也可查阅 README.md.

对于完整的arch基础，可以从下面克隆镜像并且建立你自己的镜像.

    $ git clone https://gitlab.archlinux.org/archlinux/archlinux-docker.git

编辑包文件让它只含有 '基础'. 运行:

    # make docker-image

### Debian

下面的命令会拉取Debian镜像 debian x86_64 image.

    # docker pull debian

#### 手动

用 debootstrap建立Debian镜像:

    # mkdir jessie-chroot
    # debootstrap jessie ./jessie-chroot http://http.debian.net/debian/
    # cd jessie-chroot
    # tar cpf - . | docker import - debian
    # docker run -t -i --rm debian /bin/bash

## 用NVIDIA GPU运行GPU加速的Docker容器

### 使用NVIDIA Container Toolkit (推荐)

从19.03版本开始，Docker原生支持NVIDIA GPU作为Docker设备。 推荐使用NVIDIA Container Toolkit来运行需要操作NVIDIA显卡的容器。 安装 nvidia-container-toolkitAUR 包并重启Docker。之后可以用`--gpus`选项来运行使用NVIDIA显卡的容器

    # docker run --gpus all nvidia/cuda:9.0-base nvidia-smi

指定容器内可使用多少GPU：

    # docker run --gpus 2 nvidia/cuda:9.0-base nvidia-smi

指定使用哪一个GPU：

    # docker run --gpus '"device=1,2"' nvidia/cuda:9.0-base nvidia-smi

或

    # docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:9.0-base nvidia-smi

指定需要的具体功能（图像、计算等）

    # docker run --gpus all,capabilities=utility nvidia/cuda:9.0-base nvidia-smi

参阅 README.md 与 Wiki.

### 使用 NVIDIA Container Runtime

安装 nvidia-container-runtimeAUR 包. 之后，编辑`/etc/docker/daemon.json`以注册NVIDIA运行时环境。

    /etc/docker/daemon.json

    {
      "runtimes": {
        "nvidia": {
          "path": "/usr/bin/nvidia-container-runtime",
          "runtimeArgs": []
        }
      }
    }

之后重启 Docker。

运行时也可以通过dockerd的一个命令行选项来注册。

    # /usr/bin/dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime

完成后可通过命令启动GPU加速的容器:

    # docker run --runtime=nvidia nvidia/cuda:9.0-base nvidia-smi

或 （要求 Docker 版本19.03或更高）

    # docker run --gpus all nvidia/cuda:9.0-base nvidia-smi

参阅 README.md.

### 使用 nvidia-docker (已废弃)

nvidia-docker is a wrapper around NVIDIA Container Runtime which registers the NVIDIA runtime by default and provides the nvidia-docker command.

To use nvidia-docker, install the nvidia-dockerAUR package and then 重启 docker. Containers with NVIDIA GPU support can then be run using any of the following methods:

    # docker run --runtime=nvidia nvidia/cuda:9.0-base nvidia-smi

    # nvidia-docker run nvidia/cuda:9.0-base nvidia-smi

or (required Docker version 19.03 or higher)

    # docker run --gpus all nvidia/cuda:9.0-base nvidia-smi

注意： nvidia-docker 是直到Docker 19.03版本，运行 NVIDIA GPU加速的容器的遗留方法，已被废弃。如果使用19.03版本或更高Docker，建议使用NVIDIA Container Toolkit 替代。

### 有CUDA的 Arch Linux 镜像

可使用以下`Dockerfile` 构建自定义的有CUDA的 Arch Linux 镜像。它使用 Dockerfile frontend syntax 1.2 在宿主机上缓存pacman包。`DOCKER_BUILDKIT=1` environment variable 必须于构建镜像之前设置。

    Dockerfile

    # syntax = docker/dockerfile:1.2

    FROM archlinux

    # 使用更快的镜像
    RUN echo 'Server = https://mirror.pkgbuild.com/$repo/os/$arch' > /etc/pacman.d/mirrorlist

    # 安装包
    RUN --mount=type=cache,sharing=locked,target=/var/cache/pacman \
        pacman -Syu --noconfirm --needed base base-devel cuda

    # 配置 nvidia container runtime
    # https://github.com/NVIDIA/nvidia-container-runtime#environment-variables-oci-spec
    ENV NVIDIA_VISIBLE_DEVICES all
    ENV NVIDIA_DRIVER_CAPABILITIES compute,utility

## 移除docker和镜像

如果你想完全移除Docker，你可以通过下面的步骤完成:

注意： 不要仅仅只是复制粘贴下面的命令而不知道你在干什么.

检查正在运行的容器:

    # docker ps

列出在主机运行的所有容器，为删除做准备:

    # docker ps -a

停止一个运行的容器:

    # docker stop <CONTAINER ID>

杀死还在运行的容器:

    # docker kill <CONTAINER ID>

通过ID删除列出的所有容器:

    # docker rm <CONTAINER ID>

列出所有的docker镜像:

    # docker images

通过ID删除所有镜像:

    # docker rmi <IMAGE ID>

删除所有docker数据 (清除目录):

The factual accuracy of this article or section is disputed.

Reason: 执行 # rm -R /var/lib/docker 将会留下已删除容器的btrfs子卷 (Discuss in Talk:Docker (简体中文))

    # rm -R /var/lib/docker

## 有用的建议

抓取运行容器的IP地址:

    $ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container-name OR id>

    172.17.0.37

每个正在运行的容器，它们的名字和相关IP地址都能被列出来在 `/etc/hosts`里用:

    #!/usr/bin/env sh
    for ID in $(docker ps -q | awk '{print $1}'); do
        IP=$(docker inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" "$ID")
        NAME=$(docker ps | grep "$ID" | awk '{print $NF}')
        printf "%s %s\n" "$IP" "$NAME"
    done

## 故障排除

### docker0 网桥无法获取 IP / internet 到容器

Docker会自己启用IP转发，但是默认 systemd-networkd 会覆盖对应的sysctl设置. 在网络配置文件里设置 `IPForward=yes` . 查阅 Internet sharing#Enable packet forwarding 获取细节.

注意： 你可能需要在每次 restart `systemd-networkd.service` 或者 `iptables.service` 之后手动重启 `docker.service`

### 默认的允许的进程/线程数太少

如果你允许时得到下面的错误信息

    # e.g. Java
    java.lang.OutOfMemoryError: unable to create new native thread
    # e.g. C, bash, ...
    fork failed: Resource temporarily unavailable

那么你可能需要调整被systemd允许的进程数. 默认的是 500 (see `system.conf`), 这对需要允许几个容器的话太少了. Edit 并添加下面片段 `docker.service` :

    # systemctl edit docker.service

    [Service]
    TasksMax=infinity

### 初始化显卡驱动错误: devmapper

如果 systemctl 不能开启docker并提供了以下信息:

    Error starting daemon: error initializing graphdriver: devmapper: Device docker-8:2-915035-pool is not a thin pool

那么尝试以下步骤来解决错误。停止docker服务，备份 `/var/lib/docker/` (如果需要的话), 移除`/var/lib/docker/`的内容, 尝试重启docker服务. 查阅 GitHub issue 获取更多细节.

### 无法创建到某文件的路径: 设备没有多余的空间了

如果你获取到的错误信息是像这样的话:

    ERROR: Failed to create some/path/to/file: No space left on device

当创建或者运行Docker镜像时，尽管磁盘还有多余的空间。所以请确保:

- Tmpfs 被禁用了并且有足够的内存分配. Docker可能会尝试写入文件到 `/tmp` 但是失败了因为内存使用的限制和磁盘空间不足.
- 如果你在使用 XFS (简体中文), 你可能得从相关入口移除 `noquota` 挂载选项在 `/etc/fstab`里 (通常是 `/tmp` 和/或 `/var/lib/docker` 在的地方). 查阅 Disk quota 获取更多信息, 特别是你计划使用和调整 `overlay2` Docker 存储驱动.
- XFS 的配额挂载选项在文件系统重新挂载时 (`uquota`, `gquota`, `prjquota`, 等等.) 失败了. 为了为root文件系统启用配额挂载选项必须作为 Kernel parameters (简体中文) `rootflags=`传递到initramfs. 之后, 它就不应该在 `/etc/fstab`中的挂载选项中列出root (`/`) 文件系统.

注意： XFS配额和标准LinuxDisk quota, [1] 是有区别的。这里值得一读.

### kernel 4.19.1下无效的跨设备链接

如果像 dpkg 这样的命令在docker运行失败, 比如:

    dpkg: error: error creating new backup file '/var/lib/dpkg/status-old': Invalid cross-device link

可以 添加 `overlay.metacopy=N` kernel parameter 或者降级到 4.18.x 直到 这个 issue 被解决. 更多信息查看 Arch forum.

## 查阅更多

- Official website
- Arch Linux on docs.docker.com
- Are Docker containers really secure? — opensource.com

Categories:

- Sandboxing (简体中文)
- Virtualization (简体中文)

Hidden categories:

- Pages or sections flagged with Template:Bad translation (简体中文)
- Pages or sections flagged with Template:Accuracy