在使用docker过程中,通常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间有能够互相访问到对方的服务
除了通过网络访问外,Docker还提供了两个很方便的功能来满足服务访问的基本需求:一个是允许映射容器内应用的服务端口到本地宿主主机,另一个是互联机制实现多个容器间通过容器名来快速访问。

端口映射实现访问容器

1.从外部访问容器应用
在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的
当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-P或-p参数来指定端口映射。当使用-P(大写)标记时,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口

FengZhen$ docker run -d -P training/webapp python app.py
caf80e2a413f37a05d9a880677e700e2bb712d3feb076cb85915bd59b61e4b87
FengZhendeMacBook-Pro:docker FengZhen$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
caf80e2a413f training/webapp "python app.py" Less than a second ago Up 4 seconds 0.0.0.0:32780->5000/tcp elastic_swartz

-d以守护态运行
此时可以使用docker ps看到,本地主机的32780被映射到了容器的5000端口。
访问宿主主机的32780端口即可访问容器内应用提供的界面

同样,可以通过docker logs命令来查看应用的信息

FengZhen$ docker logs -f caf80e2a413f
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [18/Jun/2018 04:43:12] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [18/Jun/2018 04:43:12] "GET /favicon.ico HTTP/1.1" 404 –

-p(小写)可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器,支持的格式有IP:HostPort:ContainerPort | IP::ContainerPort | HostPort:ContainerPort

2.映射所有接口地址
使用HostPort:ContainerPort格式将本地的5000端口映射到容器5000端口,如下

FengZhen$ docker run -d -p 5000:5000 training/webapp python app.py
ebe37b33ec4914d73280ab5def59d16898949fd8faa13d4404c82e2ef5c5e28c

此时默认会绑定本地所有接口上的所有地址。多次使用-p标记可以绑定多个端口,如下

FengZhen$ docker run -d -p 5000:5000 –p 3000:80 training/webapp python app.py
ebe37b33ec4914d73280ab5def59d16898949fd8faa13d4404c82e2ef5c5e28c

3.映射到指定地址的指定端口
使用IP:HostPort:ContainerPort格式指定映射使用一个特定地址,比如localhost地址127.0.0.1

FengZhen$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
b370850595aa8715e7ebbd46ed0a5666eb99494f226a618b3628a5be193fc97e
FengZhen$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b370850595aa training/webapp "python app.py" 19 seconds ago Up 20 seconds 127.0.0.1:5000->5000/tcp lucid_shtern

4.映射到指定地址的任意端口
使用IP::ContainerPort绑定localhost的任意端口到容器的5000端口,本地主机会自动分配一个端口

FengZhen$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py
4d517d154105855f2e468fd756debc08ba4d874f9912a8db39fba6f66f17eaf3
FengZhendeMacBook-Pro:docker FengZhen$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d517d154105 training/webapp "python app.py" 3 seconds ago Up 4 seconds 127.0.0.1:32768->5000/tcp optimistic_elbakyan

还可以使用udp标记来指定udp端口

FengZhen$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
003ed6ace8049d8578cc03f64547406177ebe7e8f31a97a5232de16221bd3922
FengZhendeMacBook-Pro:docker FengZhen$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
003ed6ace804 training/webapp "python app.py" 2 seconds ago Up 3 seconds 5000/tcp, 127.0.0.1:5000->5000/udp xenodochial_cori

5.查看映射端口配置
使用docker port命令来查看当前映射的端口配置,也可以查看到绑定的地址

FengZhen$ docker port lucid_shtern 5000
127.0.0.1:5000

注意:容器有自己的内部网络和IP地址,使用docker inspect +容器ID可以获取容器的具体信息

互联机制实现便捷互访

容器的互联(linking)是一种让多个容器中应用进行快速交互的方式,它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用指定具体的IP地址
1. 自定义容器命名
连接系统依据容器的名称来执行。因此,首先需要定义一个好记的容器名字
虽然当创建容器的时候,系统默认会分配一个名字,但自定义容器名字有两个好处
(1)自定义的命名比较好记,比如一个Web应用容器,我们可以给他起名叫web,一目了然
(2)当要连接其他容器时,即便重启,也可以使用容器名而不用改变,比如连接web容器到db容器
使用--name标记可以为容器自定义命名

FengZhen$ docker run -d -P --name web_link training/webapp python app.py
d35ded35f5ec9d27b32c7b9c02065497a9aa20e763ca7b751262d0fae0d25f21
使用docker ps来验证设定的命名
FengZhen$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d35ded35f5ec training/webapp "python app.py" 34 seconds ago Up 38 seconds 0.0.0.0:32781->5000/tcp web_link

-l是查看latest的容器
也可以使用docker inspect来查看容器的名字

FengZhen$ docker inspect -f "{{.Name}}" d35ded35f5ec
/web_link

注意:容器的名称是唯一的。如果已经命名了一个叫web的容器,当你要再次使用web这个名称的时候,需要先用docker rm来删除之前创建的同名容器
在执行docker run的时候如果添加--rm标记,则最终在终止后会立即删除,注意,--rm 和-d不能同时使用

2. 容器互联
使--link参数可以让容器之间安全的进行交互
先创建一个新的数据库容器

