5.2.1 构建 Sinatra 应用程序
- 创建目录

- Dockerfile

FROM ubuntu:14.04MAINTAINER James Turnbull "james@example.com"ENV REFRESHED_AT 2014-06-01RUN apt-get update -yqq && apt-get -yqq install ruby ruby-dev build-essential redis-toolsRUN gem install --no-rdoc --no-ri sinatra json redisRUN mkdir -p /opt/webappEXPOSE 4567CMD ["/opt/webapp/bin/webapp"]
- 构建
$ sudo docker build -t jdxj/sinatra .[sudo] jdxj 的密码:Sending build context to Docker daemon 2.048kBStep 1/8 : FROM ubuntu:14.04---> df043b4f0cf1Step 2/8 : MAINTAINER James Turnbull "james@example.com"---> Using cache...
5.2.2 创建 Sinatra 容器

启动:
$ sudo docker run -d -p 4567 --name webapp -v $PWD/webapp:/opt/webapp jdxj/sinatra0f40c6838fa3803962ccd8383ca00af91993cd0532e97aa16a9a8e2d0ca6cb70
5.2.3 扩展 Sinatra 应用程序来使用 Redis
1. 升级我们的 Sinatra 应用程序

2. 构建 Redis 数据库镜像
- Dockerfile

- 构建
$ sudo docker build -t jdxj/redis .Sending build context to Docker daemon 2.048kBStep 1/7 : FROM ubuntu:18.04---> 2c047404e52dStep 2/7 : LABEL maintainer="james@example.com"---> Using cache---> 0bb3ff33e238...
- 启动
$ sudo docker run -d -p 6379 --name redis_test jdxj/redis0b786164c7f29fc6a47b21289758934c280664ddedddfa39eae167b8ab5cd1f3
5.2.4 将 Sinatra 应用程序连接到 Redis 容器
连接容器有几种方法:
- Docker 的内部网络 (不推荐)
- Docker 1.9 及之后, 可以使用 Docker Networking 以及 docker network 命令
- Docker 链接 (Docker link) (1.9 之前推荐)
Docker Networking 和 Docker link 的区别:

5.2.5 Docker 内部连网
在安装 Docker 时, 会创建一个新的网络接口 docker0. 每个 Docker 容器都会在这个接口上分配一个 IP 地址.
docker0:
$ ip a show docker03: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:b4:dc:07:fa brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:b4ff:fedc:7fa/64 scope linkvalid_lft forever preferred_lft forever
- 内网地址范围: 172.16.0.0 - 172.31.255.255
- docker0 的分配范围: 172.16~172.30
- docker0 本身地址为: 172.17.0.1
veth:




Docker 网络还有另一个部分配置才能允许建立连接:
- 防火墙规则
- NAT 配置
这些配置允许 Docker 在宿主网络和容器间路由.
查看宿主机上的 IPTables NAT 配置:
$ sudo iptables -t nat -L -n[sudo] jdxj 的密码:Chain PREROUTING (policy ACCEPT)target prot opt source destinationDOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCALChain INPUT (policy ACCEPT)target prot opt source destinationChain OUTPUT (policy ACCEPT)target prot opt source destinationDOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCALChain POSTROUTING (policy ACCEPT)target prot opt source destinationMASQUERADE all -- 172.17.0.0/16 0.0.0.0/0MASQUERADE all -- 172.18.0.0/16 0.0.0.0/0MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:80MASQUERADE tcp -- 172.17.0.4 172.17.0.4 tcp dpt:4567MASQUERADE tcp -- 172.17.0.5 172.17.0.5 tcp dpt:6379Chain DOCKER (2 references)target prot opt source destinationRETURN all -- 0.0.0.0/0 0.0.0.0/0RETURN all -- 0.0.0.0/0 0.0.0.0/0DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49154 to:172.17.0.3:80DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49155 to:172.17.0.4:4567DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49156 to:172.17.0.5:6379
网络相关阅读:
Redis 容器的网络
$ sudo docker inspect redis_test..."NetworkSettings": {"Bridge": "","SandboxID": "ad6246f985bdcbd0aa15ff5be19a013b28a962b3a3c3d744682719b32346a7b9","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {"6379/tcp": [{"HostIp": "0.0.0.0","HostPort": "49157"}]},"SandboxKey": "/var/run/docker/netns/ad6246f985bd","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "ee4ecd535e5d2fd34d9a7d79843c774647860efa100afb937dd7098e7e6b7c3f","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.5","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:05","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "3c81845502810addebbfe15bc6e7db9309f5cf84acd4be2b9215a563c9f659c9","EndpointID": "ee4ecd535e5d2fd34d9a7d79843c774647860efa100afb937dd7098e7e6b7c3f","Gateway": "172.17.0.1","IPAddress": "172.17.0.5","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:05","DriverOpts": null}}}...
这种容器互联方案有两个问题:
- 应用程序要对 Redis 容器 IP 地址做硬编码
- 重启容器后 Redis 容器 IP 会变化
5.2.6 Docker Networking

- 创建 Docker 网络
- 桥接网络
$ sudo docker network create app[sudo] jdxj 的密码:de1722dc3cb119e39338fa56be68674df1b8d230ee89821f7ed87a4713766a68
查看新创建的网络:
$ sudo docker network inspect app[{"Name": "app","Id": "de1722dc3cb119e39338fa56be68674df1b8d230ee89821f7ed87a4713766a68","Created": "2021-01-15T15:09:39.40914087+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "172.19.0.0/16","Gateway": "172.19.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}]
overlay 网络允许跨多台宿主机进行通信:
列出所有网络:
$ sudo docker network lsNETWORK ID NAME DRIVER SCOPEde1722dc3cb1 app bridge local3c8184550281 bridge bridge local0c2e0f70fb87 host host local52b9fca4051b localnet bridge localaa57e57f4d0c none null local
- 向 app 网络中添加容器
redis:
$ sudo docker run -d --net=app --name db jdxj/redis172eb42594462ec1c22f0b818edd5c1f388a8c5a1ef628bfad76ce88bd858ba1
webapp:
$ sudo docker run -p 4567 --net=app --name webapp -t -i -v $PWD/webapp:/opt/webapp jdxj/sinatra /bin/bashroot@4623e133fbb8:/#
查看 hosts:
root@4623e133fbb8:/# cat /etc/hosts127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopbackfe00::0 ip6-localnetff00::0 ip6-mcastprefixff02::1 ip6-allnodesff02::2 ip6-allrouters172.19.0.3 4623e133fbb8root@4623e133fbb8:/#
1. 将已有容器连接到 Docker 网络
$ sudo docker network connect app db2
断开:
$ sudo docker network disconnect app db2
2. 通过 Docker 链接连接容器
1.9版本之前的选择.
低于1.9版本的使用:
- 只能工作于同一台 Docker 宿主机中
# 容器名:链接名$ sudo docker run -p 4567 --name webapp --link redis:db -t -i \-v $PWD/webapp_redis:/opt/webapp jamtur01/sinatra /bin/bash
5.2.7 使用容器连接来通信
有两种方法可以让应用程序连接到 Redis.
- 环境变量
- DNS 和 /etc/hosts 信息
环境变量:

DNS:

