跳到主要内容

Docker 执行器 Pro

使用 Docker 执行器时,运行器在新容器中启动每个任务,并在任务结束时删除该容器。 运行器通过 API 与 Docker 守护进程通信:守护进程可以在同一主机上,也可以是通过 TLS 连接的远程守护进程。

容器任务如何运行、容器内有什么以及哪些功能不受支持,请参见 执行器。本页介绍 Docker 的设置。

开始之前​

  • 拥有 Pro 或 Enterprise 许可证的 Semaphore 服务器。
  • 已在服务器上注册的运行器,参见运行器。请使用 semaphoreui/runner 镜像或官方 semaphore 二进制文件。
  • 运行器可以访问 Docker Engine,并具有使用权限:属于 docker 组、可访问挂载的 socket,或拥有 TLS 客户端证书。
  • 守护进程可以拉取 semaphoreui/job 和 semaphoreui/helper(或你自己的镜像)。

快速开始​

将执行器添加到运行器配置中并重启运行器:

{
"web_host": "https://semaphore.example.com",
"runner": {
"token_file": "/var/lib/semaphore/runner_token.txt",
"executor": {
"type": "docker"
}
}
}

没有其他选项时,运行器使用本地 socket(如果设置了 DOCKER_HOST 则使用它, 否则使用 unix:///var/run/docker.sock)、构建镜像 semaphoreui/job:latest 和 bridge 网络。

运行任意一个路由到该运行器的任务。任务日志以如下内容开头:

docker: prepared task 42 (workspace volume semaphore-workspace-42-a1b2c3, secrets=true)
=== git-clone ===
Cloning into '/workspace/repo'...
=== build ===
semaphore: container executor: task 42, template 7

任务运行期间,可以查看它的容器:

docker ps --filter label=com.semaphoreui.runner=semaphore

示例​

Docker 主机上的运行器二进制文件​

运行器作为 systemd 服务运行在 Docker 所在的同一主机上。为其用户授予 socket 访问权限:

sudo usermod -aG docker semaphore
sudo systemctl restart semaphore-runner
{
"web_host": "https://semaphore.example.com",
"tmp_path": "/tmp/semaphore",
"runner": {
"token_file": "/var/lib/semaphore/runner_token.txt",
"executor": {
"type": "docker",
"docker": {
"image": "semaphoreui/job:latest",
"cpu_limit": 2,
"memory_limit": "2g"
}
}
}
}

在容器中运行运行器并使用主机 socket​

运行器容器通过挂载的 socket 控制主机守护进程;任务容器与运行器是同级容器,而不是 嵌套在其中。运行器镜像以 UID 1001 运行,因此请将其加入拥有该 socket 的组:

docker run -d --name semaphore-runner \
--restart unless-stopped \
-e SEMAPHORE_WEB_ROOT=https://semaphore.example.com \
-e SEMAPHORE_RUNNER_REGISTRATION_TOKEN=<registration token> \
-e SEMAPHORE_RUNNER_EXECUTOR_TYPE=docker \
-v /var/run/docker.sock:/var/run/docker.sock \
-v semaphore-runner-data:/var/lib/semaphore \
--group-add "$(stat -c %g /var/run/docker.sock)" \
semaphoreui/runner:latest

semaphore-runner-data 卷保存注册时颁发的运行器令牌,因此运行器重启后不会再次注册。

使用 Docker Compose 的等效配置:

services:
runner:
image: semaphoreui/runner:latest
restart: unless-stopped
environment:
SEMAPHORE_WEB_ROOT: https://semaphore.example.com
SEMAPHORE_RUNNER_REGISTRATION_TOKEN: ${RUNNER_REGISTRATION_TOKEN}
SEMAPHORE_RUNNER_EXECUTOR_TYPE: docker
SEMAPHORE_RUNNER_DOCKER_IMAGE: semaphoreui/job:latest
SEMAPHORE_RUNNER_DOCKER_PULL_POLICY: if-not-present
SEMAPHORE_RUNNER_DOCKER_MEMORY_LIMIT: 2g
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- runner-data:/var/lib/semaphore
group_add:
- "${DOCKER_GID}" # stat -c %g /var/run/docker.sock

volumes:
runner-data:

机密信息通过守护进程上的命名卷传递给任务,从不经过运行器的文件系统,因此无需在 运行器和主机之间共享其他路径。

通过 TLS 连接远程 Docker 守护进程​

运行器和守护进程位于不同的机器上。使用双向 TLS 保护守护进程端口(参见 Protect the Docker daemon socket), 并将客户端文件放到运行器上:

/etc/semaphore/docker-certs/
├── ca.pem # CA that signed the daemon certificate
├── cert.pem # client certificate
└── key.pem # client key
{
"runner": {
"executor": {
"type": "docker",
"docker": {
"host": "tcp://docker-build-01.internal:2376",
"cert_path": "/etc/semaphore/docker-certs"
}
}
}
}

设置 cert_path 后,运行器使用 ca.pem 校验守护进程证书,并使用 cert.pem 和 key.pem 进行身份验证。文件名是固定的。

注意

不设置 cert_path 时,tcp:// 连接是明文 HTTP,任何能访问该端口的人都能控制守护 进程。仅设置 tls_verify 不会启用 TLS(⚠️ 2026-11-05:该选项会被读取但不会生效); 对于远程守护进程,请始终设置 cert_path。

用于内部服务的网络​

默认情况下任务容器加入 bridge 网络。若要让任务通过容器名访问服务,或将它们隔离在 单独的网络中,请创建一个网络并进行设置:

docker network create semaphore-tasks
{
"runner": {
"executor": {
"type": "docker",
"docker": {
"network": "semaphore-tasks"
}
}
}
}

network 接受 Docker 支持的任何网络模式:网络名称、bridge、host 或 none。 克隆容器加入同一网络,因此使用 none 时无法克隆仓库。

来自私有镜像仓库的镜像​

执行器拉取镜像时不使用镜像仓库凭据。对于私有镜像,请在守护进程主机上登录并拉取, 并保持一个不会重新拉取的拉取策略:

docker login registry.example.com
docker pull registry.example.com/semaphore/job-aws:1.0
{
"runner": {
"executor": {
"type": "docker",
"docker": {
"image": "registry.example.com/semaphore/job-aws:1.0",
"pull_policy": "if-not-present"
}
}
}
}

与 if-not-present 搭配时,请使用版本标签而不是 latest:守护进程上已存在的标签 永远不会刷新。never 会让缺失的镜像直接导致任务失败,而不是尝试拉取。

将整个块作为一个变量​

对于仅通过环境变量配置的部署,可以将执行器块作为 JSON 传入:

SEMAPHORE_RUNNER_EXECUTOR='{"type":"docker","docker":{"network":"semaphore-tasks","memory_limit":"4g","cpu_limit":2}}'

配置参考​

所有选项都位于运行器配置的 runner.executor.docker 下。

选项环境变量默认值说明
hostSEMAPHORE_RUNNER_DOCKER_HOSTDOCKER_HOST,其次是平台 socket守护进程地址:unix:///path、tcp://host:port 或 npipe:////./pipe/name。
cert_pathSEMAPHORE_RUNNER_DOCKER_CERT_PATH—包含 ca.pem、cert.pem 和 key.pem 的目录,用于双向 TLS。设置后即启用 TLS。
tls_verifySEMAPHORE_RUNNER_DOCKER_TLS_VERIFYfalse尚未生效;请使用 cert_path。
imageSEMAPHORE_RUNNER_DOCKER_IMAGEsemaphoreui/job:latest构建镜像。模板的 Executor image 会覆盖它。
helper_imageSEMAPHORE_RUNNER_DOCKER_HELPER_IMAGEsemaphoreui/helper:latest用于克隆容器和填充机密卷的镜像。
networkSEMAPHORE_RUNNER_DOCKER_NETWORKbridge克隆容器和构建容器的网络。
pull_policySEMAPHORE_RUNNER_DOCKER_PULL_POLICYif-not-presentalways、if-not-present 或 never。未知值回退为 if-not-present。
cpu_limitSEMAPHORE_RUNNER_DOCKER_CPU_LIMIT无限制每个容器的 CPU 数,类似 docker run --cpus。允许小数:0.5。
memory_limitSEMAPHORE_RUNNER_DOCKER_MEMORY_LIMIT无限制每个容器的内存:字节数,或带 k、m、g(512m、2g)。无法解析的值表示无限制。
privilegedSEMAPHORE_RUNNER_DOCKER_PRIVILEGEDfalse以 --privileged 运行容器。
cleanup_grace_secondsSEMAPHORE_RUNNER_DOCKER_CLEANUP_GRACE_SECONDS30点击 Stop 后 docker stop 在强制终止容器前等待的秒数。
poll_interval_secondsSEMAPHORE_RUNNER_DOCKER_POLL_INTERVAL_SECONDS2未使用:执行器等待容器退出,而不是轮询。

资源限制、网络和 privileged 同时适用于克隆容器和构建容器。

停止与清理​

UI 中的 Stop 会向正在运行的容器发送 docker stop,最多等待 cleanup_grace_seconds,然后删除容器和两个卷。

如果运行器进程在任务期间被终止,其容器和卷会留在守护进程上;运行器下次启动时不会 回收它们。执行器创建的所有对象都带有 com.semaphoreui.runner=semaphore 标签, com.semaphoreui.task-id 保存任务 ID。在该守护进程上没有任务运行时清理残留:

docker ps -a --filter label=com.semaphoreui.runner=semaphore
docker rm -f $(docker ps -aq --filter label=com.semaphoreui.runner=semaphore)
docker volume rm $(docker volume ls -q --filter label=com.semaphoreui.runner=semaphore)

故障排除​

消息原因与解决方法
docker executor is only available in the proprietary build(运行器日志)运行器是 Community 构建。请使用 semaphoreui/runner 或官方二进制文件。
docker executor: daemon not reachablehost 错误、守护进程未运行,或运行器用户无法打开 socket(permission denied)。以运行器用户执行 docker -H <host> info 检查;将该用户加入 socket 所属组。
pull image ...: ... unauthorized 或 not found镜像是私有的或名称拼写错误。请先在守护进程主机上拉取,参见私有镜像仓库。
git clone exited with status 128仓库 URL、分支或 SSH 密钥错误,或网络阻止了 Git 主机。该行上方的克隆输出会显示 Git 错误。
interpreter python3 not found in image; set a runner image that provides it构建镜像缺少应用二进制文件。请在运行器或模板的 Executor image 中设置包含它的镜像。
ssh-agent / ssh-add not found in image; skipping SSH key install镜像中没有 OpenSSH 客户端;Ansible 无法使用清单密钥。请安装 openssh-client。
/workspace 下的 Permission denied自定义镜像以无法写入 /workspace 的用户运行。参见构建自定义镜像。
build container exited with status N应用以退出码 N 失败;原因见上方日志。
inventory login_password authentication is not supported参见限制。