docker compose网络
基本概念
默认情况下,Compose会为我们的应用创建一个网络,服务的每个容器都会加入该网络中。这样,容器就可被该网络中的其他容器访问,不仅如此,该容器还能以服务名称作为hostname被其他容器访问。
默认情况下,应用程序的网络名称基于Compose的工程名称,而项目名称基于docker-compose.yml所在目录的名称。如需修改工程名称,可使用--project-name标识或COMPOSE_PORJECT_NAME环境变量。
举个例子,假如一个应用程序在名为myapp的目录中,并且docker-compose.yml如下所示:
version: '2' services: web: build: . ports: - "8000:8000" db: image: postgres
当我们运行docker-compose up时,将会执行以下几步:
- 创建一个名为myapp_default的网络;
- 使用web服务的配置创建容器,它以“web”这个名称加入网络myapp_default;
- 使用db服务的配置创建容器,它以“db”这个名称加入网络myapp_default。
容器间可使用服务名称(web或db)作为hostname相互访问。例如,web这个服务可使用postgres://db:5432
访问db容器。
更新容器
当服务的配置发生更改时,可使用docker-compose up命令更新配置。
此时,Compose会删除旧容器并创建新容器。新容器会以不同的IP地址加入网络,名称保持不变。任何指向旧容器的连接都会被关闭,容器会重新找到新容器并连接上去。
links
前文讲过,默认情况下,服务之间可使用服务名称相互访问。links允许我们定义一个别名,从而使用该别名访问其他服务。举个例子:
version: '2' services: web: build: . links: - "db:database" db: image: postgres
这样web服务就可使用db或database作为hostname访问db服务了。
指定自定义网络
一些场景下,默认的网络配置满足不了我们的需求,此时我们可使用networks命令自定义网络。networks命令允许我们创建更加复杂的网络拓扑并指定自定义网络驱动和选项。不仅如此,我们还可使用networks将服务连接到不是由Compose管理的、外部创建的网络。
如下,我们在其中定义了两个自定义网络。
version: '2' services: proxy: build: ./proxy networks: - front app: build: ./app networks: - front - back db: image: postgres networks: - back networks: front: driver: custom-driver-1 back: driver: custom-driver-2 driver_opts: foo: "1" bar: "2"
其中,proxy服务与db服务隔离,两者分别使用自己的网络;app服务可与两者通信。
由本例不难发现,使用networks命令,即可方便实现服务间的网络隔离与连接。
配置默认网络
除自定义网络外,我们也可为默认网络自定义配置。
version: '2' services: web: build: . ports: - "8000:8000" db: image: postgres networks: default: driver: custom-driver-1
这样,就可为该应用指定自定义的网络驱动。
使用已存在的网络
一些场景下,我们并不需要创建新的网络,而只需加入已存在的网络,此时可使用external选项。示例:
networks: default: external: name: my-pre-existing-network
Docker Compose 链接外部容器的几种方式
在Docker中,容器之间的链接是一种很常见的操作:它提供了访问其中的某个容器的网络服务而不需要将所需的端口暴露给Docker Host主机的功能。Docker Compose中对该特性的支持同样是很方便的。然而,如果需要链接的容器没有定义在同一个docker-compose.yml
中的时候,这个时候就稍微麻烦复杂了点。
在不使用Docker Compose的时候,将两个容器链接起来使用—link
参数,相对来说比较简单,以nginx
镜像为例子:
docker run --rm --name test1 -d nginx docker run --rm --name test2 --link test1 -d nginx
这样,test2
与test1
便建立了链接,就可以在test2
中使用访问test1
中的服务了。
如果使用Docker Compose,那么这个事情就更简单了,还是以上面的nginx
镜像为例子,编辑docker-compose.yml
文件为:
version: "3" services: test2: image: nginx depends_on: - test1 links: - test1 test1: image: nginx
最终效果与使用普通的Docker命令docker run xxxx
建立的链接并无区别。这只是一种最为理想的情况。
- 如果容器没有定义在同一个
docker-compose.yml
文件中,应该如何链接它们呢? - 又如果定义在
docker-compose.yml
文件中的容器需要与docker run xxx
启动的容器链接,需要如何处理?
针对这两种典型的情况,下面给出我个人测试可行的办法:
方式一:让需要链接的容器同属一个外部网络
我们还是使用nginx镜像来模拟这样的一个情景:假设我们需要将两个使用Docker Compose管理的nignx容器(test1
和test2
)链接起来,使得test2
能够访问test1
中提供的服务,这里我们以能ping通为准。
首先,我们定义容器test1
的docker-compose.yml
文件内容为:
version: "3" services: test2: image: nginx container_name: test1 networks: - default - app_net networks: app_net: external: true
容器test2
内容与test1
基本一样,只是多了一个external_links
,需要特别说明的是:最近发布的Docker版本已经不需要使用external_links来链接容器,容器的DNS服务可以正确的作出判断,因此如果你你需要兼容较老版本的Docker的话,那么容器test2
的docker-compose.yml
文件内容为:
version: "3" services: test2: image: nginx networks: - default - app_net external_links: - test1 container_name: test2 networks: app_net: external: true
否则的话,test2
的docker-compose.yml
和test1
的定义完全一致,不需要额外多指定一个external_links
。相关的问题请参见stackoverflow上的相关问题:docker-compose + external container
正如你看到的那样,这里两个容器的定义里都使用了同一个外部网络app_net
,因此,我们需要在启动这两个容器之前通过以下命令再创建外部网络:
docker network create app_net
之后,通过docker-compose up -d
命令启动这两个容器,然后执行docker exec -it test2 ping test1
,你将会看到如下的输出:
docker exec -it test2 ping test1 PING test1 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.091 ms 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.146 ms 64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.150 ms 64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.145 ms 64 bytes from 172.18.0.2: icmp_seq=4 ttl=64 time=0.126 ms 64 bytes from 172.18.0.2: icmp_seq=5 ttl=64 time=0.147 ms
证明这两个容器是成功链接了,反过来在test1
中pingtest2
也是能够正常ping通的。
如果我们通过docker run --rm --name test3 -d nginx
这种方式来先启动了一个容器(test3
)并且没有指定它所属的外部网络,而需要将其与test1
或者test2
链接的话,这个时候手动链接外部网络即可:
docker network connect app_net test3
这样,三个容器都可以相互访问了。
方式二:更改需要链接的容器的网络模式
通过更改你想要相互链接的容器的网络模式为bridge
,并指定需要链接的外部容器(external_links
)即可。与同属外部网络的容器可以相互访问的链接方式一不同,这种方式的访问是单向的。
还是以nginx容器镜像为例子,如果容器实例nginx1
需要访问容器实例nginx2
,那么nginx2
的doker-compose.yml
定义为:
version: "3" services: nginx2: image: nginx container_name: nginx2 network_mode: bridge
与其对应的,nginx1
的docker-compose.yml
定义为:
version: "3" services: nginx1: image: nginx external_links: - nginx2 container_name: nginx1 network_mode: bridge
需要特别说明的是,这里的
external_links
是不能省略的,而且nginx1
的启动必须要在nginx2
之后,否则可能会报找不到容器nginx2
的错误。
接着我们使用ping来测试下连通性:
$ docker exec -it nginx1 ping nginx2 PING nginx2 (172.17.0.4): 56 data bytes 64 bytes from 172.17.0.4: icmp_seq=0 ttl=64 time=0.141 ms 64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.139 ms 64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.145 ms $ docker exec -it nginx2 ping nginx1 ping: unknown host
以上也能充分证明这种方式是属于单向联通的。
在实际应用中根据自己的需要灵活的选择这两种链接方式,如果想偷懒的话,大可选择第二种。不过我更推荐第一种,不难看出无论是联通性还是灵活性,较为更改网络模式的第二种都更为友好。
附docker-compose.yml文件详解
Compose和Docker兼容性: Compose 文件格式有3个版本,分别为1, 2.x 和 3.x 目前主流的为 3.x 其支持 docker 1.13.0 及其以上的版本 常用参数: version services build context dockerfile args cache_from labels shm_size command configs cgroup_parent container_name credential_spec deploy endpoint_mode vip dnsrr labels mode global replicated placement replicas resources limits cpus: "0.5" memory: 50M reservations cpus: "0.2" memory: 20M restart_policy condition none on-failure any delay max_attempts window update_config parallelism delay failure_action continue rollback pause monitor max_failure_ratio order stop-first start-first rollback_config parallelism delay failure_action continue pause monitor max_failure_ratio order stop-first start-first 注意: 支持 docker-compose up 和 docker-compose run 但不支持 docker stack deploy 的子选项 security_opt container_name devices tmpfs stop_signal links cgroup_parent network_mode external_links restart build userns_mode sysctls devices depends_on 示例: docker-compose up 以依赖顺序启动服务,下面例子中 redis 和 db 服务在 web 启动前启动 默认情况下使用 docker-compose up web 这样的方式启动 web 服务时,也会启动 redis 和 db 两个服务,因为在配置文件中定义了依赖关系 version: '3' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres dns dns_search tmpfs entrypoint env_file 文件格式: RACK_ENV=development environment expose external_links extra_hosts healthcheck test NONE CMD CMD-SHELL interval: 1m30s timeout: 10s retries: 3 start_period: 40s disable: true image init isolation labels links logging driver options max-size max-file network_mode networks aliases ipv4_address ipv6_address 示例: version: '3.7' services: test: image: nginx:1.14-alpine container_name: mynginx command: ifconfig networks: app_net: ipv4_address: 172.16.238.10 networks: app_net: driver: bridge ipam: driver: default config: - subnet: 172.16.238.0/24 pid: 'host' ports SHORT 语法格式示例: - "3000" - "3000-3005" - "8000:8000" - "9090-9091:8080-8081" - "127.0.0.1:8001:8001" - "127.0.0.1:5000-5010:5000-5010" - "6060:6060/udp" LONG 语法格式示例:(v3.2 新增的语法格式) ports: - target: 80 published: 8080 protocol: tcp mode: host secrets security_opt stop_grace_period stop_signal sysctls ulimits userns_mode volumes SHORT 语法格式示例: volumes: - /var/lib/mysql - /opt/data:/var/lib/mysql - ./cache:/tmp/cache - ~/configs:/etc/configs/:ro - datavolume:/var/lib/mysql LONG 语法格式示例:(v3.2 新增的语法格式) version: "3.2" services: web: image: nginx:alpine ports: - "80:80" volumes: - type: volume source: mydata target: /data volume: nocopy: true - type: bind source: ./static target: /opt/app/static read_only: true volumes: mydata: restart no always on-failure 其他选项: domainname, hostname, ipc, mac_address, privileged, read_only, shm_size, stdin_open, tty, user, working_dir 上面这些选项都只接受单个值和 docker run 的对应参数类似 对于值为时间的可接受的值: 2.5s 10s 1m30s 2h32m 5h34m56s 时间单位: us, ms, s, m, h 对于值为大小的可接受的值: 2b 1024kb 2048k 300m 1gb 单位: b, k, m, g 或者 kb, mb, gb networks driver bridge overlay host none driver_opts attachable ipam driver config subnet external name 文件格式示例: version: "3" services: redis: image: redis:alpine ports: - "6379" networks: - frontend deploy: replicas: 2 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure db: image: postgres:9.4 volumes: - db-data:/var/lib/postgresql/data networks: - backend deploy: placement: constraints: [node.role == manager]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现