使用 Portainer 管理 Docker:基于 dockerd 配置文件修改的安全性和实现步骤

使用 Portainer 管理 Docker:基于 dockerd 配置文件修改的安全性和实现步骤

在容器化应用逐渐成为主流的今天,Docker 已经成为开发和运维中不可或缺的工具。为了有效地管理 Docker 容器,很多团队选择使用图形化管理工具 Portainer,它不仅简化了 Docker 容器管理,还提供了直观的界面和多种功能。

在这篇文章中,我们将介绍如何通过修改 Docker 守护进程配置,暴露 Docker API 端口并通过 Portainer 实现容器管理。我们还将讨论这个过程的安全性考虑、配置步骤以及如何验证 API 接口的有效性。


一、目标:通过 Portainer 管理 Docker 容器

Portainer 是一个轻量级的 Docker 管理工具,提供了一个简洁的 Web 界面来管理 Docker 容器、镜像、网络和卷。通过 Portainer,你可以轻松地执行以下操作:

  • 查看 Docker 容器的状态、日志和指标。
  • 启动、停止、重启容器。
  • 管理 Docker 镜像和网络。

为了能够通过 Portainer 远程管理 Docker,我们需要开放 Docker 的 API 接口,使得 Portainer 能够与 Docker 守护进程进行通信。

二、安全性考虑

暴露 Docker API 端口是一个潜在的安全风险。如果没有加密和身份验证,恶意用户可能会远程访问并控制你的 Docker 守护进程。因此,在开放 Docker API 时,必须采取以下安全措施:

  1. 只允许信任的 IP 访问:通过防火墙或其他网络访问控制限制可以访问 Docker API 的 IP 地址。
  2. 启用 TLS 加密:使用 TLS 加密通信,确保 Docker API 与客户端之间的通信是安全的。
  3. 认证机制:使用客户端证书来验证访问 Docker API 的请求,确保只有授权的客户端才能访问。

如果仅用于局域网内的开发环境,可以暂时通过未加密的 TCP 端口来开放 Docker API,但这应当尽量避免在生产环境中使用。

三、调整 Docker 服务配置

默认情况下,Docker 守护进程仅监听本地 Unix socket (/var/run/docker.sock),这意味着只能通过本地访问 Docker。但是,如果你希望通过远程方式管理 Docker,尤其是通过 Portainer 来管理 Docker,则需要调整 Docker 服务配置,使其监听指定的 TCP 端口。

1. 修改 Docker 配置文件

修改 Docker 服务配置文件,指定 Docker 守护进程监听所有 IP 地址的端口(如 2375)。

首先,打开 Docker 的服务文件(通常是 /etc/systemd/system/docker.service/lib/systemd/system/docker.service)。

1
sudo nano /etc/systemd/system/docker.service

然后,在 ExecStart 行中修改为:

1
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock

这里的参数含义如下:

  • -H fd://:Docker 守护进程继续通过默认的 Unix socket 进行本地通信。

  • -H tcp://0.0.0.0:2375:Docker 守护进程会在所有网络接口上监听 2375 端口,允许通过 TCP 协议访问 Docker API。

  • --containerd=/run/containerd/containerd.sock:指定 containerd 套接字文件位置。

  • 完成配置文件内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    [Unit]
    Description=Docker Application Container Engine
    Documentation=https://docs.docker.com
    After=network-online.target nss-lookup.target docker.socket firewalld.service containerd.service time-set.target
    Wants=network-online.target containerd.service
    Requires=docker.socket

    [Service]
    Type=notify
    # the default is not to use systemd for cgroups because the delegate issues still
    # exists and systemd currently does not support the cgroup feature set required
    # for containers run by docker
    ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
    ExecReload=/bin/kill -s HUP $MAINPID
    TimeoutStartSec=0
    RestartSec=2
    Restart=always

    # Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
    # Both the old, and new location are accepted by systemd 229 and up, so using the old location
    # to make them work for either version of systemd.
    StartLimitBurst=3

    # Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
    # Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
    # this option work for either version of systemd.
    StartLimitInterval=60s

    # Having non-zero Limit*s causes performance problems due to accounting overhead
    # in the kernel. We recommend using cgroups to do container-local accounting.
    LimitNPROC=infinity
    LimitCORE=infinity

    # Comment TasksMax if your systemd version does not support it.
    # Only systemd 226 and above support this option.
    TasksMax=infinity

    # set delegate yes so that systemd does not reset the cgroups of docker containers
    Delegate=yes

    # kill only the docker process, not all processes in the cgroup
    KillMode=process
    OOMScoreAdjust=-500

    [Install]
    WantedBy=multi-user.target

2. 重新加载 Docker 配置并重启服务

修改完服务文件后,需要重新加载 systemd 配置并重启 Docker 服务。

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

3. 防火墙配置

为确保只有信任的 IP 地址可以访问 Docker API,配置防火墙来限制访问。以 ufw 为例,可以允许本地网络的 IP 地址访问 Docker API:

1
sudo ufw allow from 10.10.0.0/24 to any port 2375

如果你使用 iptables,可以使用类似的规则来控制访问。

四、安装并配置 Portainer

1.拉取 Portainer 镜像并启动

