上一篇 下一篇 分享链接 返回 返回顶部

生产环境如何调用 Docker API:从配置到实战避坑

发布人:慈云数据-客服中心 发布时间:11小时前 阅读量:3

Docker API接口调用教程|生产环境实测

在生产环境中,很多自动化运维、CI/CD、容器监控、资源编排、故障自愈系统,都会涉及 Docker 的 API 调用。相比直接使用 docker 命令行,Docker Engine API 更适合被程序调用,可以完成容器创建、启动、停止、日志读取、镜像拉取、网络管理、数据卷管理等操作。

本文将结合生产环境中的实际使用经验,系统讲解 Docker API 的调用方式、配置方法、常见接口、调用示例、安全注意事项以及生产环境最佳实践,帮助你快速掌握 Docker API 的使用。


一、Docker API是什么?

Docker API 通常指 Docker Engine API,它是 Docker Daemon 对外提供的一组 RESTful API。我们平时执行的很多命令,例如:

docker ps
docker images
docker run nginx
docker stop container_id
docker logs container_id

本质上都是 Docker CLI 与 Docker Daemon 通信后完成的操作。

Docker 的整体结构可以简单理解为:

Docker CLI  --->  Docker Daemon  --->  Containers / Images / Networks / Volumes

而 Docker API 则允许我们绕过 Docker CLI,直接通过 HTTP 请求与 Docker Daemon 通信。

常见调用方式包括:

  1. 通过 Unix Socket 调用;
  2. 通过 TCP 端口调用;
  3. 通过 SDK 调用,例如 Python SDK、Go SDK、Java SDK;
  4. 通过反向代理或网关封装后调用。

二、为什么生产环境要使用Docker API?

在生产环境中,Docker API 的用途非常广泛。下面是一些常见场景。

1. 自动化部署

例如业务系统发布时,可以通过 API 自动完成:

  • 拉取最新镜像;
  • 停止旧容器;
  • 删除旧容器;
  • 创建新容器;
  • 挂载配置文件;
  • 设置环境变量;
  • 启动容器;
  • 检查容器状态。

2. 容器监控

通过 Docker API 可以实时获取容器状态、CPU 使用率、内存使用率、网络流量、磁盘 IO 等数据。

例如调用:

GET /containers/{id}/stats

可以获取容器资源使用情况。

3. 容器日志采集

调用 Docker API 可以读取容器日志:

GET /containers/{id}/logs

这对于构建自己的日志平台或故障排查系统非常有用。

4. 运维平台集成

很多企业内部运维平台都需要提供容器管理功能,例如:

  • 查看容器列表;
  • 查看镜像列表;
  • 启动、停止、重启容器;
  • 查看容器日志;
  • 查看资源监控;
  • 删除无用镜像和容器。

这些功能都可以通过 Docker API 实现。

5. 故障自愈

通过定时检测容器状态,如果发现容器退出、异常、资源占用过高,可以自动重启容器或通知管理员。


三、查看Docker API版本

在调用 Docker API 之前,建议先查看当前 Docker 的 API 版本。

执行命令:

docker version

示例输出:

Client: Docker Engine - Community
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.20.10

Server: Docker Engine - Community
 Engine:
  Version:          24.0.7
  API version:      1.43

其中比较重要的是:

Server API version: 1.43

调用 API 时,接口路径中通常可以带上版本号,例如:

/v1.43/containers/json

如果不指定版本,Docker 会使用默认版本。但在生产环境中,建议显式指定 API 版本,避免 Docker 升级后接口兼容性出现问题。


四、Docker API的两种常见调用方式

Docker API 最常见的调用方式有两种:

  1. Unix Socket 调用;
  2. TCP 远程调用。

五、通过Unix Socket调用Docker API

默认情况下,Docker Daemon 监听在 Unix Socket 文件上:

/var/run/docker.sock

