Docker容器化运维踩坑记录

Docker容器化运维踩坑记录

去年我在生产环境部署Docker时踩了不少坑,这里记录一下遇到的问题和解决方法,希望能帮到有同样困扰的人。

Docker基础安装与配置

Docker安装环境准备

在使用Docker前,需要确保系统环境满足以下条件:

  • Linux内核版本 3.10 以上
  • 开启 cgroup 和 namespace 支持
  • SELinux 配置正确(推荐设置为 permissive 模式)

SELinux配置优化

Docker运行时常会遇到SELinux权限问题,以下是推荐的配置方案:

临时关闭SELinux:

1
setenforce 0

永久关闭SELinux(需重启生效):

1
2
vi /etc/selinux/config
# 将 SELINUX=enforcing 改为 SELINUX=disabled

推荐方案 - 设置为宽容模式:

1
2
vi /etc/selinux/config
# 将 SELINUX=disabled 改为 SELINUX=permissive

设置 permissive 模式可以在保持安全审计的同时,避免因权限问题导致容器启动失败。

Docker存储驱动配置

当出现 error creating overlay mount 错误时,通常是由于SELinux配置不一致导致的。除了统一SELinux配置外,还可以考虑使用其他存储驱动:

1
2
3
4
# 修改 /etc/docker/daemon.json
{
"storage-driver": "devicemapper"
}

Docker容器生命周期管理

批量启动容器

在实际运维中,经常需要批量管理容器。以下命令可以启动所有已停止的容器:

1
docker start $(docker ps -a | awk '{ print $1}' | tail -n +2)

命令解析:

  • docker ps -a:列出所有容器(包括停止的)
  • awk '{ print $1}':提取容器ID列
  • tail -n +2:跳过标题行

修改容器自启动参数

有时需要修改已创建容器的启动参数,可以通过以下方式实现:

1
2
3
4
5
6
7
8
9
10
11
12
# 停止Docker服务
systemctl stop docker

# 进入容器配置目录
cd /var/lib/docker/containers/[containerID]

# 修改配置文件
vi config.v2.json
vi hostconfig.json

# 重启Docker服务
systemctl start docker

注意事项:

  • 修改前务必备份原始配置文件
  • 确保JSON格式正确,否则Docker无法启动
  • 建议先在测试环境验证

容器与宿主机文件传输

Docker提供了便捷的文件拷贝命令:

从容器复制到宿主机:

1
docker cp testtomcat:/usr/local/test.js /opt

从宿主机复制到容器:

1
docker cp /opt/test.js testtomcat:/usr/local/

Redis容器部署与故障排查

Redis容器启动失败处理

常见错误:

1
chown: changing ownership of '.': Permission denied

解决方案一:赋予特权

1
docker run --privileged=true redis

解决方案二:关闭SELinux
按照前文SELinux配置方法操作。

解决方案三:修改挂载目录权限

1
chown -R 999:999 /path/to/redis/data

Windows环境Redis启动

在Windows环境下启动Redis时,可能遇到监听错误:

1
creating server tcp listening socket *:6379 listen unknown error

原因分析: 默认配置文件读取失败

解决方法:

1
redis-server.exe ./redis.windows.conf

明确指定配置文件路径可以解决大部分Windows环境下的Redis启动问题。

四、MySQL容器部署实战

MySQL容器启动报错处理

错误信息:

1
initialize specified but the data directory has files in it

原因分析: 通过 -v 挂载的目录已存在文件

解决方案:

  • 选择空目录作为挂载点
  • 或使用不存在的目录(Docker会自动创建)
1
2
# 正确示例
docker run -v /empty/mysql/data:/var/lib/mysql mysql:8.0

MySQL认证方式问题

MySQL 8.0默认使用 caching_sha2_password 认证插件,可能导致旧客户端连接失败。

解决方法: 切换为传统认证方式

1
2
3
4
5
6
7
8
9
10
11
12
-- 登录MySQL
mysql -uroot -p

-- 选择mysql数据库
USE mysql;

-- 修改root用户认证方式
ALTER USER root@localhost IDENTIFIED WITH mysql_native_password BY 'your_password';
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';

-- 刷新权限
FLUSH PRIVILEGES;

Socket连接问题

错误信息:

1
Can't connect to local MySQL server through socket /tmp/mysql.sock

原因分析: my.cnf配置文件中缺少[client]段的socket配置

解决方案:

1
2
3
4
5
[mysqld]
socket=/usr/local/mysql/data/mysql.sock

[client]
socket=/usr/local/mysql/data/mysql.sock

临时解决方法:

1
mysql -uroot -h127.0.0.1 -p

Docker生产环境最佳实践

目录挂载规范

场景 推荐做法 说明
数据持久化 使用命名卷 docker volume create
配置挂载 使用bind mount 挂载到特定配置文件
日志收集 使用日志驱动 --log-driver

容器安全配置

1
2
3
4
5
6
7
8
# 限制容器资源
docker run --memory=512m --cpus=1.0 redis

# 以非root用户运行
docker run --user 999:999 mysql

# 禁用容器特权
docker run --security-opt=no-new-privileges:true nginx

监控与日志

查看容器资源使用:

1
docker stats

查看容器日志:

1
docker logs -f container_name

常见问题速查表

问题 可能原因 解决方案
容器启动失败 SELinux限制 设置为permissive模式
权限被拒绝 挂载目录权限错误 检查目录权限和所有权
端口冲突 宿主机端口被占用 更换映射端口
存储空间不足 镜像和容器数据过多 清理未使用的镜像和卷

总结

Docker运维的核心在于理解容器与宿主机的关系,多实践、多记录,遇到问题善用日志和文档。以上就是我在Docker运维中遇到的一些典型问题和解决方案,希望对大家有帮助。


参考资源: