Docker 配置详解

概述

参考:

Docker 的守护进程为 dockerd,dockerd 可以通过两种方式配置运行时行为

  • 通过配置文件 /etc/docker/daemon.json 进行配置
  • 使用 dockerd 命令的 flags 进行配置,可以将 flags 添加到 dockerd.service 中。

[!Note] 配置文件中的配置,也可以通过 dockerd 的命令行参数(也就是 flags)指定,比如配置文件中的 data-root 字段,对应的 dockerd flags 为 –data-root STRING。

配置文件示例

dockerd 配置文件是 JSON 格式,基本常用的配置内容如下。

{
  // 指定 docker pull 时,首先去连接的 registry。
  "registry-mirrors": [
    "http://172.38.40.180",
    "https://ac1rmo5p.mirror.aliyuncs.com"
  ],
  // 指定运行 docker 操作的不安全的 registry 的列表
  "insecure-registries": ["http://172.38.40.180"],
  // 指定 docker 运行时其他的选项,这里面指定 docker 的 cgroupdriver 为 systemd
  "exec-opts": ["native.cgroupdriver=systemd"],
  // 指定 docker 的日志驱动为 json-file
  "log-driver": "json-file",
  // 指定 docker 记录容器日志的参数,这里指定容器日志文件大小最大为100m
  "log-opts": {
    "max-size": "100m"
  },
  // 指定 docker 的存储驱动类型为 overlay2
  "storage-driver": "overlay2",
  // 指定 docker 存储驱动的其他选项
  "storage-opts": ["overlay2.override_kernel_check=true"]
}

命令行标志详解

绝大部分的命令行标志都可以参考配置文件详解进行使用

-H, –host <LIST> # 要连接的守护进程 socket。官方给的 systemd 的 service 中,使用的是 docker -H fd://,这样的用法必须要先启动 docker.socket

配置文件详解

data-root(STRING)

配置 docker info 命令中的 Docker Root Dir,也就是 docker 存储数据的路径。

features(OBJECT)

一些新的特性可以通过配置该字段来启动或停止

hosts([]STRING) # 指定 docker 守护进程监听的端口

可以从其他机器使用 docker -H URL 命令对该设备进行 docker 操作

live-restore(BOOL)

在 docker.service 守护程序停止期间,保持容器状态,说白了就是重启 docker 的时候 Containers 不重启。 开启该参数后,就算重启 dockerd 服务也不会更改 default-address-pools 参数执行的地址范围

registry-mirrors([]STRING) # 指定 pull、push 镜像时候的加速器地址

可用的地址参考 容器镜像管理

日志配置

log-driver(STRING) # 指定 docker 的日志驱动

log-opts(OBJECT) # 指定 docker 记录容器日志的参数

存储驱动配置

storage-driver(STRING) # 在 Linux 上,Dockerd 进程支持多种不同的镜像层存储驱动程序: overlay2fuse-overlayfsbtrfszfs, and devicemapper.

storage-opts([]STRING) # 与存储驱动相关的选项。

  • 很多选项随着版本的更新,会弃用,比如 overlay2.override_kernel_check 已于 24.0+ 版本弃用

下面是官网给的配置文件中所有可用字段的说明

https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file

{
  "authorization-plugins": [],
  "data-root": "",
  "dns": [],
  "dns-opts": [],
  "dns-search": [],
  "exec-opts": [],
  "exec-root": "",
  "experimental": false,
  "features": {},
  "storage-driver": "",
  "storage-opts": [],
  "labels": [],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5",
    "labels": "somelabel",
    "env": "os,customer"
  },
  "mtu": 0,
  "pidfile": "",
  "cluster-store": "",
  "cluster-store-opts": {},
  "cluster-advertise": "",
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "default-shm-size": "64M",
  "shutdown-timeout": 15,
  "debug": true,
  // 指定docker守护进程监听的端口,可以从其他机器使用docker -H URL命令对该设备进行docker操作
  "hosts": [],
  "log-level": "",
  "tls": true,
  "tlsverify": true,
  "tlscacert": "",
  "tlscert": "",
  "tlskey": "",
  "swarm-default-advertise-addr": "",
  "api-cors-header": "",
  "selinux-enabled": false,
  "userns-remap": "",
  "group": "",
  "cgroup-parent": "",
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  },
  "init": false,
  "init-path": "/usr/libexec/docker-init",
  "ipv6": false,
  "iptables": false,
  "ip-forward": false,
  "ip-masq": false,
  "userland-proxy": false,
  "userland-proxy-path": "/usr/libexec/docker-proxy",
  "ip": "0.0.0.0",
  "bridge": "",
  // 指定 docker0 桥的 IP
  "bip": "",
  "fixed-cidr": "",
  "fixed-cidr-v6": "",
  "default-gateway": "",
  "default-gateway-v6": "",
  "icc": false,
  "raw-logs": false,
  "allow-nondistributable-artifacts": [],
  "registry-mirrors": [],
  "seccomp-profile": "",
  // 指定不安全仓库,docker 默认无法连接 http 协议的仓库,将仓库的 URL 添加到该字段后,docker 即可连接
  "insecure-registries": [],
  "no-new-privileges": false,
  "default-runtime": "runc",
  "oom-score-adjust": -500,
  "node-generic-resources": ["NVIDIA-GPU=UUID1", "NVIDIA-GPU=UUID2"],
  "runtimes": {
    "cc-runtime": {
      "path": "/usr/bin/cc-runtime"
    },
    "custom": {
      "path": "/usr/local/bin/my-runc-replacement",
      "runtimeArgs": ["--debug"]
    }
  },
  "default-address-pools": [
    { "base": "172.80.0.0/16", "size": 24 },
    { "base": "172.90.0.0/16", "size": 24 }
  ]
}

