跳转至内容

Docker

来自 ArchWiki

Docker 是一个用于将任何应用程序包装、交付和运行为轻量级容器的实用工具。

安装

要拉取 Docker 镜像并运行 Docker 容器,您需要 Docker Engine。Docker Engine 包含一个用于管理容器的守护进程,以及 docker 命令行界面 (CLI) 前端。

安装 docker 软件包。

接下来 启用并启动 docker.servicedocker.socket。请注意,docker.service 会在开机时启动服务,而 docker.socket 会在第一次使用时启动 Docker,这可以减少开机时间。然后验证 Docker 的状态

# docker info

请注意,由于 VPN 与 Docker 的桥接网络和覆盖网络 (overlay networks) 之间存在 IP 冲突,如果您有活动的 VPN 连接,启动 docker 服务可能会失败。如果是这种情况,请尝试在启动 docker 服务之前断开 VPN。之后可以立即重新连接 VPN。您也可以尝试解决网络冲突(参见解决方案 [1][2])。

接下来,验证您是否可以运行容器。以下命令会下载最新的 Arch Linux 镜像,并使用它在容器内运行 Hello World 程序

# docker run -it --rm archlinux bash -c "echo hello world"

要删除下载的 archlinux Docker 镜像,请参阅 #卸载 Docker 及镜像

如果您希望能够以非 root 用户身份运行 docker CLI 命令,请将您的用户添加到 docker 用户组,重新登录并重启 docker.service

警告: 任何被添加到 docker 组的用户都等同于拥有 root 权限,因为他们可以使用 docker run --privileged 命令来以 root 权限启动容器。更多信息请参阅 [3][4]

如果您计划使用 Docker 构建容器镜像,请安装 docker-buildx 以使用当前的构建器,而不是已弃用的旧版构建器。

Docker Compose

Docker Compose 是 Docker Engine 的另一种 CLI 前端,它使用 compose.yaml YAML 文件指定容器属性,而不是通过带有 docker run 选项的脚本。这对于设置经常使用且/或具有复杂配置的循环服务非常有用。要使用它,请 安装 docker-compose

Docker Desktop

Docker Desktop 是一款专有的桌面应用程序,它在 Linux 虚拟机中运行 Docker Engine。它还包含 Kubernetes 集群和漏洞扫描器等附加功能。该程序对于使用 macOS 和 Windows 开发 Docker 容器的软件开发团队非常有用。该应用程序的 Linux 端口相对较新,是对 Docker CLI 前端的补充 [5]

Docker 直接为 Arch 提供了一个实验性软件包;有关更多信息,请参阅 手册。不幸的是,它包含的文件与 docker-composedocker-buildx 软件包冲突,因此如果已安装这些软件包,您需要先将其卸载。或者,您可以安装 docker-desktopAUR 软件包。

此外,运行 Docker Desktop 需要确保满足 Linux 系统要求,包括通过 KVM 的虚拟化支持。要在 Gnome 下看到托盘图标,需要安装 gnome-shell-extension-appindicator

最后,文件共享支持需要通过 /etc/subuid/etc/subgid 映射用户和组 ID。有关更多详细信息,请参阅 Docker Desktop For Linux 文件共享说明

注意: Linux 上的 Docker Desktop 会运行一个虚拟机,并在启动时创建并使用自定义的 Docker 上下文 desktop-linux。这意味着(在安装前)部署在 Linux Docker Engine 上的镜像和容器在 Linux 版 Docker Desktop 中不可用。[6]

有关更多信息,请参阅 Docker Desktop for Linux 和 Docker Engine 之间有什么区别

此外,在 Linux 上使用 Docker Desktop 时,请做好性能下降和 CPU 使用率升高的准备。

默认情况下,Docker Desktop 会启用一个用户级 systemd 服务,该服务在启动时自动运行应用程序。在 Docker Desktop 控制面板中禁用 "Autostart" 设置 并不能 阻止此服务启动。要禁用自启动,请 禁用 docker-desktop.service 用户单元

前端

  • Ducker — 一个用于管理 docker 容器的终端应用。
https://github.com/robertpsoane/ducker || ducker
  • goManageDocker — 一个用于管理 docker 对象的 TUI 工具。
https://github.com/ajayd-san/gomanagedocker || gomanagedockerAUR
  • Lazydocker — 一个简单的 docker 和 docker-compose 终端 UI,由 Go 编写,使用了 gocui 库。
