docker网络管理详解 一
一· 生产故障:docker 同一宿主机不能通信
1. 检查容器网络配置
1.1 查看容器的网络信息
使用 `docker inspect` 命令查看容器的网络配置,确保它们连接到了正确的网络。
docker inspect -f '{{json .NetworkSettings.Networks }}' container1
docker inspect -f '{{json .NetworkSettings.Networks }}' container2
确保两个容器连接到了同一个网络,例如 `bridge` 网络或自定义网络。
2. 检查容器的IP地址
获取容器的IP地址,确保它们在同一个子网内。
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container2
3. 检查网络连通性
3.1 使用 `ping` 测试
从一个容器向另一个容器发送 `ping` 请求,检查网络连通性。
docker exec -it container1 ping -c 4 <container2_ip>
如果 `ping` 不通,说明网络配置可能有问题。
4. 检查防火墙规则
4.1 检查 `iptables` 规则
查看 `iptables` 规则,确保没有阻止容器之间的通信。
sudo iptables -L -n -v
特别是检查 `DOCKER` 和 `DOCKER-USER` 链,确保没有 `DROP` 或 `REJECT` 规则。
4.2 检查 `firewalld` 规则
如果你使用 `firewalld`,检查其规则。
sudo firewall-cmd --list-all
5. 检查 Docker 网络设置
5.1 检查 Docker 网络
查看 Docker 网络的详细信息,确保网络配置正确。
docker network ls
docker network inspect <network_name>
5.2 检查 `--icc` 设置
确保 Docker 守护进程没有禁用容器间通信(ICC)。检查 `/etc/docker/daemon.json` 文件,确保 `icc` 设置为 `true`。
json
{
"icc": true
}
6. 检查容器端口映射
确保容器的端口映射正确,特别是如果你使用了 `--publish` 或 `-p` 选项。
docker ps -a
7. 检查容器内的网络配置
进入容器内部,检查其网络配置。
docker exec -it container1 /bin/sh
ip addr show
ip route show
8. 检查 DNS 解析
如果容器使用域名而不是IP地址进行通信,确保 DNS 解析正常。
docker exec -it container1 nslookup <container2_hostname>
9. 检查容器日志
查看容器的日志,寻找可能的网络相关错误。
docker logs container1
docker logs container2
10. 重启 Docker 服务
如果上述步骤都没有解决问题,尝试重启 Docker 服务。
sudo systemctl restart docker
11. 重新创建网络和容器
如果问题依然存在,可以尝试删除现有的网络和容器,然后重新创建。
docker network rm <network_name>
docker network create <network_name>
docker rm -f container1
docker rm -f container2
docker run -d --name container1 --network <network_name> my_image
docker run -d --name container2 --network <network_name> my_image
二. 容器名称互联
假设我们在西安的环境中部署了一个简单的微服务应用,包含以下几个部分:
1. Web服务器:运行Nginx,负责处理HTTP请求。
2. 应用服务器:运行Node.js应用,处理业务逻辑。
3. 数据库:使用MySQL,存储应用数据。
步骤
# 1. 创建自定义网络
首先,创建一个自定义的桥接网络,以便容器之间可以相互通信。
docker network create my_network
# 2. 创建数据卷
创建一个数据卷,用于持久化MySQL的数据。
docker volume create mysql_data
# 3. 启动MySQL容器
启动MySQL容器,并将其连接到自定义网络。为容器指定一个别名,以便其他容器可以通过别名访问它。同时,挂载数据卷以实现数据持久化。
docker run -d --name mysql_db --network my_network --alias db \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
mysql:5.7
# 4. 启动应用服务器容器
启动Node.js应用服务器容器,并将其连接到自定义网络。为容器指定一个别名,以便其他容器可以通过别名访问它。
docker run -d --name node_app --network my_network --alias app \
-e DB_HOST=db \
-e DB_USER=myuser \
-e DB_PASSWORD=mypassword \
-e DB_NAME=mydb \
my_node_app_image
# 5. 启动Web服务器容器
启动Nginx容器,并将其连接到自定义网络。为容器指定一个别名,以便其他容器可以通过别名访问它。
docker run -d --name nginx_server --network my_network --alias web \
-p 80:80 \
-v /path/to/nginx/conf.d:/etc/nginx/conf.d \
-v /path/to/static/files:/usr/share/nginx/html \
nginx
配置Nginx
在Nginx配置文件中,配置反向代理,将请求转发到Node.js应用服务器。
# Nginx配置文件 (`/path/to/nginx/conf.d/default.conf`)
nginx
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://app:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static/ {
alias /usr/share/nginx/html/;
}
}
验证
1. 验证MySQL容器:
- 确保MySQL容器正常运行并监听端口3306。
docker logs mysql_db
2. 验证Node.js应用服务器容器:
- 确保Node.js应用服务器容器正常运行并连接到MySQL数据库。
docker logs node_app
3. 验证Web服务器容器:
- 访问Web服务器的主页,确保Nginx能够正确代理请求到Node.js应用服务器。
curl http://localhost
持久化存储验证
1. 停止并删除MySQL容器
docker stop mysql_db
docker rm mysql_db
2. 重新启动MySQL容器
docker run -d --name mysql_db --network my_network --alias db \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
mysql:5.7
3. 验证数据
连接到MySQL容器,确保数据仍然存在。
docker exec -it mysql_db mysql -u myuser -pmypassword mydb
备份和恢复
# 备份数据
1. 备份数据卷
docker run --rm --volumes-from mysql_db -v $(pwd):/backup ubuntu tar czvf /backup/mysql_backup.tar.gz /var/lib/mysql
# 恢复数据
1. 恢复数据卷
docker run --rm --volumes-from mysql_db -v $(pwd):/backup ubuntu -c "cd / && tar xzvf /backup/mysql_backup.tar.gz"
补充还有 通过link方式,一般生产都用别名方式,就略了
--link sever1:sever2
这也是别名实现的另一种方式