step-ca 0.30.2 Docker Compose 部署指南

step-ca 0.30.2 Compose 部署全流程:step ca init 初始化实录、password-file 注入、编排文件逐项解说、healthcheck 排障实录、签发第一张证书、持久化与升级回滚

Smallstep CertificatesSmallstep CertificatesPKI 证书证书管理2026/10/31

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 仓库仅当需要未发版补丁时使用

选型要点:

  1. 固定版本 tag:与《Smallstep Certificates 介绍与选型指南》中"0.30.2 已实证"保持一致,升级时改 tag 重拉即可;
  2. 一个镜像两个角色:CA 实例以 step-ca 命令运行,CLI 实例以 step 命令工作,避免再装一套 step CLI;
  3. 非 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 TypeStandalone独立 CA;多 CA 集中管理选 Linking(商业场景)
PKI 名称Interactive Lab CA仅显示用途
客户端可达 DNSca.lab.internal会写入 ca.json 的 dnsNames,务必填客户端真实可达名
监听地址:9000容器内固定 9000,由宿主机端口映射对外
首个 provisioner 名称iaadminJWK 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 → 服务 90009000 是 CA 的 HTTPS 端口
STEPPATH=/home/stepPKI 数据根路径官方镜像默认值,显式声明便于排查
volumesbind 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/stepPKI 数据根目录;官方镜像默认值,显式声明防歧义

step-ca 的其余行为均由 ca.json 配置文件控制(详解见《step-ca 0.30.2 配置参数详解》),无额外必要环境变量。

六、配置参数说明(Compose 层)

参数推荐值说明
restartunless-stopped崩溃自愈;维护窗口手动停机不受影响
healthcheck.interval30s探测频率,CA 属低频变更服务无需更密
healthcheck.retries3连续 3 次失败才判 unhealthy,避免抖动误报
healthcheck.timeout10s单次探测超时
ports8128: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=

十、升级与回滚

  1. 升级:改 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>
  1. 回滚:把 tag 改回旧版本并 docker compose up -d 即可,无需动数据目录;若新版本已写入数据库 schema 变更,回滚前先停服并整目录备份;
  2. 升级前必做: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 时必然校验失败。

十二、参考链接

  1. Smallstep 官方安装文档(含 Docker 方式) — https://smallstep.com/docs/step-ca/installation/ (查询日期 2026-10-31)
  2. 官方 Docker Hub 仓库 smallstep/step-ca — https://hub.docker.com/r/smallstep/step-ca (查询日期 2026-10-31)
  3. GitHub 仓库 smallstep/certificates — https://github.com/smallstep/certificates (查询日期 2026-10-31)
  4. 官方配置文档 — https://smallstep.com/docs/step-ca/configuration/ (查询日期 2026-10-31)
  5. 站内《Smallstep Certificates 介绍与选型指南》 — https://www.quzuo.net/document/KIfB9rTqBgRD