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-composeup时,将会执行以下几步:
- 创建一个名为myapp_default的网络;
- 使用web服务的配置创建容器,它以“web”这个名称加入网络myapp_default;
- 使用db服务的配置创建容器,它以“db”这个名称加入网络myapp_default。
容器间可使用服务名称(web或db)作为hostname相互访问。例如,web这个服务可使用postgres://db:5432访问db容器。
更新容器
当服务的配置发生更改时,可使用docker-composeup命令更新配置。
此时,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: #Useacustomdriver driver:custom-driver-1 back: #Useacustomdriverwhichtakesspecialoptions 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: #Useacustomdriver driver:custom-driver-1
这样,就可为该应用指定自定义的网络驱动。
使用已存在的网络
一些场景下,我们并不需要创建新的网络,而只需加入已存在的网络,此时可使用external选项。示例:
networks: default: external: name:my-pre-existing-network
DockerCompose链接外部容器的几种方式
在Docker中,容器之间的链接是一种很常见的操作:它提供了访问其中的某个容器的网络服务而不需要将所需的端口暴露给DockerHost主机的功能。DockerCompose中对该特性的支持同样是很方便的。然而,如果需要链接的容器没有定义在同一个docker-compose.yml中的时候,这个时候就稍微麻烦复杂了点。
在不使用DockerCompose的时候,将两个容器链接起来使用—link参数,相对来说比较简单,以nginx镜像为例子:
dockerrun--rm--nametest1-dnginx#开启一个实例test1 dockerrun--rm--nametest2--linktest1-dnginx#开启一个实例test2并与test1建立链接
这样,test2与test1便建立了链接,就可以在test2中使用访问test1中的服务了。如果使用DockerCompose,那么这个事情就更简单了,还是以上面的nginx镜像为例子,编辑docker-compose.yml文件为:
version:"3" services: test2: image:nginx depends_on: -test1 links: -test1 test1: image:nginx
最终效果与使用普通的Docker命令dockerrunxxxx建立的链接并无区别。这只是一种最为理想的情况。
如果容器没有定义在同一个docker-compose.yml文件中,应该如何链接它们呢?
又如果定义在docker-compose.yml文件中的容器需要与dockerrunxxx启动的容器链接,需要如何处理?
针对这两种典型的情况,下面给出我个人测试可行的办法:
方式一:让需要链接的容器同属一个外部网络
我们还是使用nginx镜像来模拟这样的一个情景:假设我们需要将两个使用DockerCompose管理的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+externalcontainer
正如你看到的那样,这里两个容器的定义里都使用了同一个外部网络app_net,因此,我们需要在启动这两个容器之前通过以下命令再创建外部网络:
dockernetworkcreateapp_net
之后,通过docker-composeup-d命令启动这两个容器,然后执行dockerexec-ittest2pingtest1,你将会看到如下的输出:
dockerexec-ittest2pingtest1 PINGtest1(172.18.0.2):56databytes 64bytesfrom172.18.0.2:icmp_seq=0ttl=64time=0.091ms 64bytesfrom172.18.0.2:icmp_seq=1ttl=64time=0.146ms 64bytesfrom172.18.0.2:icmp_seq=2ttl=64time=0.150ms 64bytesfrom172.18.0.2:icmp_seq=3ttl=64time=0.145ms 64bytesfrom172.18.0.2:icmp_seq=4ttl=64time=0.126ms 64bytesfrom172.18.0.2:icmp_seq=5ttl=64time=0.147ms
证明这两个容器是成功链接了,反过来在test1中pingtest2也是能够正常ping通的。
如果我们通过dockerrun--rm--nametest3-dnginx这种方式来先启动了一个容器(test3)并且没有指定它所属的外部网络,而需要将其与test1或者test2链接的话,这个时候手动链接外部网络即可:
dockernetworkconnectapp_nettest3
这样,三个容器都可以相互访问了。
方式二:更改需要链接的容器的网络模式
通过更改你想要相互链接的容器的网络模式为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来测试下连通性:
$dockerexec-itnginx1pingnginx2#nginx1tonginx2 PINGnginx2(172.17.0.4):56databytes 64bytesfrom172.17.0.4:icmp_seq=0ttl=64time=0.141ms 64bytesfrom172.17.0.4:icmp_seq=1ttl=64time=0.139ms 64bytesfrom172.17.0.4:icmp_seq=2ttl=64time=0.145ms $dockerexec-itnginx2pingnginx1#nginx2tonginx1 ping:unknownhost
以上也能充分证明这种方式是属于单向联通的。
在实际应用中根据自己的需要灵活的选择这两种链接方式,如果想偷懒的话,大可选择第二种。不过我更推荐第一种,不难看出无论是联通性还是灵活性,较为更改网络模式的第二种都更为友好。
附docker-compose.yml文件详解Compose和Docker兼容性:
Compose文件格式有3个版本,分别为1,2.x和3.x 目前主流的为3.x其支持docker1.13.0及其以上的版本 常用参数: version#指定compose文件的版本 services#定义所有的service信息,services下面的第一级别的key既是一个service的名称 build#指定包含构建上下文的路径,或作为一个对象,该对象具有context和指定的dockerfile文件以及args参数值 context#context:指定Dockerfile文件所在的路径 dockerfile#dockerfile:指定context指定的目录下面的Dockerfile的名称(默认为Dockerfile) args#args:Dockerfile在build过程中需要的参数(等同于dockercontainerbuild--build-arg的作用) cache_from#v3.2中新增的参数,指定缓存的镜像列表(等同于dockercontainerbuild--cache_from的作用) labels#v3.3中新增的参数,设置镜像的元数据(等同于dockercontainerbuild--labels的作用) shm_size#v3.5中新增的参数,设置容器/dev/shm分区的大小(等同于dockercontainerbuild--shm-size的作用) command#覆盖容器启动后默认执行的命令,支持shell格式和[]格式 configs#不知道怎么用 cgroup_parent#不知道怎么用 container_name#指定容器的名称(等同于dockerrun--name的作用) credential_spec#不知道怎么用 deploy#v3版本以上,指定与部署和运行服务相关的配置,deploy部分是dockerstack使用的,dockerstack依赖dockerswarm endpoint_mode#v3.3版本中新增的功能,指定服务暴露的方式 vip#Docker为该服务分配了一个虚拟IP(VIP),作为客户端的访问服务的地址 dnsrr#DNS轮询,Docker为该服务设置DNS条目,使得服务名称的DNS查询返回一个IP地址列表,客户端直接访问其中的一个地址 labels#指定服务的标签,这些标签仅在服务上设置 mode#指定deploy的模式 global#每个集群节点都只有一个容器 replicated#用户可以指定集群中容器的数量(默认) placement#不知道怎么用 replicas#deploy的mode为replicated时,指定容器副本的数量 resources#资源限制 limits#设置容器的资源限制 cpus:"0.5"#设置该容器最多只能使用50%的CPU memory:50M#设置该容器最多只能使用50M的内存空间 reservations#设置为容器预留的系统资源(随时可用) cpus:"0.2"#为该容器保留20%的CPU memory:20M#为该容器保留20M的内存空间 restart_policy#定义容器重启策略,用于代替restart参数 condition#定义容器重启策略(接受三个参数) none#不尝试重启 on-failure#只有当容器内部应用程序出现问题才会重启 any#无论如何都会尝试重启(默认) delay#尝试重启的间隔时间(默认为0s) max_attempts#尝试重启次数(默认一直尝试重启) window#检查重启是否成功之前的等待时间(即如果容器启动了,隔多少秒之后去检测容器是否正常,默认0s) update_config#用于配置滚动更新配置 parallelism#一次性更新的容器数量 delay#更新一组容器之间的间隔时间 failure_action#定义更新失败的策略 continue#继续更新 rollback#回滚更新 pause#暂停更新(默认) monitor#每次更新后的持续时间以监视更新是否失败(单位:ns|us|ms|s|m|h)(默认为0) max_failure_ratio#回滚期间容忍的失败率(默认值为0) order#v3.4版本中新增的参数,回滚期间的操作顺序 stop-first#旧任务在启动新任务之前停止(默认) start-first#首先启动新任务,并且正在运行的任务暂时重叠 rollback_config#v3.7版本中新增的参数,用于定义在update_config更新失败的回滚策略 parallelism#一次回滚的容器数,如果设置为0,则所有容器同时回滚 delay#每个组回滚之间的时间间隔(默认为0) failure_action#定义回滚失败的策略 continue#继续回滚 pause#暂停回滚 monitor#每次回滚任务后的持续时间以监视失败(单位:ns|us|ms|s|m|h)(默认为0) max_failure_ratio#回滚期间容忍的失败率(默认值0) order#回滚期间的操作顺序 stop-first#旧任务在启动新任务之前停止(默认) start-first#首先启动新任务,并且正在运行的任务暂时重叠 注意: 支持docker-composeup和docker-composerun但不支持dockerstackdeploy的子选项 security_optcontainer_namedevicestmpfsstop_signallinkscgroup_parent network_modeexternal_linksrestartbuilduserns_modesysctls devices#指定设备映射列表(等同于dockerrun--device的作用) depends_on#定义容器启动顺序(此选项解决了容器之间的依赖关系,此选项在v3版本中使用swarm部署时将忽略该选项) 示例: docker-composeup以依赖顺序启动服务,下面例子中redis和db服务在web启动前启动 默认情况下使用docker-composeupweb这样的方式启动web服务时,也会启动redis和db两个服务,因为在配置文件中定义了依赖关系 version:'3' services: web: build:. depends_on: -db -redis redis: image:redis db: image:postgres dns#设置DNS地址(等同于dockerrun--dns的作用) dns_search#设置DNS搜索域(等同于dockerrun--dns-search的作用) tmpfs#v2版本以上,挂载目录到容器中,作为容器的临时文件系统(等同于dockerrun--tmpfs的作用,在使用swarm部署时将忽略该选项) entrypoint#覆盖容器的默认entrypoint指令(等同于dockerrun--entrypoint的作用) env_file#从指定文件中读取变量设置为容器中的环境变量,可以是单个值或者一个文件列表,如果多个文件中的变量重名则后面的变量覆盖前面的变量,environment的值覆盖env_file的值 文件格式: RACK_ENV=development environment#设置环境变量,environment的值可以覆盖env_file的值(等同于dockerrun--env的作用) expose#暴露端口,但是不能和宿主机建立映射关系,类似于Dockerfile的EXPOSE指令 external_links#连接不在docker-compose.yml中定义的容器或者不在compose管理的容器(dockerrun启动的容器,在v3版本中使用swarm部署时将忽略该选项) extra_hosts#添加host记录到容器中的/etc/hosts中(等同于dockerrun--add-host的作用) healthcheck#v2.1以上版本,定义容器健康状态检查,类似于Dockerfile的HEALTHCHECK指令 test#检查容器检查状态的命令,该选项必须是一个字符串或者列表,第一项必须是NONE,CMD或CMD-SHELL,如果其是一个字符串则相当于CMD-SHELL加该字符串 NONE#禁用容器的健康状态检测 CMD#test:["CMD","curl","-f","http://localhost"] CMD-SHELL#test:["CMD-SHELL","curl-fhttp://localhost||exit1"]或者test:curl-fhttps://localhost||exit1 interval:1m30s#每次检查之间的间隔时间 timeout:10s#运行命令的超时时间 retries:3#重试次数 start_period:40s#v3.4以上新增的选项,定义容器启动时间间隔 disable:true#true或false,表示是否禁用健康状态检测和test:NONE相同 image#指定docker镜像,可以是远程仓库镜像、本地镜像 init#v3.7中新增的参数,true或false表示是否在容器中运行一个init,它接收信号并传递给进程 isolation#隔离容器技术,在Linux中仅支持default值 labels#使用Docker标签将元数据添加到容器,与Dockerfile中的LABELS类似 links#链接到其它服务中的容器,该选项是docker历史遗留的选项,目前已被用户自定义网络名称空间取代,最终有可能被废弃(在使用swarm部署时将忽略该选项) logging#设置容器日志服务 driver#指定日志记录驱动程序,默认json-file(等同于dockerrun--log-driver的作用) options#指定日志的相关参数(等同于dockerrun--log-opt的作用) max-size#设置单个日志文件的大小,当到达这个值后会进行日志滚动操作 max-file#日志文件保留的数量 network_mode#指定网络模式(等同于dockerrun--net的作用,在使用swarm部署时将忽略该选项) networks#将容器加入指定网络(等同于dockernetworkconnect的作用),networks可以位于compose文件顶级键和services键的二级键 aliases#同一网络上的容器可以使用服务名称或别名连接到其中一个服务的容器 ipv4_address#IPV4格式 ipv6_address#IPV6格式 示例: version:'3.7' services: test: image:nginx:1.14-alpine container_name:mynginx command:ifconfig networks: app_net:#调用下面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'#共享宿主机的进程空间(PID) ports#建立宿主机和容器之间的端口映射关系,ports支持两种语法格式 SHORT语法格式示例: -"3000"#暴露容器的3000端口,宿主机的端口由docker随机映射一个没有被占用的端口 -"3000-3005"#暴露容器的3000到3005端口,宿主机的端口由docker随机映射没有被占用的端口 -"8000:8000"#容器的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#host在每个节点上发布主机端口,ingress对于群模式端口进行负载均衡 secrets#不知道怎么用 security_opt#为每个容器覆盖默认的标签(在使用swarm部署时将忽略该选项) stop_grace_period#指定在发送了SIGTERM信号之后,容器等待多少秒之后退出(默认10s) stop_signal#指定停止容器发送的信号(默认为SIGTERM相当于killPID;SIGKILL相当于kill-9PID;在使用swarm部署时将忽略该选项) sysctls#设置容器中的内核参数(在使用swarm部署时将忽略该选项) ulimits#设置容器的limit userns_mode#如果Docker守护程序配置了用户名称空间,则禁用此服务的用户名称空间(在使用swarm部署时将忽略该选项) volumes#定义容器和宿主机的卷映射关系,其和networks一样可以位于services键的二级键和compose顶级键,如果需要跨服务间使用则在顶级键定义,在services中引用 SHORT语法格式示例: volumes: -/var/lib/mysql#映射容器内的/var/lib/mysql到宿主机的一个随机目录中 -/opt/data:/var/lib/mysql#映射容器内的/var/lib/mysql到宿主机的/opt/data -./cache:/tmp/cache#映射容器内的/var/lib/mysql到宿主机compose文件所在的位置 -~/configs:/etc/configs/:ro#映射容器宿主机的目录到容器中去,权限只读 -datavolume:/var/lib/mysql#datavolume为volumes顶级键定义的目录,在此处直接调用 LONG语法格式示例:(v3.2新增的语法格式) version:"3.2" services: web: image:nginx:alpine ports: -"80:80" volumes: -type:volume#mount的类型,必须是bind、volume或tmpfs source:mydata#宿主机目录 target:/data#容器目录 volume:#配置额外的选项,其key必须和type的值相同 nocopy:true#volume额外的选项,在创建卷时禁用从容器复制数据 -type:bind#volume模式只指定容器路径即可,宿主机路径随机生成;bind需要指定容器和数据机的映射路径 source:./static target:/opt/app/static read_only:true#设置文件系统为只读文件系统 volumes: mydata:#定义在volume,可在所有服务中调用 restart#定义容器重启策略(在使用swarm部署时将忽略该选项,在swarm使用restart_policy代替restart) no#禁止自动重启容器(默认) always#无论如何容器都会重启 on-failure#当出现on-failure报错时,容器重新启动 其他选项: domainname,hostname,ipc,mac_address,privileged,read_only,shm_size,stdin_open,tty,user,working_dir 上面这些选项都只接受单个值和dockerrun的对应参数类似 对于值为时间的可接受的值: 2.5s 10s 1m30s 2h32m 5h34m56s 时间单位:us,ms,s,m,h 对于值为大小的可接受的值: 2b 1024kb 2048k 300m 1gb 单位:b,k,m,g或者kb,mb,gb networks#定义networks信息 driver#指定网络模式,大多数情况下,它bridge于单个主机和overlaySwarm上 bridge#Docker默认使用bridge连接单个主机上的网络 overlay#overlay驱动程序创建一个跨多个节点命名的网络 host#共享主机网络名称空间(等同于dockerrun--net=host) none#等同于dockerrun--net=none driver_opts#v3.2以上版本,传递给驱动程序的参数,这些参数取决于驱动程序 attachable#driver为overlay时使用,如果设置为true则除了服务之外,独立容器也可以附加到该网络;如果独立容器连接到该网络,则它可以与其他Docker守护进程连接到的该网络的服务和独立容器进行通信 ipam#自定义IPAM配置.这是一个具有多个属性的对象,每个属性都是可选的 driver#IPAM驱动程序,bridge或者default config#配置项 subnet#CIDR格式的子网,表示该网络的网段 external#外部网络,如果设置为true则docker-composeup不会尝试创建它,如果它不存在则引发错误 name#v3.5以上版本,为此网络设置名称 文件格式示例: 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]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。