https://github.com/jesseduffield/lazydocker || lazydocker
  • oxker — 一个简单的 TUI,用于查看和控制 Docker 容器。
https://github.com/mrjackwills/oxker || oxker-binAUR
  • Podman Desktop — 从单个 UI 和托盘管理 Podman 及其他容器引擎。
https://github.com/containers/podman-desktop || podman-desktop
  • Portainer — 一个轻量级的 docker 管理 UI。
https://github.com/portainer/portainer || portainer-binAUR
  • Whaler — 为 Pantheon 设计的 Docker 容器管理。
https://github.com/sdv43/whaler || whaler-gitAUR

用法

Docker 由多个部分组成

  • Docker 守护进程(有时也称为 Docker Engine),它是以 docker.service 运行的进程。它提供 Docker API 并管理 Docker 容器。
  • docker CLI 命令,允许用户通过命令行与 Docker API 交互并控制 Docker 守护进程。
  • Docker 容器,它们是由 Docker 守护进程按照 Docker API 请求启动和管理的带有命名空间的进程。

通常,用户通过运行 docker CLI 命令来使用 Docker,这些命令进而请求 Docker 守护进程执行操作,从而实现对 Docker 容器的管理。理解客户端 (docker)、服务器 (docker.service) 和容器之间的关系对于成功管理 Docker 至关重要。

请注意,如果 Docker 守护进程停止或重启,所有当前运行的 Docker 容器也会停止或重启。

另外请注意,也可以不使用 docker CLI 命令直接向 Docker API 发送请求并控制 Docker 守护进程。有关更多信息,请参阅 Docker API 开发人员文档

有关更多使用文档,请参阅 Docker 入门指南

配置

Docker 守护进程可以通过 /etc/docker/daemon.json 配置文件进行配置,也可以通过在 docker.service systemd 单元中添加命令行标志进行配置。根据 Docker 官方文档,首选配置文件方法。如果您希望使用命令行标志,请使用 systemd drop-in 文件 来覆盖 docker.service 中的 ExecStart 指令。

有关 daemon.json 中选项的更多信息,请参阅 dockerd 文档

存储驱动

存储驱动控制镜像和容器在 Docker 主机上的存储和管理方式。对于大多数用例,默认的 overlay2 驱动具有良好的性能。

btrfsZFS 用户可以使用 btrfszfs 驱动,它们利用了这些文件系统的独特功能。有关更多信息和分步说明,请参阅 btrfs 驱动zfs 驱动 文档。

守护进程套接字 (Daemon socket)

默认情况下,Docker 守护进程使用位于 /var/run/docker.sockUnix 套接字 提供 Docker API 服务。对于大多数用例,这是一个合适的选项。

也可以配置守护进程额外监听一个 TCP 套接字,从而允许来自其他计算机的远程 Docker API 访问。[7] 这对于允许宿主机上的 docker 命令访问 Linux 虚拟机上的 Docker 守护进程非常有用,例如 Windows 或 macOS 系统上的 Arch 虚拟机。

警告: 默认情况下,Docker API 是未加密且未经验证的。除非同时也启用了使用 SSH 或 TLS 的附加保护,否则对 Docker 守护进程的远程 TCP 访问相当于无保护的远程 root 访问。

请注意,默认的 docker.service 文件默认设置了 -H 标志,如果一个选项同时出现在标志和 /etc/docker/daemon.json 文件中,Docker 将无法启动。因此,更改套接字设置最简单的方法是使用 drop-in 文件,例如以下内容,它在 2376 端口添加了一个 TCP 套接字

/etc/systemd/system/docker.service.d/docker.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376

重新加载 systemd 守护进程并 重启 docker.service 以应用更改。

HTTP 代理

配置 Docker 使用 HTTP 代理分为两个部分:配置 Docker 守护进程和配置 Docker 容器。

Docker 守护进程代理配置

参阅 关于配置 Docker 守护进程使用 HTTP 代理的 Docker 文档

Docker 容器代理配置

有关如何自动为所有使用 docker CLI 创建的容器配置代理的信息,请参阅 关于配置代理的 Docker 文档

配置 DNS

有关 Docker 容器内 DNS 的记录行为以及自定义 DNS 配置的信息,请参阅 Docker 的 DNS 文档。在大多数情况下,宿主机上配置的解析器也会配置在容器中。

