Docker容器间通信有多种方式:
# 创建自定义网络
docker network create mynet
# 启动MySQL容器
docker run -d \
--name mysql-server \
--network mynet \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
# 启动应用容器,通过容器名访问MySQL
docker run -d \
--name webapp \
--network mynet \
-e DB_HOST=mysql-server \
-e DB_PORT=3306 \
myapp:latest
# 在webapp容器中测试连接
docker exec webapp ping mysql-server
docker exec webapp curl http://mysql-server:3306
# 创建网络
docker network create app-tier
# 1. 数据库层
docker run -d \
--name postgres-db \
--network app-tier \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=myapp \
postgres:14
# 2. 后端API层
docker run -d \
--name api-server \
--network app-tier \
-e DATABASE_URL=postgresql://postgres:secret@postgres-db:5432/myapp \
-e REDIS_URL=redis://redis-cache:6379 \
myapi:latest
# 3. Redis缓存层
docker run -d \
--name redis-cache \
--network app-tier \
redis:alpine
# 4. 前端层
docker run -d \
--name frontend \
--network app-tier \
-p 80:80 \
-e API_URL=http://api-server:8000 \
myfrontend:latest
# 创建网络
docker network create lb-net
# 启动多个后端服务,使用相同别名
docker run -d --name api1 --network lb-net --network-alias api nginx
docker run -d --name api2 --network lb-net --network-alias api nginx
docker run -d --name api3 --network lb-net --network-alias api nginx
# 启动客户端容器
docker run -it --rm --network lb-net alpine sh
# 在客户端容器中测试(会轮询到不同的后端)
# nslookup api
# wget -qO- http://api
# 创建前端和后端网络
docker network create frontend
docker network create backend
# 数据库只在后端网络
docker run -d --name db --network backend mysql
# API服务器连接两个网络
docker run -d --name api --network backend myapi
docker network connect frontend api
# Web服务器只在前端网络
docker run -d --name web --network frontend -p 80:80 nginx
# 现在:web可以访问api,api可以访问db,但web不能直接访问db
version: '3.8'
services:
# 前端
frontend:
image: nginx:alpine
ports:
- "80:80"
networks:
- frontend
depends_on:
- backend
# 后端API
backend:
image: myapi:latest
environment:
- DB_HOST=database
- CACHE_HOST=cache
networks:
- frontend
- backend
depends_on:
- database
- cache
# 数据库
database:
image: postgres:14
environment:
- POSTGRES_PASSWORD=secret
networks:
- backend
volumes:
- db-data:/var/lib/postgresql/data
# 缓存
cache:
image: redis:alpine
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络,不能访问外网
volumes:
db-data:
# Docker内置DNS服务器
# 容器启动时自动注册到DNS
# 其他容器可以通过名称解析
# 查看容器DNS配置
docker exec mycontainer cat /etc/resolv.conf
# 测试DNS解析
docker exec mycontainer nslookup other-container
docker exec mycontainer dig other-container
# 在管理节点初始化Swarm
docker swarm init --advertise-addr 192.168.1.100
# 创建overlay网络
docker network create \
--driver overlay \
--attachable \
my-overlay-net
# 在任意节点运行容器
docker run -d --name app1 --network my-overlay-net myapp
docker run -d --name app2 --network my-overlay-net myapp
# app1和app2可以跨主机通信
# 容器访问主机服务
# Linux: 使用host.docker.internal(需要添加extra_hosts)
docker run --add-host=host.docker.internal:host-gateway myapp
# macOS/Windows: 直接使用host.docker.internal
docker run myapp
# 在容器中访问:curl http://host.docker.internal:8080
# 主机访问容器
# 方法1: 端口映射
docker run -p 8080:80 nginx
# 方法2: 使用容器IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mycontainer
# 创建隔离的内部网络
docker network create --internal secure-net
# 内部网络的容器无法访问外网
docker run -d --name secure-app --network secure-net myapp
# 创建网络时指定子网
docker network create \
--subnet=172.18.0.0/16 \
--gateway=172.18.0.1 \
custom-net
# 测试容器间连通性
docker exec container1 ping container2
# 查看容器网络配置
docker exec container1 ip addr
docker exec container1 ip route
# 使用netshoot工具容器调试
docker run -it --rm --network container:myapp nicolaka/netshoot
# 在netshoot中可以使用:
# - ping, curl, wget
# - tcpdump, netstat, ss
# - nslookup, dig
# - traceroute, mtr