这个文件非常重要。Docker CLI 本质上也是通过它与 Docker Daemon 通信。

1. 查看docker.sock文件

ls -l /var/run/docker.sock

示例输出:

srw-rw---- 1 root docker 0 Jan 10 10:00 /var/run/docker.sock

如果用户属于 docker 用户组,就可以访问这个 Socket。

2. 使用curl调用Unix Socket

查看 Docker 版本:

curl --unix-socket /var/run/docker.sock http://localhost/version

查看容器列表:

curl --unix-socket /var/run/docker.sock http://localhost/v1.43/containers/json

查看所有容器,包括已停止容器:

curl --unix-socket /var/run/docker.sock "http://localhost/v1.43/containers/json?all=true"

查看镜像列表:

curl --unix-socket /var/run/docker.sock http://localhost/v1.43/images/json

3. Unix Socket方式的优点

  • 不需要开放网络端口;
  • 相对安全;
  • 适合本机脚本、Agent、运维工具调用;
  • 性能较好。

4. Unix Socket方式的缺点

  • 只能本机调用;
  • 权限控制较粗;
  • 一旦拿到 docker.sock 权限,基本等同于拥有宿主机 root 权限。

生产环境提醒:不要随意把 /var/run/docker.sock 挂载到不可信容器中,否则存在严重安全风险。


六、通过TCP端口调用Docker API

如果需要远程调用 Docker API,可以配置 Docker Daemon 监听 TCP 端口。

常见端口是:

2375:未加密端口,不推荐生产环境使用
2376:TLS加密端口,生产环境推荐使用

七、开启Docker远程API

下面以 Linux 系统为例。

1. 修改Docker服务配置

编辑 Docker systemd 配置文件:

sudo vim /usr/lib/systemd/system/docker.service

或者某些系统路径为:

sudo vim /lib/systemd/system/docker.service

找到:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

修改为:

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

然后重新加载配置:

sudo systemctl daemon-reload
sudo systemctl restart docker

检查端口是否监听:

ss -lntp | grep 2375

或者:

netstat -lntp | grep 2375

2. 测试远程API

假设 Docker 主机 IP 是:

192.168.1.100

在另一台机器上执行:

curl http://192.168.1.100:2375/version

查看容器列表:

curl http://192.168.1.100:2375/v1.43/containers/json

如果能正常返回 JSON 数据,说明远程 API 已经开启成功。


八、生产环境不建议直接开放2375端口

虽然 2375 端口使用起来非常方便,但它没有认证和加密。如果直接暴露在公网或不可信内网中,风险极高。

攻击者如果访问到 Docker API,可以执行以下操作:

  • 查看所有容器;
  • 启动恶意容器;
  • 挂载宿主机目录;
  • 读取宿主机敏感文件;
  • 删除镜像和容器;
  • 控制整个宿主机。

例如攻击者可以创建一个挂载宿主机根目录的容器:

docker run -v /:/host -it ubuntu

这意味着 Docker API 一旦被未授权访问,宿主机基本就失守了。

因此生产环境强烈建议:

  1. 不开放 2375;
  2. 使用 2376 + TLS;
  3. 使用防火墙限制访问 IP;
  4. 使用 VPN 或内网专线;
  5. 使用反向代理增加认证;
  6. 不要将 Docker API 暴露到公网。

九、Docker API常用接口实战

下面介绍一些生产环境最常用的 Docker API 接口。


十、查看Docker版本信息

接口:

GET /version

调用示例:

curl --unix-socket /var/run/docker.sock http://localhost/version

远程调用:

curl http://192.168.1.100:2375/version

返回示例:

{
  "Platform": {
    "Name": "Docker Engine - Community"
  },
  "Components": [],
  "Version": "24.0.7",
  "ApiVersion": "1.43",
  "MinAPIVersion": "1.12",
  "GitCommit": "afdd53b",
  "GoVersion": "go1.20.10",
  "Os": "linux",
  "Arch": "amd64"
}

