Docker
Docker 是一种打包、传输和运行任何程序作为轻量级容器的实用工具.
安装[编辑 | 编辑源代码]
要拉取Docker镜像并运行Docker容器,你需要安装Docker引擎,其包含包括一个守护进程来管理容器,以及一个docker
命令行界面前端。安装 docker包 包 或者,对于开发版本,选择docker-gitAUR 包. 下一步启动 docker.service
或者 docker.socket
。两者的差距在于docker.service
将会在开机时启动,而docker.socket
将会在第一次启动Docker时启动,使用后者可以减少开机启动时间。然后验证操作:
# docker info
注意, 如果你有一个活动的 VPN 连接, 那么 docker 服务的启动可能失败, 因为 VPN 和 Docker 的网桥 IP 冲突以及网络覆盖. 如果发生了这种事, 尝试在启动 docker 服务之前断开 VPN 连接. 你可以在之后立刻重连 VPN. 你也可以尝试手动解决网络冲突(也可参见[1]或[2])。
你也可以尝试验证是否可以运行容器。以下命令行将会下载一个最新的Arch Linux image,并使用其在这个容器中运行一个Hello World程序:
# docker run -it --rm archlinux bash -c "echo hello world"
如果你想以普通用户身份运行docker的话,添加你自己到 docker
用户组,重新登录并重启docker.service
如果你还要使用 Docker 构建容器镜像,请安装docker-buildx包以使用新版构建器(否则会使用已弃用的旧版构建器)。
Docker Compose[编辑 | 编辑源代码]
Docker Compose是另一种Docker引擎的CLI前端,它使用compose.yaml
YAML文件来指定容器的属性,这样就可以不使用附带指令的docker run
脚本了.如果你需要经常设置或者使用具有复杂选项的容器,可能使用docker-compose更为方便.你需要安装 docker-compose包来使用.
Docker Desktop[编辑 | 编辑源代码]
Docker Desktop是一个专有的桌面应用程序,它在一个Linux虚拟机中运行Docker。它还包括Kubernetes集群以及一个漏洞扫描器。这个应用程序对于在macOS或Windows上进行开发Docker容器的团队非常友好。Docker Desktop适配的Linux版本相对较新,同时也保持了对Docker CLI的良好兼容[3]。
Docker直接为Arch Linux提供了一个实验性的软件包(参见其官方文档手动安装Docker一节)。需要注意其手动下载的软件包会与docker-compose包以及docker-buildx包冲突,你需要在安装前手动移除这两个包。如果你想保留现有的软件包,你也可以从AUR安装docker-desktopAUR,它将不会与现有软件包发生冲突。
此外,在运行Docker Desktop之前,你需要确保你已经安装了所有的在Linux上运行的最小系统要求,包括使用KVM进行虚拟化技术支持。对于Gnome用户,你还需要安装gnome-shell-extension-appindicator包以显示托盘图标。
最后,请注意文件共享功能是通过/etc/subuid
和/etc/subgid
映射用户和组ID完成的。详细参见Docker Desktop的Linux文件共享说明。
desktop-linux
。
这意味着在安装前,部署在Linux Docker引擎上的所有镜像与容器都无法在Docker Desktop中使用。[4]此外,由于Docker Desktop是在VM上启动的,相比直接使用Docker引擎,预期性能会下降并且 CPU 使用率会提高。
GUI 工具[编辑 | 编辑源代码]
- ducker包 — 一个用于管理docker容器的终端应用程序。
- oxker-binAUR — 一个简单的 TUI程序,用于查看和控制 Docker 容器。
- lazydockerAUR — 一个简单的 docker 和 docker-compose 管理TUI程序,使用 Go 语言和 gocui 库编写。
- dokoAUR — 一个简单的docker TUI程序。
- gomanagedockerAUR — 一款用于管理 Docker 对象的 TUI 程序。
- dockstationAUR — 轻松管理 Docker。
- whaler-gitAUR — 为 Pantheon 设计的 Docker 容器管理。
- podman-desktopAUR — 从单一的用户界面和托盘管理 Podman以及其他容器引擎。
- portainer-binAUR — 一款轻量级的 Docker 管理用户界面。
- kitematicAUR — 可视化Docker 容器管理。
使用[编辑 | 编辑源代码]
Docker由多个部分组成:
- Docker守护进程(也称Docker引擎),这是一个以
docker.service
形式运行的进程。其提供了Docker API接口并管理Docker容器。
docker
CLI命令,其允许用户使用命令行来与Docker API交互,并控制 Docker 守护进程。
- Docker容器,这是一种命名进程,由Docker守护进程通过Docker API的请求进行管理。
一般来说,用户通过使用docker
命令行来对Docker进行操作,命令行又通过Docker API对Docker守护进程发起请求以执行对容器的相关操作。掌握客户端 (docker
), 服务端(docker.service
)和容器之间的关系是很必要的。
请注意,如果Docker守护进程停止/重启,那么当前运行的所有Docker容器也会停止/重启。
你也可以不借助docker
CLI来对Docker API发起请求来控制容器,参见Docker API开发指南。
更多使用文档请参见Docker入门指南。
配置[编辑 | 编辑源代码]
Docker守护进程可以通过修改配置文件/etc/docker/daemon.json
或者直接在docker.service
中添加命令行标志来进行配置。根据Docker官方文档, 推荐使用修改配置文件的方法进行配置。如果你想使用添加命令行标志的方法进行配置,使用Systemd#附加配置片段覆盖docker.service
中的ExecStart
部分。
对于daemon.json
中的选项,参见守护进程配置文件参考。
存储驱动程序[编辑 | 编辑源代码]
存储驱动程序控制着Docker主机上的镜像与容器的储存与管理方式。默认的overlay2
驱动在大部分情况下都具有良好的性能。
如果你的文件系统使用的是btrfs或者ZFS,你可以使用对应的btrfs
或者zfs
驱动,它们可以利用这些文件系统独有的功能,要使用这些驱动请参见btrfs驱动或zfs驱动文档。
启用守护进程TCP套接字[编辑 | 编辑源代码]
默认情况下,Docker守护进程使用位于/var/run/docker.sock
的Unix套接字来提供Docker API。大部分情况下,这是一个合适的选择。
你可以将设置守护进程设置为额外监听TCP套接字,这样就能使Docker API被远程访问了(参见允许远程访问Docker API)。如果你在Windows或macOS上使用Arch虚拟机,你可以在完成设置后使用宿主机上直接使用docker
命令行访问虚拟机中允许的Docker守护进程。
注意默认的docker.service
设置了-H
标志,如果选项同时存在于标志与/etc/docker/daemon.json
文件中,Docker将不会启动,因此最简单的更改监听TCP套接字设置的方法是使用一个附加文件。例如,如果你想在端口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文档:配置Docker守护进程使用HTTP代理。
Docker容器代理设置[编辑 | 编辑源代码]
参见Docker文档:如何配置代理,使用docker
CLI来自动为所有容器配置代理。
配置DNS[编辑 | 编辑源代码]
参见Docker中网络配置了解Docker容器内部的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来提供一个本地解析器,考虑为dnsmasq添加一个虚拟接口(使用169.254.0.0/16
网段的链路本地IP地址来绑定,而不是127.0.0.1
)以避免网络命名空间冲突。
镜像位置[编辑 | 编辑源代码]
默认,docker镜像放置在 /var/lib/docker
。他们可以被移动到其他分区,例如你想将镜像移动到别的磁盘上,在这个例子中,假设我们要将镜像移动到/mnt/docker
。
首先, 停止docker.service
,注意,这也会停止所有当前运行的容器并卸载任何正在运行的镜像。
如果你正在运行docker镜像,你必须确定镜像被完全解除挂载。一旦这个完成后,你就可以把镜像从 /var/lib/docker
移动到你的目标地点。在这个例子中使用指令cp -r /var/lib/docker /mnt/docker
。
在/etc/docker/daemon.json
中配置data-root
:
/etc/docker/daemon.json
{ "data-root": "/mnt/docker" }
重启docker.service
以应用更改。
不安全的自建仓库[编辑 | 编辑源代码]
如果您使用自签名证书的仓库(registries),或该自建仓库未使用TLS加密(即:http), 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[编辑 | 编辑源代码]
首先,将/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 NAT以解决使用私有IPv6子网时出现的路由问题:
# 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#转发策略创建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来创建的容器,你可能还需要在networks
中对应的部分设置enable_ipv6: true
。另外,你可能还需要手动指定IPv6子网,参见compose-file中的ipv6地址设置。
用户命名空间隔离[编辑 | 编辑源代码]
默认情况下,Docker中的进程和dockerd
主守护程序运行在同一用户命名空间中,即容器不会通过用户命名空间隔离(参见user_namespaces(7))。这将会允许进程根据用户和用户组#权限与属主在主机上来访问已配置的资源。这样提升了容器运行的兼容性,但是一旦出现了一个允许容器中进程访问非预期资源的漏洞,这会带来很大的安全隐患。(一个这样的漏洞在2019年2月发布并修补。)
启用用户命名空间隔离可以降低此类漏洞的影响。其将会在单独的用户命空间中运行每个容器,并将这个空间中的UIDs/GIDs映射到主机上不同的(通常情况下也是非特权的)UIDs/GIDs。
- 主
dockerd
守护程序依然是以root
身份在主机上运行的,在非root身份下运行docker(rootless mode)是另一个功能。 - 容器中的进程将会以Dockerfile中定义的USER指令定义的用户身份启动。
- 所有容器都会映射到相同的UID/GID范围,这是为了让容器之间的共享卷功能生效。
- 在一些情况下无法启用用户命名空间。
- 由于 Docker 需要调整这些资源的所有权,因此启用用户命名空间隔离会有效屏蔽现有的映像层和容器层,以及
/var/lib/docker/
中的其他 Docker 对象。上游文档建议仅在新安装的Docker上启用此功能,而不是在现有的Docker上启用。
在/etc/docker/daemon.json
中配置userns-remap
的值。default
是一个特殊值,其会自动创建名为dockremap
的用户与用户组用于重映射。
/etc/docker/daemon.json
{ "userns-remap": "default" }
在/etc/subuid
和/etc/subgid
中配置用户名/组名,UID/GID的范围。在这个例子中,dockremap
用户/用户组分配为从165536开始的65536个UIDs/GIDs。
/etc/subuid
dockremap:165536:65536
/etc/subgid
dockremap:165536:65536
重启docker.service
以应用更改。
应用此更改后,默认情况下所有容器都将在隔离的用户命名空间中运行。你也可以在docker
命令中加上添加标志--userns=host
来在特定的容器中禁用用户命名空间隔离,参见[7]。
无根模式运行Docker守护程序(Docker rootless)[编辑 | 编辑源代码]
CONFIG_USER_NS_UNPRIVILEGED
)。在linux包, linux-lts包, 和linux-zen包内核中默认启用这一功能。如果你使用其他版本的内核,你可能需要手动启用这一功能。这可能带来一些安全隐患,参见安全#沙盒程序。要将Docker守护程序作为普通用户运行,安装 docker-rootless-extrasAUR软件包。
随后在/etc/subuid
与/etc/subgid
中配置用户名/用户组名,起始 UID/GID 和 UID/GID 范围大小,以分配重新映射的用户和组。以下是一个示例:
/etc/subuid
your_username:165536:65536
/etc/subgid
your_username:165536:65536
启用 docker.socket
systemd/用户单元: 这将会使用systemd的套接字激活来启动docker。
最后设置docker套接字的环境变量:
$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
启用本地覆盖差异引擎(native overlay diff engine)[编辑 | 编辑源代码]
默认情况下Docker无法在Arch Linux上使用本地覆盖差异引擎(native overlay diff engine),这会导致构建Docker镜像很慢。如果你经常构建镜像,请按照以下步骤配置:
/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 info
检查Native Overlay Diff
值是否为true
。
镜像[编辑 | 编辑源代码]
Arch Linux[编辑 | 编辑源代码]
下面的命令会拉取 archlinux x86_64 image.这是一个arch内核的剥离版本,没有网络等等.
# docker pull archlinux
也可查阅 README.md.
对于完整的arch基础,可以从下面克隆镜像并且建立你自己的镜像.
$ git clone https://gitlab.archlinux.org/archlinux/archlinux-docker.git
请确保devtools包, fakechroot包以及fakeroot包软件包已被安装。
编辑包文件让它只含有 '基础'. 运行:
# make docker-image
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(或其他没有使用musl libc实现的发行版)上编译的动态链接软件在Alpine Linux (或其他使用musl libc的镜像)上可能会出现错误或性能问题。参见[8], [9]和[10]。
Debian[编辑 | 编辑源代码]
下面的命令会拉取Debian镜像 debian x86_64 image.
# docker pull debian
请参阅Docker Hub页面查看可用标签的完整列表,包括每个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
Distroless[编辑 | 编辑源代码]
Google 维护着distroless镜像,这是没有基本操作系统组件(例如shells和包管理器)的最小化镜像。其最小镜像gcr.io/distroless/static-debian11
仅有2MiB左右,可以用于打包软件并生成非常小的镜像。
请参阅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
运行容器中的图像程序[编辑 | 编辑源代码]
本节介绍了允许在主机的X服务器上运行图形程序(包括依赖于OpenGL或Vulkan的程序)所需的步骤。
首先,需要在容器内安装与主机图形硬件兼容的正确驱动程序。如果容器使用的Arch Linux镜像,请参见OpenGL#安装或 Vulkan#安装来安装对应的驱动。
接下来,你需要授予容器访问主机上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
允许容器直接访问主机上的直接渲染(DRI) 设备。
为了验证设置是否生效,请在容器中运行mesa-utils包中的glxgears
命令(或者vulkan-tools包中的vkcube
命令)。
开机启动 Docker Compose 项目[编辑 | 编辑源代码]
首先,创建一个用于Docker Compose的Systemed单元,并通过服务名称进行参数化(参见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
文件)[13]。
最后, 启用/启动 docker-compose@project_name.service
。
使用buildx进行交叉编译[编辑 | 编辑源代码]
buildx CLI 插件使用了新的BuildKit构建工具包。安装docker-buildx包,buildx接口支持构建多平台镜像(包括与主机不同的框架)。
交叉编译镜像也需要QEMU。如果你想在Docker中设置静态版本的QEMU,请参见multiarch/qemu-user-static 镜像。否则请在主机上设置QEMU与Docker共同使用(参见QEMU#从 x86_64 环境中 Chroot 至 arm/arm64 环境)。无论哪种情况,你的系统都将配置为对客户端架构进行用户模式模拟。
$ 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
用NVIDIA GPU运行GPU加速的Docker容器[编辑 | 编辑源代码]
从19.03版本开始,Docker原生支持NVIDIA GPU作为Docker设备。 推荐使用NVIDIA Container Toolkit来运行需要操作NVIDIA显卡的容器。
安装 nvidia-container-toolkit包 包并重启Docker。之后可以用--gpus
选项来运行使用NVIDIA显卡的容器
使用 --gpus 选项(推荐)[编辑 | 编辑源代码]
# docker run --gpus all nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi
指定容器内可使用多少GPU:
# docker run --gpus 2 nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi
指定使用哪一个GPU:
# docker run --gpus '"device=1,2"' nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi
或
# docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi
如果在执行指令时收到错误Failed to initialize NVML: Unknown Error
,你可以尝试详细指定GPU来解决这个问题:
# docker run --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
指定需要的具体功能(图像、计算等)
# docker run --gpus all,capabilities=utility nvidia/cuda:12.1.1-runtime-ubuntu22.04 nvidia-smi
使用 NVIDIA Container Runtime[编辑 | 编辑源代码]
编辑/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。
有CUDA的 Arch Linux 镜像[编辑 | 编辑源代码]
可使用以下Dockerfile
构建自定义的有CUDA的 Arch Linux 镜像。它使用 Dockerfile frontend syntax 1.2 在宿主机上缓存pacman包。请注意,你必须在构建镜像之前设置环境变量DOCKER_BUILDKIT=1
。
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 system prune
要删除所有停止的容器和所有未使用的镜像(而不只是悬空镜像),添加-a
标志:
# docker system prune -a
删除所有docker数据 (清除目录):
# rm -R /var/lib/docker
故障排除[编辑 | 编辑源代码]
使用systemd-networkd时,docker0 网桥无法获取 IP / Internet 到容器[编辑 | 编辑源代码]
Docker会自己启用IP转发,但是默认 systemd-networkd 会覆盖对应的sysctl设置,在网络配置文件里设置 IPForward=yes
。查阅网络分享#启用包转发获取细节。
当systemd-networkd尝试管理由Docker创建的网络时,如果你在Match
部分设置了Name=*
或Type=ether
,这可能会导致网络连接出现问题。请更为具体地配置接口,即尽可能避免使用Name=*
,Type=ether
等通配符来匹配Docker管理的接口。你可以验证 networkctl list
是否在 Docker 创建的所有网络的 SETUP 栏中设置为 unmanaged
。
默认的允许的进程/线程数太少[编辑 | 编辑源代码]
如果你允许时得到下面的错误信息
# e.g. Java java.lang.OutOfMemoryError: unable to create new native thread # e.g. C, bash, ... fork failed: Resource temporarily unavailable
那么你可能需要调整被systemd允许的进程数, 编辑并添加下面片段 docker.service
:
# systemctl edit docker.service
[Service] TasksMax=infinity
对于更多参数,例如 DefaultLimitNPROC
,请参阅 systemd-system.conf(5) § OPTIONS。对于 TasksMax
请参阅 systemd.resource-control(5) § OPTIONS。
初始化显卡驱动错误: 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文件系统启用配额挂载选项必须作为内核参数rootflags=
传递到initramfs. 之后, 它就不应该在/etc/fstab
中的挂载选项中列出root (/
) 文件系统.
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的配置文件来解决这个问题,参见[17]将配置文件修改为:
/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 ECR, Google Container Registry, Azure Container Registry 或 Quay Container Registry。
使用Docker CLI 中的 pull
, tag
以及 push
命令来镜像一个镜像。例如,将 Nginx 标签(tag)为 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 (旧版): 未知选项 "--dport"[编辑 | 编辑源代码]
如果你在运行容器时收到了这样的错误:
iptables (legacy): unknown option "--dport"
安装 iptables-nft包 而不是 iptables包 (旧版) 然后重启[18]。
运行docker login时提示"密码以非加密形式储存"[编辑 | 编辑源代码]
默认情况下 Docker 会尝试使用 pass
或者 secretservice
的二进制形式文件来储存你的注册表密码。如未能找到这些文件,注册表秘密将以明文形式(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, 默认选项是:
Type | Default Size | Default Pool |
---|---|---|
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冲突,请不要修改第二个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默认地址池选项的权威指南。
Golang编译速度过慢[编辑 | 编辑源代码]
由于ulimit配置的原因,使用makepkg构建docker镜像以及其依赖时会非常缓慢(会在"Entering fakeroot environment..."处卡住)。
这是因为[19] [20],你可以尝试将 --ulimit "nofile=1024:524288"
添加到你的docker构建选项中来解决问题:
/etc/docker/daemon.json
{ "default-ulimits": { "nofile": { "Name": "nofile", "Soft": 1024, "Hard": 524288 } } }