Portainer 通过 Docker 运行,所以首先需要从 Docker Hub 拉取 Portainer 镜像并运行它:

1
docker pull portainer/portainer-ce

然后运行 Portainer 容器:

1
docker run -d -p 9000:9000 -p 8000:8000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer-ce

Portainer 容器 docker-compose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
portainer:
image: portainer/portainer-ce:lts
container_name: portainer
restart: unless-stopped
ports:
- "3013:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/data
networks:
- service

networks:
service:
external: true

上述命令将 Portainer 容器映射到宿主机的 9000 端口(Web 界面)和 8000 端口(用于 Docker Socket API)。

2.访问 Portainer Web 界面

通过浏览器访问 http://<docker_host>:9000,你将看到 Portainer 的登录界面。使用管理员账户登录后,你可以开始使用 Portainer 管理 Docker。

五、验证 Docker API 接口是否可用

在修改了 Docker 配置并启动了 Portainer 后,需要验证 Docker API 接口是否已经正确开放并能够通过 Portainer 进行管理。

5.1. 使用 Curl 测试 API

你可以使用 curl 命令验证 Docker API 是否正常工作:

1
2
3
4
curl http://<docker_host>:2375/containers/json

# 实际curl命令
curl http://10.10.0.253:2375/containers/json

如果配置正确,该命令将返回所有容器的 JSON 列表。如果 Docker API 正常工作,你将看到一个类似以下的响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PS C:\Users\Administrator> curl http://10.10.0.253:2375/containers/json

StatusCode : 200
StatusDescription : OK
Content : [{"Id":"426985df4c2634c369d9ba32e15d00296d4a1e6ff46b107316903bb251d18cbd","Names":["/adguardhome"],"Image":"adguard/adguardhome:latest","ImageID":"sh
a256:dec26deaafcff748c4b70202473c0f81aa4ebfbe47f4b3...
RawContent : HTTP/1.1 200 OK
Api-Version: 1.51
Docker-Experimental: false
Ostype: linux
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 15 Oct 2025 04:44:15 GMT
Server: Docker/28.3.2 (l...
Forms : {}
Headers : {[Api-Version, 1.51], [Docker-Experimental, false], [Ostype, linux], [Transfer-Encoding, chunked]...}
Images : {}
InputFields : {}
Links : {@{innerHTML=Portainer.io; innerText=Portainer.io; outerHTML=<A title='\"http://Portainer.io\"' class='\"sc-jKJlTe' href='\"http://portainer.io/\"' d
ata-renderer-mark='\"true\"' dPfAtb\?>Portainer.io</A>; outerText=Portainer.io; tagName=A; title=\"http://Portainer.io\"; class=\"sc-jKJlTe; href=\"h
ttp://portainer.io/\"; data-renderer-mark=\"true\"; dPfAtb\?=}, @{innerHTML=get 3 free nodes.; innerText=get 3 free nodes.; outerHTML=<A title='\"htt
p://portainer.io/take-3?utm_campaign=DockerCon&amp;utm_source=Docker%20Desktop\"' class='\"sc-jKJlTe' href='\"http://portainer.io/take-3?utm_campaign
=DockerCon&amp;utm_source=Docker%20Desktop\"' data-renderer-mark='\"true\"' dPfAtb\?>get 3 free nodes.</A>; outerText=get 3 free nodes.; tagName=A; t
itle=\"http://portainer.io/take-3?utm_campaign=DockerCon&amp;utm_source=Docker%20Desktop\"; class=\"sc-jKJlTe; href=\"http://portainer.io/take-3?utm_
campaign=DockerCon&amp;utm_source=Docker%20Desktop\"; data-renderer-mark=\"true\"; dPfAtb\?=}}
ParsedHtml : mshtml.HTMLDocumentClass
RawContentLength : 35852
1
[{"Id":"d1e2a2f4e65b","Names":["/my_container"],"Image":"nginx:latest","Status":"Up 5 minutes"}]

5.2. 在 Portainer 中验证

登录到 Portainer 后,选择 Docker 环境,如果配置正确,Portainer 会自动连接到远程 Docker 守护进程,你将能够在 Portainer 的 Web 界面上看到所有容器、镜像和网络等信息。

image

六、结论

通过修改 Docker 配置文件并开放远程 API,我们成功地实现了通过 Portainer 管理 Docker 容器。虽然这种方法非常方便,但在生产环境中一定要注意安全性问题,尤其是要避免暴露 Docker API 给公共网络。

总结来说:

  1. 暴露 Docker API 使得 Docker 可以被远程管理。
  2. Portainer 提供了简洁易用的图形界面来管理 Docker。
  3. 安全性考虑:必须加密通信、配置防火墙以及限制访问 IP 地址。
  4. 验证 API 接口:使用 curl 或 Portainer 验证 Docker API 是否正常工作。

通过这种方式,你可以更高效地管理 Docker 容器,同时保持对 Docker API 的控制和安全性。


使用 Portainer 管理 Docker:基于 dockerd 配置文件修改的安全性和实现步骤
https://hesc.info/post/using-portainer-to-manage-docker-security-and-implementation-steps-based-on-dockerd-configuration-file-modification-1hsid1.html
作者
需要哈气的纸飞机
发布于
2025年10月15日
许可协议