该接口常用于检测 Docker 服务是否正常。


十一、查看容器列表

接口:

GET /containers/json

查看运行中的容器:

curl --unix-socket /var/run/docker.sock http://localhost/v1.43/containers/json

查看所有容器:

curl --unix-socket /var/run/docker.sock "http://localhost/v1.43/containers/json?all=true"

常见参数:

参数 说明
all=true 显示所有容器,包括停止状态
limit=10 限制返回数量
size=true 显示容器大小
filters 过滤条件

按名称过滤:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/json?all=true&filters=%7B%22name%22%3A%5B%22nginx%22%5D%7D"

其中 filters 是 URL 编码后的 JSON。

原始 JSON 为:

{
  "name": ["nginx"]
}

十二、查看容器详情

接口:

GET /containers/{id}/json

示例:

curl --unix-socket /var/run/docker.sock \
http://localhost/v1.43/containers/nginx/json

如果容器名是 my-nginx,可以这样调用:

curl --unix-socket /var/run/docker.sock \
http://localhost/v1.43/containers/my-nginx/json

该接口返回信息非常详细,包括:

  • 容器 ID;
  • 创建时间;
  • 启动命令;
  • 环境变量;
  • 挂载目录;
  • 网络配置;
  • 端口映射;
  • 容器状态;
  • 镜像 ID;
  • 日志路径。

生产环境中常用于排查容器配置是否符合预期。


十三、创建容器

接口:

POST /containers/create

创建一个 nginx 容器:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/containers/create?name=my-nginx" \
-H "Content-Type: application/json" \
-d '{
  "Image": "nginx:latest",
  "Cmd": [],
  "ExposedPorts": {
    "80/tcp": {}
  },
  "HostConfig": {
    "PortBindings": {
      "80/tcp": [
        {
          "HostPort": "8080"
        }
      ]
    },
    "RestartPolicy": {
      "Name": "always"
    }
  }
}'

说明:

  • name=my-nginx 表示容器名称;
  • Image 表示镜像;
  • ExposedPorts 表示容器暴露端口;
  • PortBindings 表示宿主机端口映射;
  • RestartPolicy 表示重启策略。

如果镜像本地不存在,创建容器可能失败。因此生产环境一般会先调用镜像拉取接口。


十四、拉取镜像

接口:

POST /images/create

拉取 nginx 镜像:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/images/create?fromImage=nginx&tag=latest"

拉取指定仓库镜像:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/images/create?fromImage=registry.example.com/app/backend&tag=v1.0.0"

如果是私有仓库,通常需要认证。可以通过 X-Registry-Auth 请求头传递认证信息,该值是 Base64 编码后的 JSON。

原始认证 JSON:

{
  "username": "admin",
  "password": "123456",
  "serveraddress": "registry.example.com"
}

编码后放入请求头:

-H "X-Registry-Auth: base64_string"

生产环境中,不建议在脚本里明文写密码,可以使用环境变量、密钥管理系统或 CI/CD 的 Secret 管理能力。


十五、启动容器

接口:

POST /containers/{id}/start

示例:

curl --unix-socket /var/run/docker.sock \
-X POST http://localhost/v1.43/containers/my-nginx/start

如果返回 HTTP 状态码 204,表示启动成功。


十六、停止容器

接口:

POST /containers/{id}/stop

示例:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/containers/my-nginx/stop?t=10"

参数说明:

参数 说明
t 等待容器优雅停止的秒数

例如 t=10 表示先发送停止信号,等待 10 秒,如果容器仍未退出,则强制停止。


十七、重启容器

接口:

POST /containers/{id}/restart

示例:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/containers/my-nginx/restart?t=10"

十八、删除容器

接口:

DELETE /containers/{id}

删除已停止容器:

curl --unix-socket /var/run/docker.sock \
-X DELETE http://localhost/v1.43/containers/my-nginx

