step-ca 0.30.2 Docker Compose 部署指南
step-ca 0.30.2 Compose 部署全流程:step ca init 初始化实录、password-file 注入、编排文件逐项解说、healthcheck 排障实录、签发第一张证书、持久化与升级回滚
step-ca 0.30.2 Docker Compose 部署指南
目标:用 Compose 把 Smallstep step-ca 0.30.2 跑起来——覆盖"网络与目录规划 → 交互式初始化 PKI → 编排文件逐项配置 → 启动与健康检查 → 签发第一张证书 → 数据持久化 → 升级与回滚"全流程;命令与回显均在 0.30.2 实例上实测,排障实录来自真实踩坑。
一、环境信息
- 操作系统:Linux x86_64(Ubuntu 22.04 内核系)
- Smallstep CA:
smallstep/step-ca:0.30.2(step-ca version回显Smallstep CA/0.30.2 (linux/amd64),Release Date: 2026-03-23 00:18 UTC) - Smallstep CLI:同一镜像内置,
step version回显Smallstep CLI/0.30.2 (linux/amd64),Release Date: 2026-03-22 23:21 UTC - Docker Compose:
Docker Compose version v5.6.1 - 端口规划:宿主机
8128→ 服务监听9000(CA 的 HTTPS API 端口) - 网络规划:专用外部网络
stepca-0302-net(子网自动分配为10.89.56.0/24) - 目录规划:
/opt/stepca/
├── docker-compose.yml # 编排文件(本篇第三节)
└── step/ # STEPPATH,PKI 全部数据(挂载到服务内 /home/step)
├── certs/ # root_ca.crt、intermediate_ca.crt 及签发的证书
├── config/ # ca.json、defaults.json
├── secrets/ # root_ca_key、intermediate_ca_key、password
├── db/ # badger 证书状态库
└── templates/ # 自定义证书模板
- 域名规划:CA 主机名
ca.stepca.internal(服务的 hostname),客户端测试域名acme-test.internal与acme-svc.internal.example.com - CA 管理密码(provisioner password):
q1w2e3r4
💡 说明:镜像内置
step(客户端)与step-ca(服务端)两个二进制,一个镜像即可同时充当 CA 与 CLI 两个角色,本文以两个实例分别扮演。
二、镜像选型说明
| 候选 | 结论 |
|---|---|
smallstep/step-ca:0.30.2 | ✅ 本文采用:官方镜像,版本号 tag 固定,自带 step CLI |
smallstep/step-ca:latest | ❌ 不建议生产:随上游漂移,升级不可控 |
自行编译 certificates 仓库 | 仅当需要未发版补丁时使用 |
选型要点:
- 固定版本 tag:与《Smallstep Certificates 介绍与选型指南》中"0.30.2 已实证"保持一致,升级时改 tag 重拉即可;
- 一个镜像两个角色:CA 实例以
step-ca命令运行,CLI 实例以step命令工作,避免再装一套 step CLI; - 非 root 运行:镜像内工作用户为
step(uid/gid=1000),bind mount 的宿主机目录需保证 uid 1000 可写(本篇排障实录 Q2)。
版本确认实测:
docker exec stepca-0.30.2-ca step-ca version
docker exec stepca-0302-cli step version
实测回显:
Smallstep CA/0.30.2 (linux/amd64)
Release Date: 2026-03-23 00:18 UTC
Smallstep CLI/0.30.2 (linux/amd64)
Release Date: 2026-03-22 23:21 UTC
三、部署步骤
3.1 创建专用网络
docker network create stepca-0302-net
docker network inspect stepca-0302-net --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
实测回显:
10.89.56.0/24
💡 说明:使用外部网络(compose 中
external: true)而非 compose 自动创建的默认网络,便于后续把其他实例(如 ACME 客户端)按域名接入同一平面。
3.2 目录准备与权限
mkdir -p /opt/stepca/step
chown -R 1000:1000 /opt/stepca/step # 镜像内 step 用户 uid=1000,bind mount 必须可写
3.3 首次初始化:交互式 step ca init
初始化生成 root/intermediate 两级 PKI 与 ca.json。以临时目录挂载方式执行交互式初始化(此处以 /tmp/pki-ia 作为 STEPPATH 演示):
docker compose run --rm stepca step ca init
真实交互实录(逐行照抄,密码输入时屏幕以 * 遮罩显示):
$ step ca init
✔ Deployment Type: Standalone
What would you like to name your new PKI?
✔ (e.g. Smallstep): Interactive Lab CA
What DNS names or IP addresses will clients use to reach your CA?
✔ (e.g. ca.example.com[,10.1.2.3,etc.]): ca.lab.internal
What IP and port will your new CA bind to? (:443 will bind to 0.0.0.0:443)
✔ (e.g. :443 or 127.0.0.1:443): :9000
What would you like to name the CA's first provisioner?
✔ (e.g. you@smallstep.com): iaadmin
Choose a password for your CA keys and first provisioner.
✔ [leave empty and we'll generate one]: **********(输入 q1w2e3r4,屏显为回显遮罩)
Generating root certificate... done!
Generating intermediate certificate... done!
✔ Root certificate: /tmp/pki-ia/certs/root_ca.crt
✔ Root private key: /tmp/pki-ia/secrets/root_ca_key
✔ Root fingerprint: 2436a48495cc06df3547d49b811240b2e1b6a7a6cf94c25c38083abf2333b161
✔ Intermediate certificate: /tmp/pki-ia/certs/intermediate_ca.crt
✔ Intermediate private key: /tmp/pki-ia/secrets/intermediate_ca_key
✔ Database folder: /tmp/pki-ia/db
✔ Default configuration: /tmp/pki-ia/config/defaults.json
✔ Certificate authority configuration: /tmp/pki-ia/config/ca.json
Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.
FEEDBACK 😍 🍻
The step utility is not instrumented for usage statistics. It does not phone
home. But your feedback is extremely valuable. Any information you can provide
regarding how you’re using `step` helps. Please send us a sentence or two,
good or bad at feedback@smallstep.com or join GitHub Discussions
https://github.com/smallstep/certificates/discussions and our Discord
https://u.step.sm/discord.
五次交互的填写口径:
| 提问 | 本文取值 | 说明 |
|---|---|---|
| Deployment Type | Standalone | 独立 CA;多 CA 集中管理选 Linking(商业场景) |
| PKI 名称 | Interactive Lab CA | 仅显示用途 |
| 客户端可达 DNS | ca.lab.internal | 会写入 ca.json 的 dnsNames,务必填客户端真实可达名 |
| 监听地址 | :9000 | 容器内固定 9000,由宿主机端口映射对外 |
| 首个 provisioner 名称 | iaadmin | JWK provisioner 的名字,签发时 --provisioner 引用 |
| CA 密码 | q1w2e3r4 | 加密中间 CA 私钥与 provisioner 私钥,泄露=CA 沦陷 |
⚠️ 注意:若留空密码,工具会随机生成且只显示一次;忘记密码将无法签发,务必记录。生产环境建议改用 3.4 的
--password-file免交互方式。
3.4 免交互初始化(生产推荐)
正式实例直接以 --provisioner 与 --password-file 完成 init,密码落盘 secrets/password(内容 q1w2e3r4),服务启动命令 --password-file /home/step/secrets/password 直接引用:
docker compose run --rm stepca sh -c 'step ca init \
--name "Interactive Lab CA" \
--dns ca.stepca.internal \
--address :9000 \
--provisioner admin \
--password-file /home/step/secrets/password \
--provisioner-password-file /home/step/secrets/password \
--deployment-type standalone'
💡 说明:CA 密码(解密中间 CA 私钥)与 provisioner 密码(JWK 签发签名)在 init 时同源生成;分文件管理是安全加固选项。
3.5 编排文件 docker-compose.yml
cat > /opt/stepca/docker-compose.yml <<'EOF'
name: step-ca-0.30.2-stack
networks:
stepca-net:
name: stepca-0302-net
external: true
services:
stepca:
image: smallstep/step-ca:0.30.2
container_name: stepca-0.30.2-ca
networks:
- stepca-net
extra_hosts:
- "acme-svc.internal.example.com:10.89.56.2" # ACME 测试域名指向客户端实例 IP
hostname: ca.stepca.internal
restart: unless-stopped
ports:
- "8128:9000"
environment:
- STEPPATH=/home/step
volumes:
- /opt/stepca/step:/home/step
command: step-ca /home/step/config/ca.json --password-file /home/step/secrets/password
healthcheck:
test: ["CMD", "step", "ca", "health", "--ca-url", "https://localhost:9000", "--root", "/home/step/certs/root_ca.crt"]
interval: 30s
timeout: 10s
retries: 3
EOF
逐项解说:
| 配置项 | 作用 | 要点 |
|---|---|---|
name: step-ca-0.30.2-stack | 项目名显式固定 | 避免随目录名漂移 |
networks.external | 复用已建外部网络 | 不再生成 <project>_default 网络 |
hostname: ca.stepca.internal | 服务内主机名 | 与 dnsNames 对应 |
extra_hosts | 把 ACME 测试域名写进 /etc/hosts | 指向客户端实例 IP 10.89.56.2 |
restart: unless-stopped | 崩溃自动拉起 | 手动 stop 后不自动启动 |
ports: 8128:9000 | 对外 8128 → 服务 9000 | 9000 是 CA 的 HTTPS 端口 |
STEPPATH=/home/step | PKI 数据根路径 | 官方镜像默认值,显式声明便于排查 |
volumes | bind mount 全量数据目录 | certs/config/secrets/db/templates 都在里面 |
command | 启动命令 + --password-file | 免交互注入 CA 密码,绕过 stdin 提问 |
healthcheck | 每 30s 探测 /health | 必须显式带 --ca-url 与 --root,见排障实录 Q1 |
3.6 启动与验证
docker compose up -d
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
stepca-0.30.2-ca smallstep/step-ca:0.30.2 "/bin/bash /entrypoi…" stepca 50 minutes ago Up 28 minutes (healthy) 0.0.0.0:8128->9000/tcp, [::]:8128->9000/tcp
服务启动日志(docker logs stepca-0.30.2-ca 节选,逐行照抄):
badger 2026/10/31 03:25:32 INFO: All 1 tables opened in 0s
badger 2026/10/31 03:25:32 INFO: Replaying file id: 0 at offset: 44311
badger 2026/10/31 03:25:32 INFO: Replay took: 7.037µs
2026/10/31 03:25:32 Building new tls configuration using step-ca x509 Signer Interface
2026/10/31 03:25:32 Starting Smallstep CA/0.30.2 (linux/amd64)
2026/10/31 03:25:32 Documentation: https://u.step.sm/docs/ca
2026/10/31 03:25:32 Community Discord: https://u.step.sm/discord
2026/10/31 03:25:32 Config file: /home/step/config/ca.json
2026/10/31 03:25:32 The primary server URL is https://localhost:9000
2026/10/31 03:25:32 Root certificates are available at https://localhost:9000/roots.pem
2026/10/31 03:25:32 Additional configured hostnames: ca.stepca.internal
2026/10/31 03:25:32 X.509 Root Fingerprint: 2a4d06b866972e6227494089dc788d6706f70f10ed102c7261607b860c45ff5e
2026/10/31 03:25:32 Serving HTTPS on :9000 ...
健康检查状态实测:
docker inspect stepca-0.30.2-ca --format '{{.State.Health.Status}}'
实测回显:
healthy
3.7 客户端签发第一张证书
在客户端实例上(本例 IP 为 10.89.56.2,已在 /etc/hosts 指向 ca.stepca.internal),从 CA 侧复制根证书到本地信任目录后签发:
# 1. 健康探测
step ca health --ca-url https://ca.stepca.internal:9000 --root root_ca.crt
# 2. 以 JWK provisioner 签发(密码文件注入避免交互)
echo q1w2e3r4 > .prov.pass
step ca certificate acme-test.internal acme-test.crt acme-test.key \
--ca-url https://ca.stepca.internal:9000 \
--root root_ca.crt \
--provisioner admin \
--password-file .prov.pass \
--not-after 24h
step ca health 实测回显:
ok
签发实测回显(逐行照抄):
✔ Provisioner: admin (JWK) [kid: 0oxx6mWKNZVsQGXbkVua5nuy-EV2zgCUCUIMy-odYpE]
✔ CA: https://ca.stepca.internal:9000
✔ Certificate: acme-test.crt
✔ Private Key: acme-test.key
💡 说明:客户端本地生成私钥,仅把 CSR 提交给 CA——私钥不出机是 step-ca 与传统"CA 集中生成再分发"工具的本质区别。命令全集见本专栏《step-ca 0.30.2 常用 CLI 命令详解》。
四、数据持久化说明
- 全部 PKI 状态集中在 bind mount 的
/home/step一个目录,实例销毁重建不丢数据; db/是 badger 嵌入式 KV 库,记录证书序列号与吊销状态,实测目录内容:
000000.vlog # value log
000014.sst # SST 表文件
KEYREGISTRY
LOCK # badger 运行锁,服务运行期间存在
MANIFEST
certs/与secrets/是 PKI 命根:root/intermediate 证书与加密后的私钥;secrets/password是解密钥匙,三者都需备份;- 备份口径:停服后整目录打包(badger 写入中备份可能不一致):
docker compose stop
tar -czf step-backup-$(date +%F).tar.gz step/
docker compose start
- 重启验证:
docker compose restart后 badger 重放日志(启动日志中的Replaying file id: 0行),已签发证书状态保留。
五、环境变量表
| 变量 | 本文取值 | 说明 |
|---|---|---|
STEPPATH | /home/step | PKI 数据根目录;官方镜像默认值,显式声明防歧义 |
step-ca 的其余行为均由 ca.json 配置文件控制(详解见《step-ca 0.30.2 配置参数详解》),无额外必要环境变量。
六、配置参数说明(Compose 层)
| 参数 | 推荐值 | 说明 |
|---|---|---|
restart | unless-stopped | 崩溃自愈;维护窗口手动停机不受影响 |
healthcheck.interval | 30s | 探测频率,CA 属低频变更服务无需更密 |
healthcheck.retries | 3 | 连续 3 次失败才判 unhealthy,避免抖动误报 |
healthcheck.timeout | 10s | 单次探测超时 |
ports | 8128:9000 | 对外端口避开常用冲突段,按实际规划 |
extra_hosts | 按需 | 内网无 DNS 时用 /etc/hosts 解析客户端域名 |
七、配置文件挂载
- 本文采用整目录挂载(
/opt/stepca/step:/home/step):certs/config/secrets/db 一次到位,init、运行、备份路径一致,最省心; - 备选只读挂载:把
config/ca.json单文件以:ro挂入,其余目录用 named volume——适合配置由 Git 管理的 IaC 流水线;注意db/与secrets/必须可写持久化; - 修改
ca.json后需重启进程生效(docker compose restart),生效验证方法见配置详解篇。
八、等价 docker run
不用 Compose 时,以下命令等价于上述编排(排障实录 Q2 涉及其中参数):
docker run -d \
--name stepca-0.30.2-ca \
--network stepca-0302-net \
--hostname ca.stepca.internal \
--restart unless-stopped \
-p 8128:9000 \
-e STEPPATH=/home/step \
-v /opt/stepca/step:/home/step \
--health-cmd "step ca health --ca-url https://localhost:9000 --root /home/step/certs/root_ca.crt" \
--health-interval 30s --health-timeout 10s --health-retries 3 \
smallstep/step-ca:0.30.2 \
step-ca /home/step/config/ca.json --password-file /home/step/secrets/password
九、常用运维命令
docker compose ps # 实例状态与健康
docker compose logs -f stepca # 跟踪 CA 日志(含每次签发/续期审计行)
docker compose restart stepca # 改 ca.json 后重启生效
docker compose stop && docker compose start
docker compose down # 停止并移除实例(bind mount 数据不受影响)
docker compose down && docker compose up -d # 重建实例(数据保留)
日志审计样例(每次客户端请求一行 JSON 日志,节选 /health 探测行):
time="2026-10-31T03:25:37Z" level=info duration="38.188µs" duration-ns=38188 fields.time="2026-10-31T03:25:37Z" method=GET name=ca path=/health protocol=HTTP/2.0 referer= remote-address=10.89.56.2 request-id=c98646bc-938c-40bd-8c5a-6163ba257c1d size=16 status=200 user-agent="Smallstep CLI/0.30.2 (linux/amd64)" user-id=
十、升级与回滚
- 升级:改 tag → 拉新镜像 → 重建(PKI 数据在 bind mount,格式向后兼容,小版本无损):
sed -i 's|smallstep/step-ca:0.30.2|smallstep/step-ca:<new-version>|' docker-compose.yml
docker compose pull
docker compose up -d
docker compose logs --tail 20 stepca # 确认 Starting Smallstep CA/<new-version>
- 回滚:把 tag 改回旧版本并
docker compose up -d即可,无需动数据目录;若新版本已写入数据库 schema 变更,回滚前先停服并整目录备份; - 升级前必做:
docker compose stop后备份step/整目录(见第四节),尤其是db/与secrets/。
十一、常见问题
Q1:实例状态一直 unhealthy,健康检查 ExitCode 1 且无输出?
排障实录:本环境客户端角色实例曾长期 unhealthy,docker inspect 显示 FailingStreak: 38、每次探测 ExitCode: 1。根因是健康检查命令写成 step ca health | grep ok——step ca health 不带 --ca-url 时默认探测本机 localhost 的 CA,客户端角色实例本机并没有 CA 进程,探测永远失败。修正:探测目标必须指向实际 CA 地址与根证书:
step ca health --ca-url https://ca.stepca.internal:9000 --root /home/step/work/root_ca.crt
修正后实例即转 healthy。判 healthy 的 CA 实例检查实测:docker inspect --format '{{.State.Health.Status}}' 回显 healthy,探测日志 ExitCode 0, Output: ok。
Q2:docker run 报 unknown flag: --extra-hosts?
排障实录:部分环境 Docker 版本不认 --extra-hosts 长参数(报 unknown flag: --extra-hosts),改用等价旧参数 --add-host "域名:IP" 即可;Compose 文件中 extra_hosts: 键不受影响。
Q3:启动即失败,日志报权限错误?
镜像以 uid=1000 的 step 用户运行,bind mount 宿主机目录若属主为 root 则无法写 db/LOCK 等文件。解法:chown -R 1000:1000 /opt/stepca/step。
Q4:badger 报 LOCK 冲突起不来?
db/LOCK 表明已有进程持有数据库。同一数据目录只能被一个 step-ca 进程使用:确认没有第二个实例挂同一目录;异常退出残留锁时,停服删除 db/LOCK 后再启动(badger 会自动重放恢复)。
Q5:step ca certificate 报 x509 证书校验失败?
客户端连接用的主机名必须出现在 CA 的 dnsNames 列表内(本文为 localhost 与 ca.stepca.internal),且 --root 指向同一份 root_ca.crt。用 IP 直连而 IP 不在 dnsNames 时必然校验失败。
十二、参考链接
- Smallstep 官方安装文档(含 Docker 方式) — https://smallstep.com/docs/step-ca/installation/ (查询日期 2026-10-31)
- 官方 Docker Hub 仓库 smallstep/step-ca — https://hub.docker.com/r/smallstep/step-ca (查询日期 2026-10-31)
- GitHub 仓库 smallstep/certificates — https://github.com/smallstep/certificates (查询日期 2026-10-31)
- 官方配置文档 — https://smallstep.com/docs/step-ca/configuration/ (查询日期 2026-10-31)
- 站内《Smallstep Certificates 介绍与选型指南》 — https://www.quzuo.net/document/KIfB9rTqBgRD