在中小型团队的实际开发场景中,我们常常面临这样的困境:Jenkins等传统方案对服务器资源要求高,GitLab Runner的维护成本又让人头疼。去年我们一个5人前端团队就遇到过这样的问题——每次代码提交后要等近10分钟才能看到构建结果,严重拖慢了迭代速度。
Docker化的轻量CI/CD方案恰好能解决这个痛点。通过将构建环境容器化,我们不仅实现了秒级构建任务启动,还能保持开发、测试、生产环境的高度一致。下面就以CentOS7环境为例,分享我们团队经过多次踩坑后总结出的最佳实践。
首先确保使用CentOS 7.6及以上版本(内核需≥3.10):
bash复制# 查看系统版本
cat /etc/redhat-release
# 查看内核版本
uname -r
建议先执行基础优化:
bash复制# 关闭SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 停止防火墙
systemctl stop firewalld
systemctl disable firewalld
# 备份原有yum源
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# 获取阿里云源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 清理并重建缓存
yum clean all
yum makecache
官方推荐安装方式:
bash复制# 安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加Docker官方源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 查看可用版本(建议选择稳定版)
yum list docker-ce --showduplicates | sort -r
# 安装指定版本(这里选择18.06.3)
yum install -y docker-ce-18.06.3.ce-3.el7
# 启动并设置开机自启
systemctl start docker
systemctl enable docker
重要提示:生产环境强烈建议锁定Docker版本,避免自动升级导致兼容性问题。我们曾因自动升级到19.x版本导致构建任务全部失败。
验证安装:
bash复制docker version
docker run hello-world
CentOS7默认使用devicemapper,但更推荐overlay2:
bash复制# 创建或修改daemon.json
cat > /etc/docker/daemon.json <<EOF
{
"storage-driver": "overlay2",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
# 重启生效
systemctl restart docker
国内用户必须配置镜像加速:
bash复制# 修改daemon.json追加以下内容
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
避免单个容器占用全部资源:
bash复制# 修改/etc/docker/daemon.json
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65535,
"Soft": 65535
}
},
"oom-score-adjust": -500
}
bash复制# 获取最新稳定版(当前为1.29.2)
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 赋予执行权限
chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
以MySQL为例展示服务部署:
yaml复制# docker-compose.yml示例
version: '3'
services:
mysql:
image: mysql:5.7
container_name: ci-mysql
environment:
MYSQL_ROOT_PASSWORD: your_secure_password
MYSQL_DATABASE: cicd
volumes:
- /data/mysql:/var/lib/mysql
ports:
- "3306:3306"
restart: always
启动命令:
bash复制docker-compose up -d
现象:端口绑定失败
解决方案:
bash复制# 查看已占用端口
netstat -tulnp | grep 3306
# 或者使用docker命令
docker ps --format "table {{.Names}}\t{{.Ports}}"
定期清理无用镜像:
bash复制# 删除所有悬空镜像
docker image prune -f
# 删除所有未被使用的镜像
docker image prune -a -f
在Dockerfile中加入:
dockerfile复制RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
禁止root直接运行容器:
bash复制useradd -m dockeruser
usermod -aG docker dockeruser
启用内容信任:
bash复制export DOCKER_CONTENT_TRUST=1
定期扫描镜像漏洞:
bash复制docker scan <image_name>
安装cAdvisor监控:
bash复制docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
访问http://服务器IP:8080即可查看资源使用情况。
在我们团队的实际使用中,有几点特别值得注意:
数据持久化:所有重要数据必须通过volume挂载,我们曾因容器重建导致测试数据全部丢失
资源限制:单个构建任务建议配置CPU限制(--cpus=2),避免影响其他服务
日志收集:建议统一输出到ELK栈,我们使用Filebeat+Docker日志驱动实现
镜像分层:基础镜像建议不超过3层,构建时合并RUN指令减少层数
缓存利用:合理使用docker build --cache-from提升构建速度
这套方案在我们多个项目中稳定运行超过一年,平均构建时间从原来的8分钟缩短到40秒左右,资源占用仅为传统方案的1/3。对于中小团队来说,这种轻量级实现既能满足持续交付需求,又不会带来过重的维护负担。