每次拿到一台新服务器,装 Docker 都是一套固定流程:更新索引、装 ca-certificates curl gnupg、导入 GPG 公钥、写 apt 源、再 update、装一堆包、配镜像加速、启动服务、设开机自启。官方文档十来步,照着敲五分钟,敲错一个字符就得从头排查。
这套流程我写成了脚本放在 GitHub 上,现在只需要一行:
curl -fsSL -o /tmp/docker.sh https://raw.githubusercontent.com/shubaocai/sbc-docker/main/install_docker.sh && sudo bash /tmp/docker.sh
仓库地址:github.com/shubaocai/sbc-docker
这行命令拆开看
两个动作,用 && 串起来。
第一步,下载
curl -fsSL -o /tmp/docker.sh <url>
把远端文件存成本地的 /tmp/docker.sh。注意 -o 后面跟的是完整文件路径,不是目录——它由"目录 + 文件名"拼成,curl 不会替你补文件名。
第二步,执行
sudo bash /tmp/docker.sh
&& 表示前一条成功了才执行后一条。curl 没拿到文件,后面的 bash 就不会跑——这正是"两步走"比管道安全的地方。
四个参数分别管什么
| 参数 | 作用 | 少了会怎样 |
|---|---|---|
| -f | HTTP 4xx/5xx 时返回非零退出码 | 404 的 HTML 会被当脚本执行 |
| -s | 不显示进度条 | 只影响观感 |
| -S | 出错时仍然打印错误 | 搭配 -s 用,否则失败时静默 |
| -L | 跟随重定向 | CDN 跳转时可能拿到空文件 |
-f 是最关键的那个。 没有它,curl 遇到 404 也返回 0,&& 会放行,然后 bash 拿着一个 HTML 页面去执行,报一屏语法错误。
为什么不用 curl | sudo bash
一键脚本里这个写法太常见了:
curl -fsSL https://... | sudo bash
它有两个问题。
一是失败拦不住。 管道里 $? 取的是最后一个命令的退出码,bash 的退出码盖住了 curl 的。curl 断在下载途中,bash 照样执行已经收到的半截脚本——而这是个要用 root 权限改系统配置的脚本。
二是你没看过它。 无论哪种写法,直接执行远端脚本都是在信任作者。差别在于:管道写法连"看一眼"的机会都不给你。
分两步至少留了个文件,可以先 less /tmp/docker.sh 翻一遍,再决定跑不跑。
脚本做了什么
- 先判断再动手。检测到
docker命令已存在,就只做健康检查(服务在不在跑、有没有开机自启),然后退出。反复执行不会出问题。 - 环境校验。非 root、没有 systemd、不是 Ubuntu/Debian,一律报错退出,不硬来。
- 自动识别系统。从
/etc/os-release读发行版和代号(jammy 等),用dpkg --print-architecture取架构,拼出对应的 apt 源地址。 - 安装。依赖 → GPG 公钥 → apt 源 →
docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin。 - 配置镜像加速。写入
/etc/docker/daemon.json,已有文件会先备份、不覆盖。 - 启动并验证。
systemctl enable --now docker,再确认服务真的起来了,最后打印版本汇总。
两个默认值,可能需要改
脚本顶部有两个变量:
DOCKER_APT_MIRROR="https://mirrors.aliyun.com/docker-ce"
REGISTRY_MIRROR="https://mirror.ccs.tencentyun.com"
DOCKER_APT_MIRROR是装 Docker 软件包的源,默认走阿里云。想用官方源加--official。REGISTRY_MIRROR是拉取镜像的加速器,默认填的是腾讯云内网地址,只在腾讯云的机器上有效。如果服务器不在腾讯云,加--no-mirror跳过,或者自己换一个可用地址。
配错了不会导致安装失败,但 docker pull 会很慢甚至超时,这点容易被忽略。
如果 raw 域名连不上
raw.githubusercontent.com 在国内经常不通。换 jsDelivr CDN:
curl -fsSL -o /tmp/docker.sh https://cdn.jsdelivr.net/gh/shubaocai/sbc-docker@main/install_docker.sh && sudo bash /tmp/docker.sh
jsDelivr 是正规 CDN,比各种免费代理稳定。缺点是有缓存,push 之后可能得等几分钟才生效。
或者干脆把仓库 clone 下来,以后 git pull 增量更新:
git clone https://github.com/shubaocai/sbc-docker.git
cd sbc-docker && sudo bash install_docker.sh
一个容易踩的坑
别把 blob 链接当成 raw 链接用。
❌ github.com/shubaocai/sbc-docker/blob/main/install_docker.sh ← 这是网页,返回 HTML
✅ raw.githubusercontent.com/shubaocai/sbc-docker/main/install_docker.sh
blob 那个是浏览器里看到的文件页面,返回的是一整页 HTML。更要命的是它返回 200,所以 -f 拦不住,&& 照样放行,bash 拿着 HTML 就去执行了。
保险做法是在执行前确认下到的是不是脚本:
head -1 /tmp/docker.sh | grep -q '^#!' && sudo bash /tmp/docker.sh
网页第一行是 <!DOCTYPE html>,不以 #! 开头,这一步就能拦住。
最后
脚本在 github.com/shubaocai/sbc-docker,MIT 协议,随便用。