代理配置

参考:

注意:从 Docker 的 23.0 版本开始,可以在 daemon.json 文件中配置 dockerd 的代理行为:

{
  "proxies": {
    "http-proxy": "http://192.168.254.254:7890",
    "https-proxy": "http://192.168.254.254:7890",
    "no-proxy": "*.test.example.com,.example.org,127.0.0.0/8"
  }
}

下面的文章权当记录留个念想了。

如果 docker 所在的环境是通过代理服务器和互联网连通的,那么需要一番配置才能让 docker 正常从外网正常拉取镜像。然而仅仅通过配置环境变量的方法是不够的。本文结合已有文档,介绍如何配置代理服务器能使docker正常拉取镜像。

本文使用的docker 版本是19.03

问题现象

如果不配置代理服务器就直接拉镜像,docker 会直接尝试连接镜像仓库,并且连接超时报错。如下所示:

$ docker pull busybox
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled
while waiting for connection (Client.Timeout exceeded while awaiting headers)

容易误导的官方文档

有这么一篇关于 docker 配置代理服务器的 官方文档 ,如果病急乱投医,直接按照这篇文章配置,是不能成功拉取镜像的。

我们来理解一下这篇文档,文档关键的原文摘录如下:

If your container needs to use an HTTP, HTTPS, or FTP proxy server, you can configure it in different ways: Configure the Docker client On the Docker client, create or edit the file ~/.docker/config.json in the home directory of the user that starts containers.

When you create or start new containers, the environment variables are set automatically within the container.

这篇文档说:如果你的容器或者使用 docker build 构建镜像时需要使用代理服务器,那么可以以如下方式配置: 在运行容器的用户 home 目录下,配置 ~/.docker/config.json 文件。重新启动容器后,这些环境变量将自动设置进容器,从而容器内的进程可以使用代理服务。

所以这篇文章是讲如何配置运行容器的环境,与如何拉取镜像无关。如果按照这篇文档的指导,如同南辕北辙。

要解决问题,我们首先来看一般情况下命令行如何使用代理。

环境变量

常规的命令行程序如果要使用代理,需要设置两个环境变量:HTTP_PROXY 和 HTTPS_PROXY ,设置环境变量的方法见 这篇文章 。但是仅仅这样设置环境变量,也不能让 docker 成功拉取镜像。

我们仔细观察 上面的报错信息,有一句说明了报错的来源:

Error response from daemon:

因为镜像的拉取和管理都是 docker daemon 的职责,所以我们要让 docker daemon 知道代理服务器的存在。而 docker daemon 是由 systemd 管理的,所以我们要从 systemd 配置入手。

正确的官方文档

关于 systemd 配置代理服务器的 官方文档在这里,原文说:

The Docker daemon uses the HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environmental variables in its start-up environment to configure HTTP or HTTPS proxy behavior. You cannot configure these environment variables using the daemon.json file.

This example overrides the default docker.service file.

If you are behind an HTTP or HTTPS proxy server, for example in corporate settings, you need to add this configuration in the Docker systemd service file.

这段话的意思是,docker daemon 使用 HTTP_PROXYHTTPS_PROXY, 和 NO_PROXY 三个环境变量配置代理服务器,但是你需要在 systemd 的文件里配置环境变量,而不能配置在 daemon.json 里。

具体操作

下面是来自官方文档的操作步骤和详细解释:

  1. 创建 dockerd 相关的 systemd 目录,这个目录下的配置将覆盖 dockerd 的默认配置
sudo mkdir -p /etc/systemd/system/docker.service.d
  1. 新建配置文件 /etc/systemd/system/docker.service.d/http-proxy.conf,这个文件中将包含环境变量
[Service]
Environment="HTTP_PROXY=http://192.168.254.254:7890"
Environment="HTTPS_PROXY=http://192.168.254.254:7890"
  1. 如果你自己建了私有的镜像仓库,需要 dockerd 绕过代理服务器直连,那么配置 NO_PROXY 变量:
[Service]
Environment="HTTP_PROXY=http://192.168.254.254:7890"
Environment="HTTPS_PROXY=http://192.168.254.254:7890"
Environment="NO_PROXY=your-registry.com,10.10.10.10,*.example.com"

多个 NO_PROXY 变量的值用逗号分隔,而且可以使用通配符(*),极端情况下,如果 NO_PROXY=*,那么所有请求都将不通过代理服务器。

  1. 重新加载配置文件,重启 dockerd
sudo systemctl daemon-reload
sudo systemctl restart docker
  1. 检查确认环境变量已经正确配置:
sudo systemctl show --property=Environment docker
  1. 从 docker info 的结果中查看配置项。

这样配置后,应该可以正常拉取 docker 镜像。

结论

docker 镜像由 docker daemon 管理,所以不能用修改 shell 环境变量的方法使用代理服务,而是从 systemd 角度设置环境变量。


最后修改 June 26, 2024: prometheus (13b61e0c)