ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CentOS 7.9安装Docker实战:从yum源配置到Compose编排

CentOS 7.9安装Docker实战:从yum源配置到Compose编排 1. 安装前准备工作环境检查与依赖梳理1.1 先确认内核版本和系统版本CentOS 7.9到今天仍然在大量服务器上跑着虽然官方已经停止维护但存量设备实在太多很多机房、内部系统、离线环境还在用。在这些机器上装Docker第一件事不是急着敲命令而是先看清楚系统底子。先看系统版本cat /etc/redhat-release正常会输出CentOS Linux release 7.9.2009 (Core)。接着看内核uname -rDocker官方对CentOS 7的最低内核要求是3.107.9默认内核一般在3.10.0-1160.el7.x86_64左右满足要求。但这里有个非常关键的经验内核版本低直接影响Docker的存储驱动和网络性能。如果你手里的机器内核还停在3.10.0-514这种老版本我建议先执行一次系统更新至少把内核升到1160系列不然跑高负载容器时容易出现io卡顿、容器频繁重启的问题。内核升级命令yum update -y kernel更新完后需要重启系统重启后确认内核版本已经变化。实测中很多人在这一步偷懒跳过结果后面跑容器时遇到kernel:unable to handle kernel paging request之类的错误排查一圈才发现是内核太旧。这个坑我踩过一次后来只要有新机器装Docker内核没到1160我绝对不动手。1.2 清理旧版本Docker与依赖有些机器可能之前装过docker或者docker-engine这类旧包如果不清理干净跟docker-ce装在一起会产生冲突。先查一下yum list installed | grep docker如果有输出逐个卸载yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine注意这条命令会把老版本的docker、docker-engine都清理掉但不会删除/var/lib/docker目录下的数据。如果你之前的容器数据还要用先备份这个目录如果确定不要了可以顺手删掉避免新旧数据混在一起造成诡异现象。另外还要检查containerd和runc。Docker新版本依赖独立的containerd旧版本可能自带一个runc冲突时会出现runc: symbol lookup error这类问题。保守做法是装新版docker-ce时让yum自己解析依赖不要手动装指定版本的runc。很多时候Docker启动失败不是Docker本身的问题而是系统里残留的老库在捣乱。1.3 网络与yum源准备CentOS 7.9停止维护后默认的mirrorlist失效直接用yum装东西经常报Could not resolve host: mirrorlist.centos.org。装Docker之前先把基础yum源切到可用状态。我常用的做法是换成阿里云的vault源curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo sed -i s/mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-Base.repo sed -i s|#baseurlhttp://mirror.centos.org|baseurlhttp://mirrors.aliyun.com|g /etc/yum.repos.d/CentOS-Base.repo然后清理缓存yum clean all yum makecache这里顺便提一句如果你的机器处于内网环境连外网受限那更需要在本地准备好docker-ce的rpm包或者内网yum源离线安装的思路我在后面的章节单独说。网络这东西看起来是个废话问题但实际部署时因为yum源失效而卡住的案例我见过太多了。2. 正式安装从yum源配置到命令上手2.1 配置docker-ce的yum源Docker官方仓库在海外直接配置后下载速度慢到怀疑人生。国内建议用阿里云或清华的docker-ce镜像源。我一般用阿里云yum install -y yum-utils yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo装完yum-utils后yum-config-manager这个命令才会存在。注意yum-config-manager --add-repo会自动写入repo文件但写入的地址可能还是官方源需要再确认一下cat /etc/yum.repos.d/docker-ce.repo看到baseurlhttps://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable这段才是对的。如果不是手动把download.docker.com替换成mirrors.aliyun.com。这一步能省很多时间默认官方源我在国内服务器上实测下载速度经常不到10KB/s换阿里云后基本能跑到满速。如果你是海外服务器那直接用官方repo就行不用折腾。2.2 安装docker-ce与关键组件执行安装yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin这里说下这几个包各自的职责docker-ceDocker服务端核心也就是daemon进程docker-ce-clidocker命令行工具负责跟daemon通信containerd.io容器运行时管理组件新版Docker通过containerd来管理容器生命周期docker-compose-pluginCompose V2插件支持docker compose命令用来编排多容器如果你只是随手想装个Docker玩玩只装前三个也够用。但如果你打算后面跑MySQLRedisNginx这种组合compose插件强烈建议一起装上用起来太舒服了。安装完查看版本docker --version老一点的版本输出类似Docker version 24.0.7新一点的可能是26.x甚至更高。Docker小版本迭代很快只要能用就行不用追求最新。最新版有时候会对内核有额外要求CentOS 7.9这种老系统反而适合装稍旧一点的稳定版。2.3 启动服务与验证安装结果安装完后Docker服务默认是停止状态需要手动启动systemctl start docker systemctl enable dockerenable的作用是设置开机自启服务器上一定要做这一步不然机器重启后Docker没起来你的容器全挂了排查起来很痛苦。验证Docker是否健康看两条信息systemctl status docker状态显示active (running)说明服务正常。再执行docker info这个命令会输出Docker的详细环境信息包括宿主机内核、存储驱动、镜像数量等。如果这里报Cannot connect to the Docker daemon说明daemon没起来优先看服务日志journalctl -u docker --no-pager | tail -50日志里最常见的信息是iptables相关错误后面我在问题排查章节细说。3. 镜像加速与常用镜像实战3.1 配置镜像加速器Docker Hub的镜像拉取在多数网络环境下都不稳定超时断流是家常便饭。解决思路是配置镜像加速器或者叫registry mirror。国内主流云厂商都提供Docker镜像加速服务从你的云厂商控制台能拿到专属地址。以阿里云为例在控制台搜“容器镜像服务”找到镜像加速器页面会给你一个https://xxxx.mirror.aliyuncs.com的地址。配置方式mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { registry-mirrors: [https://你的专属加速地址.mirror.aliyuncs.com] } EOF配置完重启Dockersystemctl daemon-reload systemctl restart docker验证加速器是否生效docker info | grep -A 1 Registry Mirrors看到你的加速地址列表就说明配置成功。这里多说一句如果你是在纯内网环境部署daemon.json里还需要配置insecure-registries来允许访问内网仓库否则拉取内网镜像时会报证书错误。经验之谈内网环境第一件事往往不是装Docker而是确认私有仓库地址怎么访问不然装好了也是个摆设。3.2 拉取CentOS、MySQL、Redis、Nginx等常用镜像加速器配好后拉镜像就顺畅多了。下面是我常用的几个镜像及其典型用途。先来个小测试拉一个最基础的镜像docker pull centos:7.9.2009虽然CentOS 7.9已经停止维护但很多老业务系统还在用它当基础镜像这个镜像拉下来做个基础环境还是很方便的。再看MySQL目前生产环境用得最多的版本是8.0和5.7docker pull mysql:8.0 docker pull mysql:5.7Redis在缓存场景和消息队列场景都有应用docker pull redis:7Nginx用做前端静态资源服务和反向代理docker pull nginx:1.24如果你要做Java应用部署openjdk镜像也常备docker pull openjdk:8u342拉镜像时可以用docker images查看本地已有的镜像列表用docker rmi 镜像名删除不需要的镜像。这块没什么难度真正的坑都在后面启动容器的时候。3.3 容器启动参数解读端口映射、数据卷、时区这里我以MySQL和Redis为重点讲因为这两个容器启动参数最繁琐也最容易出错。先看MySQLdocker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDYourPassword123 \ -e TZAsia/Shanghai \ -v /data/mysql:/var/lib/mysql \ -v /etc/localtime:/etc/localtime:ro \ --restartalways \ mysql:8.0逐个解释参数含义-d后台运行容器不会占据当前终端--name给容器起名字后续管理靠这个名字-p 3306:3306宿主机3306端口映射到容器3306端口。宿主机端口可以改比如-p 33061:3306容器内MySQL始终监听3306-e MYSQL_ROOT_PASSWORD指定root密码这是MySQL镜像特有的初始化环境变量-e TZAsia/Shanghai设置容器时区不设置的话容器内默认是UTC时间日志时间会慢8小时-v /data/mysql:/var/lib/mysql数据卷挂载容器内MySQL数据实际存在宿主机/data/mysql目录下。这个参数至关重要没有它容器一删数据全没-v /etc/localtime:/etc/localtime:ro把宿主机的时区文件映射进容器保证容器内时间和宿主机一致--restartalwaysDocker服务重启后容器自动启动为什么数据卷这么重要因为容器本身是无状态的docker rm一执行容器里的所有文件都会被清掉。如果你没挂数据卷MySQL数据就跟着容器一起消失了这个教训可以说是Docker新手必须付的学费。再看Redis比MySQL简单一些但有个小坑docker run -d \ --name redis7 \ -p 6379:6379 \ -v /data/redis:/data \ --restartalways \ redis:7 --requirepass YourRedisPassword注意最后的--requirepass YourRedisPassword这个看似是给redis-server传参实际是镜像的默认启动命令redis-server接收的追加参数。容器启动时镜像默认执行redis-server后面跟的--requirepass会被拼接进去从而设置访问密码。如果要挂载自定义的redis.conf配置文件可以这样docker run -d \ --name redis7 \ -p 6379:6379 \ -v /data/redis/redis.conf:/etc/redis/redis.conf \ -v /data/redis:/data \ redis:7 redis-server /etc/redis/redis.conf注意挂载配置文件时宿主机上的配置文件必须是完整的redis.conf如果文件内容为空容器会启动失败。原因很简单挂载相当于把宿主机文件覆盖到容器路径上空文件覆盖掉镜像内自带的配置redis也就不知道去哪里加载设置了。Nginx的启动一般涉及静态文件和配置文件的挂载docker run -d \ --name nginx \ -p 80:80 \ -v /data/www:/usr/share/nginx/html:ro \ -v /data/nginx/conf.d:/etc/nginx/conf.d:ro \ --restartalways \ nginx:1.24挂载目录用:ro后缀可以限制容器内对该目录只读提高安全性。Nginx容器默认会读取/etc/nginx/conf.d/下的所有conf文件你可以把自己的站点配置放在宿主机/data/nginx/conf.d/下改配置不用进容器改完宿主机文件再docker exec nginx nginx -s reload重载即可。4. 常见问题排查与避坑实录4.1 CentOS 7.9的存储驱动与内核兼容问题CentOS 7.9默认的存储驱动是overlay2但你可能会在某些机器上看到Docker自动降级成了devicemapper。这意味着容器磁盘性能会变差尤其是在大量文件读写的场景下差距非常明显。检查方法docker info | grep Storage Driver如果输出是devicemapper最好切回overlay2。在/etc/docker/daemon.json中加{ storage-driver: overlay2 }但前提是内核支持overlayfs。CentOS 7.9的内核在3.10.0-1160版本上对overlay2的支持已经比较稳定。如果你的内核低于这个版本切到overlay2后容器可能会崩溃。这种情况我建议先升级内核再切换存储驱动顺序不能反。另一个和内核相关的经典报错是cannot stat /var/lib/docker/overlay2/xxx: no such file or directory这种问题多半是之前系统异常重启导致overlay目录数据不一致。解决方法不复杂但有点粗暴systemctl stop docker rm -rf /var/lib/docker/overlay2 systemctl start docker注意/var/lib/docker下的overlay2目录存放的是镜像和容器层数据删掉后所有容器和镜像都没了但数据卷带-v挂载的目录不受影响。一定要确认数据卷都挂在宿主机外部路径再执行这个操作。4.2 Docker启动失败、无法拉取镜像的处理思路Docker启动失败最常见的是这两种。第一种是iptables相关错误报错内容里通常会出现Failed to start Docker Application Container Engine。CentOS 7自带的firewalld和Docker有历史兼容问题Docker启动时会修改iptables规则firewalld偶尔会拦一把。推荐做法是停用firewalld改用iptables服务systemctl stop firewalld systemctl disable firewalld生产环境如果此前依赖firewalld的防火墙规则这一步要慎重最好先导出现有规则再操作。如果只想放行某些端口也可以在firewalld里添加富规则但说实话和Docker搭伙干活firewalld越少介入越省心。第二种是docker daemon的socket权限问题现象是普通用户执行docker ps报permission denied while trying to connect to the Docker daemon socket原因很简单docker.sock 只对root开放你的普通用户没有权限访问。解决方式是把用户加入docker组usermod -aG docker $USER然后重新登录当前会话再执行docker ps就正常了。这里提醒一句加入docker组的用户其实等同于拿到了root权限因为容器可以挂载宿主机目录所以在多人共用服务器时要谨慎授权docker组。拉取镜像超时的处理除了前面说的配置加速器还可以手动指定镜像源拉取。比如从阿里云容器镜像服务的公开仓库拉取docker pull registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0拉下来后再打上官方tagdocker tag registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0 mysql:8.0 docker rmi registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0这个方法在没有加速器可用或者加速器不够快时非常实用相当于手动指定镜像地址。4.3 systemd管理、防火墙放行与开机自启服务器上装完Docker后还需要处理好宿主机防火墙的端口放行问题。容器端口映射到宿主机后外部流量要进得来必须在宿主机防火墙层放行。如果你用的是阿里云ECS、腾讯云这类云服务器除了系统内部防火墙云平台的安全组也记得放行对应端口。这两层缺一不可很多人的容器明明启动了外部就是访问不了查了半天发现是云平台安全组没放行。系统内部以iptables示例放行3306端口iptables -I INPUT -p tcp --dport 3306 -j ACCEPT如果想要规则持久化安装iptables-services后保存yum install -y iptables-services service iptables save再说回开机自启的问题。我在2.3节提到过systemctl enable docker这是让Docker服务本身开机启动。但如果你用docker run创建的容器没加--restartalwaysDocker服务重启后容器不会自动拉起。对于已经创建的容器可以用命令更新重启策略docker update --restartalways 容器名或者查看当前策略docker inspect 容器名 | grep -A 5 RestartPolicy--restartalways也有小坑如果容器一直启动失败比如配置文件写错进程反复崩溃Docker会一直尝试重启导致日志爆炸。遇到这种场景可以把策略改成--restartunless-stopped这个策略下容器正常退出后会被自动拉起但如果容器处于停止状态不会强制拉起来。实战中我习惯用unless-stopped避免在排障时容器不断自动重启干扰定位。4.4 磁盘空间与容器日志增长的隐患容器跑久了最隐蔽的问题是日志文件无限增长。尤其是Nginx、应用服务这类日志量大的容器/var/lib/docker/containers/容器ID/下的json日志文件能轻松吃掉几十GB磁盘。解决方案有两种。一是在全局daemon.json中限制日志大小{ log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }二是对单个容器加参数docker run -d \ --log-opt max-size100m \ --log-opt max-file3 \ nginx配置生效后单个容器的日志最多占300MB超过自动滚动不会再把磁盘写满。这类问题在初始部署时很少有人注意通常要到磁盘报警才发现。经验就是所有容器化环境日志限制从第一天就要配好。磁盘本身也需要关注CentOS 7.9默认分区方案很多时候只给根目录几十GBDocker默认把数据都放在/var/lib/docker下一旦镜像多、容器多根分区很容易爆。建议在安装Docker前用独立的个大分区来挂载Docker数据目录或者在/etc/docker/daemon.json里指定数据目录到空间充足的盘{ data-root: /data/docker }修改后重启Docker新镜像和新容器都会写到新路径。这个操作不会迁移已有数据如果你有存量容器需要先stop掉迁移/var/lib/docker下的数据再改配置。迁移前记得重新梳理数据卷路径避免容器启动时找不到数据。5. 从单容器到多容器Compose编排的用武之地很多时候我们会遇到这样的场景一个项目依赖MySQL、Redis、Nginx三个服务手敲三次docker run不仅费劲命令一长还容易写错。这时候Compose就派上用场了。用文件定义整套服务。先建一个目录mkdir -p /data/stack cd /data/stack创建docker-compose.ymlversion: 3.8 services: mysql: image: mysql:8.0 container_name: mysql8 restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: YourPassword123 TZ: Asia/Shanghai ports: - 3306:3306 volumes: - /data/mysql:/var/lib/mysql - /etc/localtime:/etc/localtime:ro redis: image: redis:7 container_name: redis7 restart: unless-stopped command: [redis-server, --requirepass, YourRedisPassword] ports: - 6379:6379 volumes: - /data/redis:/data nginx: image: nginx:1.24 container_name: nginx restart: unless-stopped ports: - 80:80 volumes: - /data/www:/usr/share/nginx/html:ro - /data/nginx/conf.d:/etc/nginx/conf.d:ro启动整套服务docker compose up -d查看状态docker compose ps停止服务docker compose downCompose对个人项目或者小团队来说最大的意义在于把环境配置代码化换一台机器把compose文件和挂载目录带过去一条命令就能拉起整套环境。不用再对着笔记敲一条条docker run也不会漏掉某个参数。使用Compose后改配置的操作也变得更安全。修改yml文件后执行docker compose up -dCompose会自动识别配置差异重建需要更新的容器不用你手动stop、rm、run一路操作。6. 几个容易被忽略的操作心得第一点docker exec进入容器后很多容器镜像默认不带vim、netstat这些常用工具。比如CentOS镜像里要装个网络工具yum install -y net-tools但如果你用的是精简版镜像比如Alpine包管理器是apk命令完全不同。用容器时先确认基础镜像是什么系统再决定用什么包管理器。这点看着小实际操作中经常卡壳。第二点容器内改配置直接改后容器一重启配置就丢了。容器是无状态的任何没有挂在数据卷里的文件修改容器重建后全部回到初始状态。所以修改容器内配置文件前先确认这个文件有没有挂载宿主机目录如果没有要么挂载出来改要么进入容器改完后docker commit保存为新镜像。后者不推荐但确实能救急。第三点docker inspect是排查问题最得力的命令。容器启动不了别只在外面猜看看容器的输出数据最直接docker logs 容器名容器是Running状态但业务访问异常先看端口映射docker port 容器名查看容器的完整配置docker inspect 容器名这些都是基本功但越基础的东西越容易被忽略。很多新手遇到问题第一反应是百度实际上一条docker logs就能告诉你答案。CentOS 7.9装Docker这套流程我前前后后在各种环境重复过不知道多少次从裸机到内网离线从单机到集群节点每次都能遇到新的小问题。但核心思路是固定的准备好yum源、装对包、配好加速器、数据卷挂在宿主机、日志限制从一开始就拉满。把这几条做到位剩下的就是在这个框架里自由发挥了。
返回列表