由于容器和宿主机网络命名空间之间的冲突,不支持 大多数托管在 127.0.0.0/8 上的 DNS 解析器。这些解析器会 从容器的 /etc/resolv.conf 中删除。如果这导致 /etc/resolv.conf 为空,则改用 Google DNS。

此外,如果 127.0.0.53 是唯一配置的域名服务器,则会处理一个特殊情况。在这种情况下,Docker 假设解析器是 systemd-resolved,并使用来自 /run/systemd/resolve/resolv.conf 的上游 DNS 解析器。

如果您正在使用 dnsmasq 之类的服务提供本地解析器,请考虑添加一个在 169.254.0.0/16 块内具有链路本地 IP 地址的虚拟接口供 dnsmasq 绑定,而不是 127.0.0.1,以避免网络命名空间冲突。

镜像位置

版本 29 (2025-11) 起,新安装的默认镜像库已更改为 containerd。

使用 containerd 镜像库 时,默认情况下镜像内容和容器快照存储在 /var/lib/containerd/ 中。对于升级而来的旧安装,Docker 镜像仍然位于 /var/lib/docker/ 中。

要验证正在使用哪个镜像库

docker info -f '{{ .DriverStatus }}'

对于 containerd 镜像库,输出将是

[[driver-type io.containerd.snapshotter.v1]]

镜像存储位置是可以更改的,例如,如果您希望为镜像使用专用分区或磁盘,可以通过 配置数据根目录位置 来实现。

在更改任何内容之前,第一步是 停止 docker.service,这也会停止所有当前运行的容器并卸载任何运行中的镜像。

然后根据镜像库驱动编辑相应的配置文件

  • 如果使用 containerd 镜像库
/etc/containerd/config.toml
version = 2
root = "/path/to/containerd-data"
  • 如果使用传统的 Docker overlay 镜像库
/etc/docker/daemon.json
{
  "data-root": "/path/to/docker-data"
}

然后将内容从 /var/lib/containerd/var/lib/docker 移动到目标目录。

注意: 请注意,这是一个全局选项:在传统 Docker 镜像库的情况下,不可能只移动镜像,因此卷也将被移动。

最后,启动 docker.service 以应用更改。

不安全的仓库 (Insecure registries)

如果您决定为私有仓库使用自签名证书,Docker 会拒绝使用它,直到您声明信任它。例如,要允许来自托管在 myregistry.example.com:8443 的仓库的镜像,请在 /etc/docker/daemon.json 文件中配置 insecure-registries

/etc/docker/daemon.json
{
  "insecure-registries": [
    "my.registry.example.com:8443"
  ]
}

重启 docker.service 以应用更改。

IPv6

为了在 Docker 中启用 IPv6 支持,您需要做一些事情。详情请参阅 [8][失效链接 2025-03-15—HTTP 404][9]

首先,在 /etc/docker/daemon.json 中启用 ipv6 设置并设置一个特定的 IPv6 子网。在本例中,我们将使用私有的 fd00::/80 子网。确保使用至少 80 位的子网,因为这样可以允许容器的 IPv6 地址以容器的 MAC 地址结尾,从而减轻 NDP 邻居缓存失效问题。

/etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80"
}

重启 docker.service 以应用更改。

最后,为了让容器访问外部网络,您需要解决因使用私有 IPv6 子网而引起的路由问题。添加 IPv6 NAT 以便实际获得流量

# ip6tables -t nat -A POSTROUTING -s fd00::/80 ! -o docker0 -j MASQUERADE

现在 Docker 应该已经正确启用了 IPv6。要测试它,您可以运行

# docker run curlimages/curl curl -v -6 archlinux.org

如果您使用 firewalld,可以像这样添加规则

# firewall-cmd --zone=public --add-rich-rule='rule family="ipv6" destination not address="fd00::1/80" source address="fd00::/80" masquerade'

如果您使用 ufw,您需要首先按照 Uncomplicated Firewall#Forward policy 启用 ipv6 转发。接下来您需要编辑 /etc/default/ufw 并取消注释以下行

/etc/ufw/sysctl.conf
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1

然后您可以添加 iptables 规则

# ip6tables -t nat -A POSTROUTING -s fd00::/80 ! -o docker0 -j MASQUERADE