FengZhen$ docker run -d --name db training/postgres
7c1b27e9e24ce631802b1524fb34738df5092f8ad7486d82b9caeaa7c7e273dd

删除之前创建的web_link

FengZhen$ docker rm -f web_link
web_link

rm参数详解
-f :通过SIGKILL信号强制删除一个运行中的容器
-l :移除容器间的网络连接,而非容器本身
-v :-v 删除与容器关联的卷
然后创建一个新的web容器,并将它连接到db容器

FengZhen$ docker run -d -P --name web_link --link db:db training/webapp python app.py
07df5f51cb29ebe3106117165229f810a990fc3638d6df66a1626154fe86b7c2

--link参数的格式为--link name:alias,其中name是要连接的容器的名称,alias是这个连接的别名

FengZhen$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cbc65e12d629 training/webapp "python app.py" Less than a second ago Up 2 seconds 0.0.0.0:32783->5000/tcp web_link
7c1b27e9e24c training/postgres "su postgres -c '/us…" 9 minutes ago Up 9 minutes 5432/tcp

docker相当于在两个互联的容器之间创建了一个虚拟通道,而且不用映射它们的端口到宿主主机上。在启动db容器的时候并没有使用-p和-P标记,从而避免了暴露数据库服务端口到外部网络上

docker通过两种方式为容器公开连接信息
更新环境变量
更新/ect/hosts文件
使用env命令来查看web容器的环境变量

FengZhen$ docker run --rm --name web_link2 --link db:db training/webapp env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=09b666df756e
DB_PORT=tcp://172.17.0.11:5432
DB_PORT_5432_TCP=tcp://172.17.0.11:5432
DB_PORT_5432_TCP_ADDR=172.17.0.11
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/web_link2/db
DB_ENV_PG_VERSION=9.3
HOME=/root

其中DB_开头的环境变量是供web容器连接db容器使用的,前缀采用大写的连接别名。
除了环境变量之外,docker还添加host信息到父容器的/etc/hosts文件,下面是父容器的web的hosts文件

FengZhen$ docker run -it --rm --link db:db training/webapp /bin/bash
root@d518c470583b:/opt/webapp# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.11 db 7c1b27e9e24c
172.17.0.12 d518c470583b

这里有两个hosts信息,第一个是web容器,web容器用自己的ID作为默认主机名(172.17.0.12 d518c470583b),第二个是db容器的IP和主机名。(172.17.0.11 db 7c1b27e9e24c)
可以在web容器中安装ping命令来测试与db容器的联通

root@d518c470583b:/opt/webapp# apt-get install -yqq inetutils-ping
(Reading database ... 18233 files and directories currently installed.)
Removing ubuntu-minimal (1.325) ...
Removing iputils-ping (3:20121221-4ubuntu1.1) ...
Selecting previously unselected package inetutils-ping.
(Reading database ... 18221 files and directories currently installed.)
Preparing to unpack .../inetutils-ping_2%3a1.9.2-1_amd64.deb ...
Unpacking inetutils-ping (2:1.9.2-1) ...
Setting up inetutils-ping (2:1.9.2-1) ...
root@d518c470583b:/opt/webapp# ping db
PING db (172.17.0.11): 56 data bytes
64 bytes from 172.17.0.11: icmp_seq=0 ttl=64 time=0.150 ms
64 bytes from 172.17.0.11: icmp_seq=1 ttl=64 time=0.163 ms

使用ping 来测试db容器,它会解析成172.17.0.11.用户可以连接多个自容器到父容器,比如可以连接多个web到同一个db容器上

最新文章

  1. 【代码笔记】iOS-正在加载
  2. BZOJ3196: Tyvj 1730 二逼平衡树
  3. 多个Class作用于同一个元素的结果分析
  4. php实现设计模式之 迭代器模式
  5. JSP+Servlet+JavaBean统计页面在线访问次数
  6. selenium and win32api
  7. FZU2219 StarCraft(哈夫曼树)
  8. inout
  9. TCP同步传送数据示例(简洁、清楚)
  10. 跨平台base64数据传输注意问题
  11. Python之路Day5
  12. VC/MFC 在ListCtl 控件中随鼠标移动提示单元格信息
  13. Troubleshooting OpenStack 瘫痪 - 每天5分钟玩转 OpenStack(160)
  14. Java代码编写规范(不是标准规范,自行整理,无须纠结)
  15. Linux时间子系统之一:认识timer_list和timer_stats和使用
  16. button JS篇ant Design of react
  17. Python学习宝典,Python400集让你成为从零基础到手写神经网络的Python大神
  18. 浅谈jquery事件命名空间
  19. You must reset your password using ALTER USER statement before executing this statement.
  20. css实现横向进度条和竖向进度条

热门文章

  1. 网络数据传输socket和http优缺点
  2. Maven的pom文件内容详细理解
  3. ubuntu环境 rake aborted!
  4. Tomcat9源码分析:BootStrap
  5. 《TomCat与Java Web开发技术详解》(第二版) 第五章节的学习总结 ---- Servlet的高级用法
  6. 在Linux下搭建Git服务器步骤
  7. MyEclipse中Save could not be completed
  8. Linux删除乱码文件的方法
  9. ios错误ignoring file xxx missing required architecture x86_64 in file
  10. Lumen开发:结合Redis实现消息队列(2)