强制删除容器:

curl --unix-socket /var/run/docker.sock \
-X DELETE "http://localhost/v1.43/containers/my-nginx?force=true"

生产环境中,删除容器前建议先确认:

  1. 容器是否属于目标业务;
  2. 是否有持久化数据;
  3. 是否存在挂载目录;
  4. 是否需要保留日志;
  5. 是否有依赖关系。

十九、查看容器日志

接口:

GET /containers/{id}/logs

示例:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/my-nginx/logs?stdout=true&stderr=true&tail=100"

常见参数:

参数 说明
stdout=true 返回标准输出
stderr=true 返回标准错误
tail=100 返回最后 100 行
since 从指定时间之后开始
follow=true 持续跟踪日志,类似 docker logs -f

实时查看日志:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/my-nginx/logs?stdout=true&stderr=true&follow=true"

需要注意的是,通过 API 返回的日志可能带有 Docker 的流头信息。如果用于日志平台采集,需要做解析处理。


二十、查看容器资源状态

接口:

GET /containers/{id}/stats

示例:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/my-nginx/stats?stream=false"

其中:

stream=false

表示只返回一次数据。

返回数据包括:

  • CPU 使用情况;
  • 内存使用情况;
  • 网络收发;
  • 块设备 IO;
  • PIDs 数量。

生产环境中,可以根据返回数据计算 CPU 使用率和内存使用率。

CPU使用率计算思路

Docker stats 返回的数据中通常包含:

  • cpu_stats.cpu_usage.total_usage
  • precpu_stats.cpu_usage.total_usage
  • cpu_stats.system_cpu_usage
  • precpu_stats.system_cpu_usage
  • cpu_stats.online_cpus

计算公式大致如下:

cpu_delta = cpu_total - precpu_total
system_delta = system_total - presystem_total
cpu_percent = cpu_delta / system_delta * online_cpus * 100

实际开发时建议做好空值判断,避免某些字段不存在导致计算异常。


二十一、查看镜像列表

接口:

GET /images/json

示例:

curl --unix-socket /var/run/docker.sock \
http://localhost/v1.43/images/json

查看全部镜像:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/images/json?all=true"

返回内容包括:

  • 镜像 ID;
  • RepoTags;
  • RepoDigests;
  • 创建时间;
  • 镜像大小;
  • 父镜像 ID。

二十二、删除镜像

接口:

DELETE /images/{name}

示例:

curl --unix-socket /var/run/docker.sock \
-X DELETE http://localhost/v1.43/images/nginx:latest

强制删除:

curl --unix-socket /var/run/docker.sock \
-X DELETE "http://localhost/v1.43/images/nginx:latest?force=true"

注意:如果镜像正在被容器使用,直接删除通常会失败。生产环境中不建议随意强制删除镜像,尤其是在多容器共享镜像的场景下。


二十三、使用Python调用Docker API

除了 curl,也可以用 Python 调用 Docker API。生产环境中更推荐使用 SDK,因为它封装了很多底层细节。

安装 Python Docker SDK:

pip install docker

1. 查看容器列表

import docker

client = docker.from_env()

containers = client.containers.list(all=True)

for c in containers:
    print(c.id, c.name, c.status)

2. 拉取镜像

import docker

client = docker.from_env()

image = client.images.pull("nginx", tag="latest")
print(image.id)

3. 创建并启动容器

import docker

client = docker.from_env()

container = client.containers.run(
    image="nginx:latest",
    name="my-nginx-python",
    ports={"80/tcp": 8081},
    detach=True,
    restart_policy={"Name": "always"}
)

print(container.id)

4. 获取日志

import docker

client = docker.from_env()

container = client.containers.get("my-nginx-python")
logs = container.logs(stdout=True, stderr=True, tail=100)

print(logs.decode("utf-8", errors="ignore"))

5. 停止并删除容器

import docker

client = docker.from_env()

