Docker 安装(CentOS 环境)
一、在线安装
步骤 1:安装仓库管理工具 yum-utils
bash
yum install -y yum-utils
为什么要装它 :
yum-config-manager这个命令由yum-utils提供 ------ 不先装它,就没法添加 Docker 仓库,也就不可能装到docker-ce。
步骤 2:添加 Docker 仓库(用阿里云镜像,国内快)
bash
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum-config-manager 是干嘛的 :它读写的就是 /etc/yum.repos.d/ 下面那些文件,专门用来增删、启用/禁用、查看和修改 yum 仓库配置。 它本身不装软件,只决定"yum 从哪里、能看见哪些仓库" ------ 加 Docker 源用它、切 MySQL 版本用它、临时屏蔽源也用它。
步骤 3:安装前置依赖包
bash
yum -y install device-mapper-persistent-data lvm2
为什么要装这两个:Docker 的存储驱动(overlay2 / devicemapper)依赖它们做设备映射和卷管理。
步骤 4:查看可安装的版本
bash
yum list docker-ce --showduplicates | sort -r
步骤 5:安装
默认装的是最新版,但生产环境最好挑稳定版本,比如这里的 docker-ce-24.0.9。
bash
yum install -y docker-ce-24.0.9 docker-ce-cli-24.0.9 containerd.io
步骤 6:启动 Docker 并设置开机自启
(略过)
步骤 7:处理 firewalld(生产环境可以用 docker zone)
bash
systemctl stop firewalld
systemctl disable firewalld
iptables -nL # 看一眼当前规则
systemctl restart docker # 关掉 firewalld 之后重启 docker,让它重新写 iptables 规则
步骤 8:验证安装
bash
docker version
docker info
docker version 预期输出 :重点看 Client 和 Server 都有内容,且版本一致。
常见报错(重要,理解"客户端"与"守护进程"的区别):
textCannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?这句表示客户端能跑,但守护进程没起来 。 解决:
systemctl start docker,然后systemctl status docker看具体报错。 顺序观察 :docker version会出现 Client 有内容、Server 报错的现象 ------ 这正说明"客户端和守护进程是两个东西"。
为什么要分 Client 和 Server(这是关键)
Docker 是客户端 / 服务端(C/S)架构,两者是完全独立的程序:
text
docker 命令(docker version / run / ps ...) ← 客户端,只是"发指令的"
│
│ 通过 unix:///var/run/docker.sock 这个文件通信
▼
dockerd(守护进程,真正干活的) ← 服务端
docker info 输出字段分析
text
Containers: 0 / Images: 0 ← 现在有几个容器、几个镜像,刚装完是 0,正常
Server Version: 24.0.9 ← 服务端版本
Storage Driver: overlay2 ← 镜像分层怎么存的
Backing Filesystem: xfs ← 底层文件系统
Logging Driver: json-file ← 容器里应用的日志默认存成 json 文件
Cgroup Driver: cgroupfs / Version: 1 ← 资源限制(限 CPU/内存)靠什么机制
Kernel Version: 3.10.0-1160.el7 ← 宿主机内核版本
CPUs: 1 / Total Memory: 972.3MiB ← 这台机器有多少资源可用
Docker Root Dir: /var/lib/docker ← 镜像和容器全部数据放这里
Registry Mirrors ← 镜像加速地址是否生效
挑几个最该记住的:
① Docker Root Dir: /var/lib/docker 所有镜像和容器都堆在这。磁盘满了先来这里看 :df -h /var/lib/docker。
② Storage Driver: overlay2 + Backing Filesystem: xfs 镜像是一层层叠出来的(基础层共享、可写层单独一份),overlay2 就是实现这个"分层 + 写时复制"的驱动。底层文件系统要在 xfs 上。
③ Logging Driver: json-file 容器里程序打印的日志,默认按 JSON 格式写在宿主机上。日志越攒越大撑爆磁盘,就是它干的(生产通常要配轮转或换成别的驱动)。
④ Cgroup Driver / Cgroup Version 限制容器能用多少 CPU、多少内存,靠的是 cgroup 这个内核机制。CentOS 7 内核老,所以是 cgroupfs + v1。 这个字段和 K8s 有关 ------ kubelet 和 Docker 的 cgroup driver 必须一致,不一致直接起不来。
⑤ Kernel Version: 3.10 内核太老。CentOS 7 自带的 3.10 跑容器能用,但 overlay2、cgroup v2 这些新特性支持不全。
⑥ Total Memory: 972.3MiB 内存不到 1G。跑一两个容器够,跑 K8s 集群会直接卡死(这也是选虚拟机配置时内存不能给太小的原因)。
步骤 9:跑第一个容器(验证真的可用)
bash
docker run hello-world
关键输出:
text
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
...
Hello from Docker!
This message shows that your installation appears to be working correctly.
这一条命令干了五件事 :① 检查本地有没有镜像 → ② 没有就从仓库下载 → ③ 用镜像创建 容器 → ④ 启动 容器执行 /hello → ⑤ 程序打印完退出,容器变成 Exited (0)。
检验:
bash
docker images # 应该能看到 hello-world
docker ps -a # 应该能看到刚才那个容器,STATUS 是 Exited (0)
Exited (0)不是报错 :0是退出码,表示正常退出。容器里的主进程执行完就退出了,容器自然就停了。
顺带搞清楚:镜像与容器
| 命令 | 看什么 |
|---|---|
docker images |
看本地有哪些镜像(看"库存") |
docker ps -a |
看有哪些容器 (看"运行记录");加 -a 表示所有容器,包括已退出的 |
那镜像与容器的区别与关系呢?
| 镜像(image) | 容器(container) | |
|---|---|---|
| 是什么 | 模板 / 安装包,只读 | 跑起来的实例,有状态 |
| 类比 | 类(class)、模具、ISO 安装盘 | 对象(object)、产品、装好的虚拟机 |
| 生命周期 | 拉下来就一直在,不会自己消失 | 创建 → 运行 → 退出,会留下记录 |
| 谁产生谁 | docker pull / build 得到 |
docker run 用镜像创建 |
一句话:镜像是"能跑的模板",容器是"跑出来的那个东西"。一个镜像可以开出很多个容器。
二、离线安装
适用场景 :服务器不能上外网,或公司有内网仓库时,需要用二进制包手动装 ,并做成系统服务。
步骤 1:下载二进制包(在能上网的机器上)
bash
wget https://mirrors.nju.edu.cn/docker-ce/linux/static/stable/x86_64/docker-28.5.2.tgz
也可以去
https://download.docker.com/linux/static/stable/x86_64/找对应版本。下载完拷到目标服务器(scp)。
步骤 2:解压并放到 PATH
bash
tar -xf docker-28.5.2.tgz # 解压出一个 docker/ 目录
cp docker/* /usr/bin/ # 把二进制都放到 /usr/bin
which dockerd # 检验:应输出 /usr/bin/dockerd
dockerd --version # 检验:能输出版本号
步骤 3:做成 systemd 服务(关键的一步)
ini
cat >/etc/systemd/system/docker.service <<'EOA'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOA
为什么需要这个文件 :二进制安装不会自动生成 systemd 单元 。不写它就只能手动敲
dockerd启动(关掉终端就没了),也没法开机自启、没法用systemctl status看状态。几个字段为什么这么写:
Type=notify:dockerd 启动完会主动通知 systemd,状态才准确LimitNOFILE=infinity:容器多时文件句柄消耗很大Delegate=yes:允许 docker 自己管理它的 cgroup(重要,否则容器里的 cgroup 操作会受限)KillMode=process:只杀主进程、不动容器,避免 stop docker 时把容器一起粗暴干掉
步骤 4:启动并设置开机自启
bash
systemctl daemon-reload # 新加了 unit 文件,必须 reload
systemctl start docker
systemctl enable docker
systemctl status docker # 期望 active (running) + enabled
步骤 5:验证
bash
docker version
docker run hello-world
离线安装的三个坑 : ① 忘了
systemctl daemon-reload→ 报Unit not found; ② 二进制没放进 PATH → 敲docker提示 command not found; ③ 只拷了docker没拷dockerd/containerd/runc→ 服务起不来,用journalctl -u docker -n 50看原因。
三、docker-compose 安装
关键前提 :如果是二进制安装的 Docker,是不包含 compose 功能的。 因为 compose 是独立发布的 CLI 插件。
先确认有没有:
bash
docker compose version # 新写法(子命令形式)
docker-compose version # 老写法(独立二进制)
环境里的实际输出是两个不同版本(说明两套都存在):
text
[root@r810-200 ~]# docker compose version
Docker Compose version v2.27.0
[root@r810-200 opt]# docker-compose version
Docker Compose version v2.38.0
方式 A:装成独立二进制(老写法 docker-compose)
bash
wget https://github.com/docker/compose/releases/download/v2.38.0/docker-compose-linux-x86_64 \
-O /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose version # 检验:Docker Compose version v2.38.0
方式 B:装成 CLI 插件(新写法 docker compose,推荐)
bash
mkdir -p /usr/libexec/docker/cli-plugins
mv /usr/local/bin/docker-compose /usr/libexec/docker/cli-plugins/docker-compose
docker compose version # 检验:Docker Compose version v2.x.x
为什么放这个目录 :Docker 会自动扫描
~/.docker/cli-plugins/、/usr/local/lib/docker/cli-plugins/、/usr/libexec/docker/cli-plugins/这三个目录,把里面的可执行文件注册成子命令。
坑(重要) :docker compose(带空格)和docker-compose(带横线)是两个不同的东西 ,版本可能不一样,行为也略有差别。写文档、写脚本时统一用一种 ,推荐统一用docker compose。两个混着用,会出现"命令能查到但 compose 文件解析报错"的怪现象。