本节讲述配置Linux主机使其更好地与Docker配合使用的可选过程。
以非root用户身份管理Docker
Docker后台程序绑定到Unix套接字而不是TCP端口。 默认情况下,Unix套接字由用户root
拥有,其他用户只能使用sudo
访问它。 Docker后台程序始终以root
用户身份运行。
如果您不想每次都在docker
命令前面加上sudo
,请创建一个名为docker
的Unix组并将用户添加到其中。 当Docker后台程序启动时,它将创建可由docker组的成员访问的Unix套接字,。
警告
docker
组授予与root
用户等效的特权。 有关如何影响系统安全性的详细信息,请参阅Docker后台程序攻击表面。
注意:
要在没有root权限的情况下运行Docker,请参阅以非root用户身份运行Docker后台程序(Rootless模式).
Rootless模式目前是实验功能。
创建docker
组并添加用户:
- 创建
docker
组。
```bash
$ sudo groupadd docker
```
- 将您的用户添加到
docker
组。
```bash
$ sudo usermod -aG docker $USER
```
- 注销并重新登录,以便重新评估您的组成员身份。
如果在虚拟机上进行测试,则可能需要重新启动虚拟机以使更改生效。
在Linux桌面环境(例如X Windows)上,完全注销会话,然后重新登录。
在Linux上,您还可以运行以下命令来激活对组的更改:
```bash
$ newgrp docker
```
- 确认您可以在不使用sudo的情况下运行docker命令。
```bash
$ docker run hello-world
```
此命令下载测试镜像并在容器中运行。 容器运行时,它会打印参考消息并退出。
如果最初在将用户添加到`docker`组之前已使用`sudo`运行了Docker CLI命令,则可能会看到以下错误,这表明`sudo`命令创建`~/.docker/`目录时使用了错误的权限。。
```none
WARNING: Error loading config file:/home/user/.docker/config.json -
stat/home/user/.docker/config.json: permission denied
```
要解决此问题,请删除`~/.docker/`目录(该目录会自动重新创建,但是所有自定义设置都会丢失),或者使用以下命令更改其所有权和权限:
```bash
$ sudo chown "$USER":"$USER"/home/"$USER"/.docker -R
$ sudo chmod g+rwx "$HOME/.docker" -R
```
配置Docker在系统启动时启动
当前大多数Linux发行版(RHEL,CentOS,Fedora,Ubuntu 16.04和更高版本)都使用systemd
(#sy管理系统启动时启动的服务。 Ubuntu 14.10及以下版本使用upstart
。
systemd
$ sudo systemctl enable docker
要禁用此行为,请改用“ disable”。
$ sudo systemctl disable docker
如果您需要添加HTTP代理,将Docker运行时文件设置到其他目录或分区,或进行其他自定义,请参阅自定义您的systemd Docker后台程序选项。
upstart
Docker被自动配置为在系统启动时启动,使用upstart
。 若要禁用此行为,请使用以下命令:
$ echo manual | sudo tee/etc/init/docker.override
chkconfig
$ sudo chkconfig docker on
使用其他存储引擎
有关不同存储引擎的信息,请参阅存储驱动程序。 默认存储引擎和受支持的存储引擎列表取决于主机的Linux发行版和可用的内核驱动程序。
配置默认日志记录驱动程序
Docker提供了capability来通过一系列日志记录驱动程序从主机上运行的所有容器中收集和查看日志数据。 默认的日志记录驱动程序,json-file
,将日志数据写入主机文件系统上的JSON格式的文件中。 随着时间的推移,这些日志文件的大小会扩大,从而可能导致磁盘资源耗尽。 要缓解此类问题,请配置备用日志记录驱动程序(例如Splunk或Syslog),或为默认驱动程序配置设置日志轮转。 如果配置备用日志记录驱动程序,请参阅远程日志记录驱动程序使用docker logs
读取容器的日志。
配置Docker后台程序侦听连接的位置
默认情况下,Docker后台程序在UNIX套接字上侦听连接以接受来自本地客户端的请求。 可以允许Docker接受来自远程主机的请求,通过将Docker配置为侦听IP地址和端口以及UNIX套接字。有关此配置选项的更多详细信息,请查看Docker CLI参考的“将Docker绑定到另一个主机/端口或unix套接字”部分文章。
Docker EE客户
Docker EE客户可以通过UCP客户端软件包获得对UCP的远程CLI访问。 UCP客户端包由UCP生成,并由双方TLS保护。 有关更多信息,请参见UCP的CLI访问上的文档。
保护您的连接
在将Docker配置为接受来自远程主机的连接之前,至关重要的是要了解将Docker打开到网络的安全隐患。 如果未采取措施保护连接安全,则远程非root用户可能会获得主机上的root访问权限。 有关如何使用TLS证书保护此连接的更多信息,请参阅如何保护Docker后台程序套接字上的此文章。
使用systemd的Linux发行版,可以使用docker.service
systemd单元文件,来配置Docker以接受远程连接。例如RedHat,CentOS,Ubuntu和SLES的最新版本。不使用systemd的Linux发行版推荐使用dada.json
文件。
systemd vs daemon.json
同时将Docker配置为使用
systemd
单元文件和daemon.json
文件来监听连接会导致冲突,从而阻止Docker启动。
使用systemd
单元文件配置远程访问
使用命令
sudo systemctl edit docker.service
在文本编辑器中打开docker.service
的重载文件。添加或修改以下行,以替换您自己的值。
```none
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd://-H tcp://127.0.0.1:2375
```
保存文件。
重新加载
systemctl
配置。
$ sudo systemctl daemon-reload
```
5. 重新启动Docker。
```bash
$ sudo systemctl restart docker.service
```
6. 通过查看`netstat`的输出以确认`dockerd`正在配置的端口上进行侦听,以查看更改是否生效。
```bash
$ sudo netstat -lntp | grep dockerd
tcp 0 0 127.0.0.1:2375 0.0.0.0:* LISTEN 3758/dockerd
```
### 使用`daemon.json`配置远程访问
1. 在`/etc/docker/daemon.json`中设置`hosts`数组,以连接到UNIX套接字和IP地址,如下所示:
```json
{
"hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
}
```
2. 重新启动Docker。
3. 通过查看`netstat`的输出以确认`dockerd`正在配置的端口上进行侦听,以查看是否接受了更改。
```bash
$ sudo netstat -lntp | grep dockerd
tcp 0 0 127.0.0.1:2375 0.0.0.0:* LISTEN 3758/dockerd
```
## 在Docker后台程序上启用IPv6
要在Docker后台程序上启用IPv6,请参阅[启用IPv6支持](/docker/docker-guides/enable-ipv6-support)。
## 故障排除
### 内核兼容性
如果您的内核早于3.10版本或缺少某些模块,则Docker无法正确运行。 要检查内核兼容性,可以下载并运行[`check-config.sh`](https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh)脚本。
```bash
$ curl https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh > check-config.sh
$ bash ./check-config.sh
该脚本仅适用于Linux,不适用于macOS。
无法连接到Docker后台程序
如果您看到以下错误,则您的Docker客户端可能已配置为连接到其他主机上的Docker后台程序,而该主机可能不是可达的。
Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?
要查看您的客户端配置为连接到哪个主机,请检查环境中的DOCKER_HOST变量的值。
$ env | grep DOCKER_HOST
如果此命令返回值,则将Docker客户端设置为连接到在该主机上运行的Docker后台程序。 如果未设置,则将Docker客户端设置为连接到在本地主机上运行的Docker后台程序。 如果设置错误,请使用以下命令将其取消设置:
$ unset DOCKER_HOST
您可能需要在~/.bashrc
或~/.bashrc
等文件中编辑环境,以防止错误地设置DOCKER_HOST
变量。
如果您根据需设置了DOCKER_HOST
,请确认Docker后台程序正在远程主机上运行,并且连接没有被防火墙或网络中断阻止。
IP转发问题
如果您使用systemd
版本219或更高的systemd-network
手动配置网络,则Docker容器可能无法访问您的网络。 从systemd
版本220开始,给定网络(net.ipv4.conf.<interface>.forwarding
)的转发设置默认为off。 此设置可防止IP转发。 这也与Docker在容器内启用net.ipv4.conf.all.forwarding
设置的行为相冲突。
要在RHEL,CentOS或Fedora上解决此问题,请在Docker主机上的/usr/lib/systemd/network/
中编辑<interface>.network
文件(例如:/usr/lib/systemd/network/80-container-host0.network
),然后在[Network]
部分中添加以下代码块。
[Network]
...
IPForward=kernel
# OR
IPForward=true
...
此配置允许按预期从容器进行IP转发。
DNS resolver found in resolv.conf and containers can't use it
使用GUI的Linux系统通常会运行网络管理器,该网络管理器使用运行在环回地址(例如127.0.0.1
或127.0.1.1
)上的dnsmasq
实例来缓存DNS请求,并将此条目添加到/etc/resolv.conf
。 dnsmasq
服务加快了DNS查找的速度,还提供了DHCP服务。 此配置在具有自己网络命名空间的Docker容器中不起作用,因为Docker容器将诸如127.0.0.1
之类的环回地址解析为自身,并且极不可能在自己的环回地址上运行DNS服务器。
如果Docker检测到/etc/resolv.conf
中没有引用功能齐全的DNS服务器,则会发生以下警告,并且Docker将使用Google在8.8.8.8
和8.8.4.4
中提供的公共DNS服务器。 用于DNS解析。
WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers
can't use it. Using default external servers : [8.8.8.8 8.8.4.4]
如果看到此警告,请首先检查是否使用dnsmasq
:
$ ps aux |grep dnsmasq
如果您的容器需要解析网络内部的主机,则公共名称服务器不能完成。 您有两种选择:
- 您可以为Docker指定要使用的DNS服务器,或
- 您可以在NetworkManager中禁用“dnsmasq”。 如果这样做,NetworkManager会将您的真实DNS名称服务器添加到
/etc/resolv.conf
中,但是您会失去dnsmasq
可能带来的好处。
您只需要使用这些方法之一。
为Docker指定DNS服务器
配置文件的默认位置是/etc/docker/daemon.json
。 您可以使用--config-file后台程序标志来更改配置文件的位置。 以下文档假定配置文件位于/etc/docker/daemon.json
中。
- 创建或编辑Docker后台程序配置文件,该文件默认为
/etc/docker/daemon.json
文件,该文件控制Docker后台程序的配置。
```bash
$ sudo nano /etc/docker/daemon.json
```
- 添加一个有一个或多个IP地址值的
dns
键。 如果文件已有内容,则只需添加或编辑dns行。
```json
{
"dns": ["8.8.8.8", "8.8.4.4"]
}
```
如果内部DNS服务器无法解析公共IP地址,则至少包括一台可以解析的DNS服务器,以便您可以连接到Docker Hub,以便您的容器可以解析Internet域名。
保存并关闭文件。
- 重新启动Docker后台程序。
```bash
$ sudo service docker restart
```
- 通过尝试拉镜像来验证Docker是否可以解析外部IP地址:
```bash
$ docker pull hello-world
```
- 如有必要,请通过ping验证Docker容器可以解析内部主机名。
```bash
$ docker run --rm -it alpine ping -c4 <my_internal_host>
PING google.com (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: seq=0 ttl=41 time=7.597 ms
64 bytes from 192.168.1.2: seq=1 ttl=41 time=7.635 ms
64 bytes from 192.168.1.2: seq=2 ttl=41 time=7.660 ms
64 bytes from 192.168.1.2: seq=3 ttl=41 time=7.677 ms
```
禁用dnsmasq
Ubuntu
如果您不想更改Docker后台程序的配置以使用特定的IP地址,请按照以下说明在NetworkManager中禁用dnsmasq
。
编辑
/etc/NetworkManager/NetworkManager.conf
文件。通过在行的开头添加一个
#
号来注释掉dns=dnsmasq
行。
```none
# dns=dnsmasq
```
保存并关闭文件。
- 重新启动NetworkManager和Docker。 或者,您可以重新启动系统。
```bash
$ sudo restart network-manager
$ sudo restart docker
```
RHEL, CentOS, or Fedora
要在RHEL,CentOS或Fedora上禁用dnsmasq
:
- 禁用
dnsmasq
服务:
```bash
$ sudo service dnsmasq stop
$ sudo systemctl disable dnsmasq
```
- 使用[Red Hat文档]手动配置DNS服务器(https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s1-networkscripts-interfaces.html)。
允许通过防火墙访问远程API
如果您在运行Docker的主机上运行防火墙,并且想从另一台主机访问Docker远程API并启用了远程访问,则需要配置防火墙以允许Docker端口上的传入连接,默认为2376
, 如果启用了TLS加密传输,则为2375
。
两种常见的防火墙后台程序是UFW(非复杂防火墙)(通常用于Ubuntu系统)和firewalld (通常用于基于RPM的系统)。 请查阅有关您的操作系统和防火墙的文档,但是以下信息可能有助于您入门。 这些选项相当宽松,您可能需要使用其他配置来进一步锁定系统。
UFW: 在您的配置中设置
DEFAULT_FORWARD_POLICY="ACCEPT"
.firewalld: 将与以下内容类似的规则添加到您的策略中(一个用于传入请求,一个用于传出请求)。 确保接口名称和链名称正确。
<direct>
[ <rule ipv="ipv6" table="filter" chain="FORWARD_direct" priority="0"> -i zt0 -j ACCEPT </rule> ]
[ <rule ipv="ipv6" table="filter" chain="FORWARD_direct" priority="0"> -o zt0 -j ACCEPT </rule> ]
</direct>
Your kernel does not support cgroup swap limit capabilities
在Ubuntu或Debian主机上,使用镜像时,您可能会看到类似以下的消息。
WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.
在基于RPM的系统上不会发生此警告,该系统默认情况下启用这些功能。
如果不需要这些功能,则可以忽略该警告。 您可以按照以下说明在Ubuntu或Debian上启用这些功能。 即使Docker未运行,内存和交换记帐也会导致总可用内存的开销约为1%,并且总体性能会降低10%。
以具有
sudo
特权的用户身份登录Ubuntu或Debian主机。编辑
/etc/default/grub
文件。 添加或编辑GRUB_CMDLINE_LINUX
行以添加以下两个键值对:
```none
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
```
保存并关闭文件。
- 更新GRUB。
```bash
$ sudo update-grub
```
如果您的GRUB配置文件语法不正确,则会发生错误。 在这种情况下,请重复步骤2和3。
更改将在系统重新启动后生效。
下一步
- 继续阅读用户指南。