container = client.containers.get("my-nginx-python")
container.stop(timeout=10)
container.remove()

二十四、使用Python requests调用Unix Socket

如果不想使用 Docker SDK,也可以通过 requests-unixsocket 调用。

安装依赖:

pip install requests requests-unixsocket

示例代码:

import requests_unixsocket

session = requests_unixsocket.Session()

url = "http+unix://%2Fvar%2Frun%2Fdocker.sock/v1.43/containers/json?all=true"

resp = session.get(url)
print(resp.status_code)
print(resp.json())

其中 /var/run/docker.sock 需要 URL 编码为:

%2Fvar%2Frun%2Fdocker.sock

这种方式适合需要直接控制 HTTP 请求细节的场景。


二十五、生产环境完整发布流程示例

下面给出一个生产环境中比较常见的容器发布流程。

目标:将业务服务 backend 更新到镜像版本 v2.0.0

流程如下:

  1. 拉取新镜像;
  2. 检查旧容器是否存在;
  3. 停止旧容器;
  4. 删除旧容器;
  5. 创建新容器;
  6. 启动新容器;
  7. 检查容器状态;
  8. 检查健康接口;
  9. 如果失败则回滚。

示例API流程

拉取镜像:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/images/create?fromImage=registry.example.com/backend&tag=v2.0.0"

停止旧容器:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/containers/backend/stop?t=20"

删除旧容器:

curl --unix-socket /var/run/docker.sock \
-X DELETE "http://localhost/v1.43/containers/backend?force=true"

创建新容器:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/containers/create?name=backend" \
-H "Content-Type: application/json" \
-d '{
  "Image": "registry.example.com/backend:v2.0.0",
  "Env": [
    "APP_ENV=prod",
    "TZ=Asia/Shanghai"
  ],
  "ExposedPorts": {
    "8080/tcp": {}
  },
  "HostConfig": {
    "PortBindings": {
      "8080/tcp": [
        {
          "HostPort": "8080"
        }
      ]
    },
    "RestartPolicy": {
      "Name": "always"
    },
    "Binds": [
      "/data/backend/logs:/app/logs",
      "/data/backend/config:/app/config"
    ]
  }
}'

启动新容器:

curl --unix-socket /var/run/docker.sock \
-X POST "http://localhost/v1.43/containers/backend/start"

检查容器状态:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/backend/json"

检查业务健康接口:

curl http://127.0.0.1:8080/health

如果健康检查失败,可以删除新容器并重新启动旧版本镜像。


二十六、生产环境实测经验总结

在真实生产环境中,Docker API 调用并不复杂,真正容易出问题的是权限、安全、异常处理和发布流程设计。

1. 一定要处理HTTP状态码

不同接口的成功状态码不完全相同。例如:

操作 常见成功状态码
查看列表 200
创建容器 201
启动容器 204
停止容器 204
删除容器 204
拉取镜像 200

不要简单地认为只有 200 才是成功,否则会误判。

2. 创建容器前先检查同名容器

如果同名容器已存在,创建会失败。因此发布流程中通常要先调用:

GET /containers/{name}/json

如果存在,再决定是停止删除,还是跳过创建。

3. 镜像拉取要设置超时

生产环境拉取镜像可能受网络、仓库、镜像大小影响。如果程序没有超时控制,可能导致发布任务长期阻塞。

4. 日志接口要限制tail数量

不要随意拉取全量日志,尤其是长期运行的容器,否则可能造成接口卡顿甚至影响 Docker Daemon。

推荐使用:

tail=100
tail=500
tail=1000

5. stats接口不要高频调用

资源统计接口如果调用过于频繁,会给 Docker Daemon 带来压力。对于普通监控,5 秒到 15 秒采集一次通常已经足够。

6. 删除操作必须谨慎

对于以下操作,建议做二次确认或权限控制:

  • 删除容器;
  • 删除镜像;
  • 删除数据卷;
  • 强制停止容器;
  • 强制删除容器。