应当注意,对于使用 docker-compose 创建的 docker 容器,您可能需要在相应网络的 networks 部分设置 enable_ipv6: true。此外,您可能需要配置 IPv6 子网。详情请参阅 [10]

用户命名空间隔离

默认情况下,Docker 容器中的进程在与主 dockerd 守护进程相同的用户命名空间中运行,即容器没有通过 user_namespaces(7) 功能进行隔离。这允许容器内的进程根据 Users and groups#Permissions and ownership 访问宿主机上配置的资源。这最大限度地提高了兼容性,但如果发现允许容器访问宿主机上非预期资源的容器特权提升或突破漏洞,则会构成安全风险。(此类漏洞之一在 2019 年 2 月发布并打补丁。)

此类漏洞的影响可以通过启用用户命名空间隔离来减轻。这将在单独的用户命名空间中运行每个容器,并将该用户命名空间内的 UID 和 GID 映射到宿主机上不同的(通常是非特权的)UID/GID 范围。

  • dockerd 守护进程仍然以宿主机上的 root 运行。在 rootless 模式下运行 Docker 是一个不同的功能。
  • 容器中的进程以用于构建容器镜像的 Dockerfile 中的 USER 指令定义的用户身份启动。
  • 所有容器都映射到同一个 UID/GID 范围。这保留了在容器之间共享卷的能力。
  • 启用用户命名空间隔离有几个局限性
  • 启用用户命名空间隔离有效地屏蔽了 /var/lib/docker/ 中现有的镜像和容器层以及其他 Docker 对象,因为 Docker 需要调整这些资源的所有权。上游文档建议在新安装的 Docker 上启用此功能,而不是在现有安装上启用。

/etc/docker/daemon.json 中配置 userns-remapdefault 是一个特殊值,它将自动创建一个名为 dockremap 的用户和组,用于重新映射。

/etc/docker/daemon.json
{
  "userns-remap": "default"
}

/etc/subuid/etc/subgid 中配置用户名/组名、起始 UID/GID 和要分配给重新映射用户和组的 UID/GID 范围大小。本例中,为 dockremap 用户和组分配了从 165536 开始、大小为 65536 的 UID 和 GID 范围。

/etc/subuid
dockremap:165536:65536
/etc/subgid
dockremap:165536:65536

重启 docker.service 以应用更改。

应用此更改后,默认情况下所有容器都将在隔离的用户命名空间中运行。通过给 docker 命令传递 --userns=host 标志,可以对特定容器部分禁用重新映射。详情请参阅 [11]

Rootless Docker 守护进程

注意: Docker rootless 依赖于非特权用户命名空间 (CONFIG_USER_NS_UNPRIVILEGED)。这在 linuxlinux-ltslinux-zen 内核中默认启用。使用其他内核的用户可能需要手动启用它。这具有安全影响;详情请参阅 Security#Sandboxing applications

要以普通用户身份运行 Docker 守护进程,请 安装 docker-rootless-extrasAUR

通过分配 65,536 个从属 UID/GID 范围,为运行守护进程的用户配置 /etc/subuid/etc/subgid,例如

/etc/subuid
username:100000:65536
/etc/subgid
username:100000:65536
注意: 上游 rootless Docker 文档提到了运行 dockerd-rootless-setuptool.sh installdocker-rootless-extrasAUR 则是提供了 docker.servicedocker.socket 用户单元;启用其中之一并按如下所述配置客户端即可提供等效的设置。

docker.socketdocker.service 作为 用户单元 启用

最后,配置 Docker 客户端。

创建一个持久的 Docker 上下文

$ docker context create rootless --description "Rootless mode" \
  --docker "host=unix:///run/user/$(id -u)/docker.sock"
$ docker context use rootless

或者,将 DOCKER_HOST 环境变量 设置为 unix://$XDG_RUNTIME_DIR/docker.sock

提示: 要在没有交互式登录会话的情况下在引导时启动 rootless Docker 用户单元,请 开启用户驻留 (user lingering)

启用原生 overlay diff 引擎

首先检查它是否已经启用:运行 docker info 并检查 Native Overlay Diff 是否为 true

默认情况下,Docker 无法在 Arch Linux 上使用原生 overlay diff 引擎,这会导致构建 Docker 镜像变慢。如果您经常构建镜像,请按照 [12] 中所述配置原生 diff 引擎

