Docker (简体中文)
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存储驱动 (或者是显卡驱动) 对性能有巨大影响. 它的工作是高效存储容器镜像层,也就是许多镜像共享一个层时只有一个层使用磁盘空间。作为兼容选项, `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
使用 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
有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数据 (清除目录):
# 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 获取细节.
默认的允许的进程/线程数太少
如果你允许时得到下面的错误信息
# 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 (/
) 文件系统.
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.