7. 容器命名要规范

建议容器名称包含业务、环境和实例编号,例如:

prod-backend-01
prod-order-01
test-payment-01

这样 API 查询、日志检索、监控展示都会更清晰。


二十七、安全最佳实践

Docker API 的安全性必须高度重视。

1. 禁止公网暴露Docker API

不要把 Docker API 直接暴露在公网。即使使用了 TLS,也建议只允许内网访问。

2. 使用防火墙限制来源IP

例如只允许运维平台服务器访问 Docker API:

iptables -A INPUT -p tcp -s 192.168.1.10 --dport 2376 -j ACCEPT
iptables -A INPUT -p tcp --dport 2376 -j DROP

3. 使用TLS双向认证

生产环境推荐使用 TLS 双向认证,客户端必须携带证书才能访问 Docker API。

4. 不要在不可信容器中挂载docker.sock

很多工具会要求挂载:

-v /var/run/docker.sock:/var/run/docker.sock

这意味着容器内部可以控制宿主机 Docker。只有在完全可信的场景下才可以这样做。

5. 使用最小权限原则

如果是自研运维平台,不要把所有 Docker 操作都开放给普通用户。应该按角色授权,例如:

  • 只读用户:查看容器、查看日志;
  • 运维用户:启动、停止、重启;
  • 管理员:删除容器、删除镜像、修改配置。

二十八、常见问题排查

1. curl调用返回权限不足

错误类似:

permission denied

可能原因:

  • 当前用户没有访问 /var/run/docker.sock 权限;
  • 用户不在 docker 组;
  • Socket 文件权限异常。

解决方式:

sudo usermod -aG docker 当前用户名

重新登录后生效。

2. 远程调用连接不上

检查以下内容:

  1. Docker 是否监听 TCP 端口;
  2. 防火墙是否放行;
  3. 云服务器安全组是否放行;
  4. Docker 服务是否重启成功;
  5. 访问地址是否正确。

3. 创建容器失败

常见原因:

  • 镜像不存在;
  • 容器名称冲突;
  • 端口被占用;
  • 挂载目录不存在;
  • JSON 格式错误;
  • 镜像启动命令异常。

建议查看 Docker API 返回的错误信息,同时查看 Docker Daemon 日志:

journalctl -u docker -f

4. 容器启动后立即退出

可以查看容器日志:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/container_name/logs?stdout=true&stderr=true&tail=200"

也可以查看容器详情中的状态信息:

curl --unix-socket /var/run/docker.sock \
"http://localhost/v1.43/containers/container_name/json"

重点关注:

"State": {
  "Status": "exited",
  "ExitCode": 1,
  "Error": ""
}

二十九、结语

Docker API 是生产环境容器自动化管理的重要工具。通过它,我们可以用程序完成容器生命周期管理、镜像管理、日志读取、资源监控和自动化发布等工作。

不过,Docker API 的能力越强,安全风险也越高。尤其是远程 API 和 /var/run/docker.sock,一旦被非授权用户访问,就可能导致宿主机被控制。因此在生产环境中,推荐优先使用 Unix Socket 本地调用;如果必须远程调用,应使用 TLS 双向认证、防火墙限制、内网访问和严格权限控制。

总结来说,生产环境调用 Docker API 时应重点关注以下几点:

  1. 显式指定 API 版本;
  2. 优先使用 Unix Socket;
  3. 远程调用必须加认证和访问控制;
  4. 正确处理 HTTP 状态码;
  5. 对创建、删除、停止等操作做好异常处理;
  6. 日志和 stats 接口避免高频、全量调用;
  7. 发布流程要包含健康检查和回滚机制;
  8. 不要将 Docker API 暴露给不可信环境。

掌握 Docker API 后,你就可以构建更灵活、更自动化、更贴近生产实际的容器管理系统。

目录结构
全文