/etc/modprobe.d/disable-overlay-redirect-dir.conf
options overlay metacopy=off redirect_dir=off

然后 停止 docker.service,按如下方式重新加载 overlay 模块

# modprobe -r overlay
# modprobe overlay

然后您可以再次 启动 docker.service

配置默认日志驱动

Docker 提供日志驱动,用于收集和查看运行在主机上的所有容器的日志数据。默认日志驱动 json-file 将日志数据写入主机文件系统上的 JSON 格式文件。随着时间的推移,这些日志文件体积会不断膨胀,可能导致磁盘资源耗尽。

为避免磁盘被日志数据过度占用,请考虑以下选项之一

/etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
/etc/docker/daemon.json
{
  "log-driver": "local"
}
  • 使用将日志发送到远程日志聚合器的日志驱动。

重启 docker.service 使更改对新创建的容器生效。现有容器不会自动使用新的日志配置。

镜像

Arch Linux

以下命令拉取 archlinux x86_64 镜像。这是 Arch 核心的一个精简版本,不含网络等功能。

# docker pull archlinux

另请参见 README.md

如需完整的 Arch 基础镜像,请克隆上方的仓库并构建您自己的镜像。

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

确保已安装 devtoolsfakechrootfakeroot 软件包。

要构建基础镜像

$ make image-base

Alpine Linux

Alpine Linux 是小型容器镜像的热门选择,特别是对于编译为静态二进制文件的软件。以下命令拉取最新的 Alpine Linux 镜像

# docker pull alpine

Alpine Linux 使用 musl libc 实现,而不是大多数 Linux 发行版使用的 glibc libc 实现。由于 Arch Linux 使用 glibc,Arch Linux 宿主机和 Alpine Linux 容器之间存在许多功能差异,这些差异可能会影响软件的性能和正确性。这些差异的列表记录在 这里

请注意,在 Arch Linux(或任何其他使用 glibc 的系统)上构建的动态链接软件在 Alpine Linux(或任何其他使用不同 libc 的系统)上运行时可能会出现错误和性能问题。请参阅 [13][14][15] 获取示例。

Debian

以下命令拉取最新的 debian 镜像

# docker pull debian

查看 Docker Hub 页面以获取可用标签的完整列表,包括每个 Debian 版本的标准版和精简版 (slim)。

Distroless

Google 维护着 distroless 镜像,这些镜像是没有包管理器或 shell 等 OS 组件的最小化镜像,从而产生用于打包软件的极小镜像。

查看 GitHub README 以获取镜像列表以及它们在各种编程语言中的使用说明。

技巧与提示

获取运行中容器的 IP 地址

要抓取运行中容器的 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

在容器内运行图形程序

本章节介绍允许图形程序(包括依赖 OpenGL 或 Vulkan 的程序)在宿主机的 X 服务器上运行的必要步骤。

首先,需要在容器内部安装与宿主机图形硬件兼容的正确驱动。安装过程取决于容器的类型,但对于基于 Arch Linux 镜像的容器,请参考 OpenGL#InstallationVulkan#Installation 获取适合您硬件的软件包。

接下来,必须授予容器访问宿主机 X 服务器的权限。在单用户环境中,可以通过在宿主机系统上运行 Xhost 轻松完成,这会将非网络的本地连接添加到访问控制列表中

$ xhost +local:

最后,需要将以下参数传递给 docker run

  • -e "DISPLAY=$DISPLAY" 将容器内的环境变量 DISPLAY 设置为宿主机的显示设备;
  • --mount type=bind,src=/tmp/.X11-unix,dst=/tmp/.X11-unix 将宿主机的 X 服务器套接字挂载到容器内的相同路径下;
  • --device=/dev/dri:/dev/dri 让容器访问宿主机上的 直接渲染架构 (Direct Rendering Infrastructure) 设备。

要确认所有设置是否正确,请在容器中运行来自 mesa-utils 软件包的 glxgears,或者来自 vulkan-tools 软件包的 vkcube

开机启动 Docker Compose 项目

本文或本章节的准确性存在争议。

原因:compose.yml 中设置 restart: always 就不需要这样做。 [16] (在 Talk:Docker#"Start Docker Compose projects on boot" Spurious? 中讨论)

首先,为 Docker Compose 创建一个由服务名称参数化的模板 单元 (unit)(参阅 systemd.service(5) § SERVICE TEMPLATES

/etc/systemd/system/docker-compose@.service
[Unit]
Description=%i service with docker compose
Requires=docker.service
After=docker.service

[Service]
WorkingDirectory=/opt/%i
ExecStartPre=-/usr/bin/docker compose pull
ExecStart=/usr/bin/docker compose up --remove-orphans
ExecStop=/usr/bin/docker compose down
ExecReload=/usr/bin/docker compose pull
ExecReload=/usr/bin/docker compose up --remove-orphans

[Install]
WantedBy=multi-user.target

然后,对于您想要运行的每个服务,在 /opt/project_name 设置一个包含 Compose 文件和任何其他所需文件(如 .env 文件)的目录。[17]

然后,启用并启动 docker-compose@project_name.service

使用 buildx 进行交叉编译

buildx CLI 插件 利用了新的 BuildKit 构建工具包安装 docker-buildx 软件包。buildx 接口支持构建多平台镜像,包括宿主机以外的架构。

交叉编译镜像需要 QEMU。要在 Docker 中设置 QEMU 的静态编译,请参阅 multiarch/qemu-user-static 镜像的使用信息。否则,要在宿主机系统上设置 QEMU 以配合 Docker 使用,请参阅 QEMU#Chrooting into arm/arm64 environment from x86_64。无论哪种情况,您的系统都将配置为用户模式模拟访客架构。

$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS  PLATFORMS
default * docker                  
  default default         running linux/amd64, linux/386, linux/arm64, linux/riscv64, linux/s390x, linux/arm/v7, linux/arm/v6

Docker 的多平台构建文档 中所述,构建多平台镜像必须使用 containerd 镜像库。例如,如果 docker buildx build --platform linux/amd64,linux/arm64 . 报错

ERROR: failed to build: Multi-platform build is not supported for the docker driver.
Switch to a different driver, or turn on the containerd image store, and try again.

请编辑 /etc/docker/daemon.json

/etc/docker/daemon.json
{
  "features": {
    "containerd-snapshotter": true
  }
}

然后 重启 Docker。

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

从 Docker 19.03 版本开始,NVIDIA GPU 已作为 Docker 设备原生支持NVIDIA Container Toolkit 是运行利用 NVIDIA GPU 的容器的推荐方式。

安装 nvidia-container-toolkit 软件包并 重启 docker。您现在可以使用 --gpus 选项或通过注册 NVIDIA 容器运行时来运行使用 NVIDIA GPU 的容器。

使用 --gpus 选项 (推荐)

# docker run --rm --gpus all nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

指定在容器内启用多少个 GPU

# docker run --rm --gpus 2 nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

指定要使用哪些 GPU

# docker run --rm --gpus '"device=1,2"' nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

或者

# docker run --rm --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

欲了解更多信息,请参阅 文档安装指南

本文或本章节的准确性存在争议。

原因: 需要更多关于以下错误何时发生的信息。它应该可以工作,见 [18][失效链接 2023-04-23—HTTP 404]。 (在 Talk:Docker#GPU accelerated Docker Nvidia 中讨论)

如果在运行上述命令时收到类似 Failed to initialize NVML: Unknown Error 的错误,可以尝试更具体地指定 GPU

# docker run --rm --gpus all --device /dev/nvidiactl:/dev/nvidiactl --device /dev/nvidia-uvm:/dev/nvidia-uvm --device /dev/nvidia0:/dev/nvidia0 nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

为容器指定一项功能 (capability)(graphics, compute...)(尽管很少有人会这样用)

# docker run --rm --gpus all,capabilities=utility nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

使用 NVIDIA 容器运行时

通过编辑 /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 --rm --runtime=nvidia nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi

另请参见 README.md

带有 CUDA 的 Arch Linux 镜像

您可以使用以下 Dockerfile 来构建带有 CUDA 的自定义 Arch Linux 镜像。它使用 Dockerfile 前端语法 1.2 来在宿主机上缓存 pacman 软件包。在构建 Docker 镜像之前,必须在客户端设置 DOCKER_BUILDKIT=1 环境变量

Dockerfile
# syntax=docker/dockerfile:1.2

FROM archlinux:base-devel

# Install packages
RUN --mount=type=cache,sharing=locked,target=/var/cache/pacman \
    pacman -Syu --noconfirm --needed cuda

# Configure nvidia container runtime
# https://github.com/NVIDIA/nvidia-container-toolkit/tree/main/cmd/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 system prune

若要额外删除任何停止的容器和所有未使用的镜像(不只是悬空的),请向命令添加 -a 标志

# docker system prune -a

删除所有 Docker 数据(清除目录)

# rm -R /var/lib/docker

故障排除

使用 systemd-networkd 时 docker0 网桥获取不到 IP / 容器内无法访问外网

Docker 尝试全局启用 IP 转发,但默认情况下 systemd-networkd 会为每个定义的网络配置文件覆盖全局 sysctl 设置。请在网络配置文件中设置 IPForward=yes。详情请参阅 Internet sharing#Enable packet forwarding

systemd-networkd 尝试管理 Docker 创建的网络接口时(例如,当您在 Match 部分配置了 Name=*Type=ether 时),可能会导致连接问题。应通过更具体地匹配接口来解决该问题,即避免使用 Name=*Type=ether 或其他匹配 Docker 管理的接口的通配符。确认 networkctl list 在 SETUP 列中为 Docker 创建的所有网络报告 unmanaged

  • 每当您 重启 systemd-networkd.serviceiptables.service 时,可能都需要 重启 docker.service
  • 还请注意,nftables 默认可能会阻止 docker 连接。使用 nft list ruleset 检查是否存在阻止规则。nft flush chain inet filter forward 可以暂时清除所有转发规则。编辑 /etc/nftables.conf 进行永久更改。记住 重启 nftables.service 以从配置文件重新加载规则。有关 Docker 中 nftables 支持的详情,请参阅 [19]

默认允许的进程/线程数过低

如果您遇到类似以下的错误消息

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

那么您可能需要调整 systemd 允许的进程数。通过以下代码段 编辑 docker.service

[Service]
TasksMax=infinity

更多背景信息,请在 systemd-system.conf(5) § OPTIONS 中查找 DefaultLimitNPROC。以及在 systemd.resource-control(5) § OPTIONS 中查找 TasksMax

初始化 graphdriver 错误: devmapper

本文或本节正考虑移除。

原因: (1) 删除数据目录是非常业余且有害的 (2) 根据链接的 Issue,device mapper 已被弃用 (在 Talk:Docker 中讨论)

如果 systemctl 无法启动 docker 并报错

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

那么,尝试以下步骤来解决错误。停止服务,备份 /var/lib/docker/(如果需要),删除 /var/lib/docker/ 的内容,然后尝试启动服务。详情请参阅 https://github.com/moby/moby/issues/21304

创建 path/to/file 失败: 设备上没有剩余空间

如果您收到如下错误消息

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

即使在您确实有足够可用磁盘空间的情况下,在构建或运行 Docker 镜像时出现此错,请确保:

  • Tmpfs 已禁用或分配了足够的内存。Docker 可能会尝试将文件写入 /tmp,但由于内存使用限制而非磁盘空间不足而失败。
  • 如果您正在使用 XFS,您可能需要从 /etc/fstab 中的相关条目(通常是 /tmp 和/或 /var/lib/docker 所在的位置)中删除 noquota 挂载选项。参考 磁盘配额 了解更多信息,尤其是如果您打算使用并调整 overlay2 Docker 存储驱动的大小。
  • XFS 配额挂载选项(uquota, gquota, prjquota 等)在重新挂载文件系统期间会失败。要为根文件系统启用配额,必须将挂载选项作为 内核参数 rootflags= 传递给 initramfs。随后,它不应被列在 /etc/fstab 中根 (/) 文件系统的挂载选项中。
注意: XFS 配额与标准 Linux 磁盘配额 之间存在一些差异,[20] 或许值得一读。

Docker-machine 使用 virtualbox 驱动创建虚拟机失败

如果 docker-machine 使用 virtualbox 驱动创建虚拟机失败,并显示以下内容

VBoxManage: error: VBoxNetAdpCtl: Error while adding new interface: failed to open /dev/vboxnetctl: No such file or directory

只需通过 CLI 使用 vboxreload 重新加载 virtualbox 即可。

启动 Docker 导致 KVM 桥接网络故障

问题在于 Docker 的脚本添加了一些 iptables 规则来阻止除其自身以外的其他接口上的转发。这是一个 已知问题

调整下面的解决方案,将 br0 替换为您自己的网桥名称。

最快的修复方法(但会关闭所有 Docker 自动添加的 iptables 调整,这可能不是您想要的)

/etc/docker/daemon.json
{
  "iptables": false
}

如果已经为 KVM 配置了网络网桥,可以通过告知 docker 来修复此问题。参阅 [21],其中 docker 配置被修改为

/etc/docker/daemon.json
{
  "bridge": "br0"
}

如果上述方法不起作用,或者您更喜欢直接通过 iptables 解决问题,或者通过 UFW 等管理器解决,请添加以下内容

iptables -I FORWARD -i br0 -o br0 -j ACCEPT

更详细的解决方案在 这里

从 Docker Hub 拉取镜像受到速率限制

从 2020 年 11 月 1 日开始,对于从匿名和免费帐户从 Docker Hub 下载的内容启用了速率限制。详情请参阅 速率限制文档

未验证的速率限制按源 IP 跟踪。已验证的速率限制按帐户跟踪。

如果您需要超过速率限制,可以 注册付费计划,或者将所需的镜像镜像到不同的镜像库。您可以 托管您自己的仓库,或使用云端仓库,例如 Amazon ECRGoogle Container RegistryAzure Container RegistryQuay Container Registry

要镜像一个镜像,请使用 Docker CLI 的 pulltagpush 子命令。例如,要将 Nginx 镜像的 1.19.3 标签镜像到托管在 cr.example.com 的仓库中

$ docker pull nginx:1.19.3
$ docker tag nginx:1.19.3 cr.example.com/nginx:1.19.3
$ docker push cr.example.com/nginx:1.19.3

然后,您可以从该镜像库拉取或运行镜像

$ docker pull cr.example.com/nginx:1.19.3
$ docker run cr.example.com/nginx:1.19.3

iptables (legacy): 未知选项 "--dport"

本文或本章节的准确性存在争议。

原因: Nftables#Working with Docker 建议不要使用 iptables。 (在 Talk:Docker 中讨论)

如果在运行容器时看到此错误,请安装 iptables 而非 iptables-legacy 并重启系统 [22]

运行 docker login 时提示 "您的密码将以明文存储"

默认情况下,Docker 会尝试使用 passsecretservice 二进制文件来存储您的仓库密码。如果找不到它们,它将以明文(base64 编码)形式将它们存储在 $HOME/.docker/config.json 中,并在成功登录后打印以下消息

$ WARNING! Your password will be stored unencrypted in /home/username/.docker/config.json.

如果您使用的密码管理器实现了 Secret Service Freedesktop DBUS API,如 KDE 的 kwallet 或 GNOME 的 gnome-keyring,您可以安装 docker-credential-secretserviceAUR 软件包将密码存储在其中。

"无法在默认池中找到可用的、不重叠的 IPv4 地址池分配给网络"

有时如果您使用了大量的 Docker 项目(例如使用 docker-compose),可能会耗尽 Docker 容器可用的 IP,从而触发错误

Could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

根据 这个 Docker Issue 发现,默认值为

类型 默认大小 默认池
local /16 172.17.0.0/12
local* /20 192.168.0.0/16

通过在 /etc/docker/daemon.json 中配置 default-address-pools,将第一个 IP 范围的大小值从 16 增加到 24,同时保持第二个不变以避免局域网 IP 冲突,可以轻松修复增加 Docker IP 空间的问题

/etc/docker/daemon.json
{
  ...
  "default-address-pools" : [
    {
      "base" : "172.17.0.0/12",
      "size" : 24
    },
    {
      "base" : "192.168.0.0/16",
      "size" : 24
    }
  ]
}

重启 docker.service 以应用更改。

更多详情和技术解释可在以下优秀文章中找到:docker default-address-pools 选项的最终指南

golang 编译缓慢

由于 ulimit 配置的原因,使用 makepkg 构建 docker 镜像及其依赖项的速度非常慢(卡在 "Entering fakeroot environment..." 步骤)。

这与 [23][24] 有关。

您可以将 --ulimit "nofile=1024:524288" 添加到您的 docker build 选项中,或者创建/编辑

/etc/docker/daemon.json
{
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Soft": 1024,
      "Hard": 524288
    }
  }
}

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.