首页 > 技术文章 > 多容器部署应用实战

shenjianping 2020-02-09 18:51 原文

一、端口映射

容器中部署的应用,如果端口没有暴露出来,外界是无法访问的:

1、创建nginx容器

[root@localhost ~]# docker run -d --name web-nginx nginx
3da548e8625ea371091922e7460c80e26a0650d50a51dc8f2f95bd4c945e2dea
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3da548e8625e        nginx               "nginx -g 'daemon of…"   9 seconds ago       Up 5 seconds        80/tcp              web-nginx

2、访问nginx服务

  在访问这个nginx容器的服务时,我们需要知道这个容器的ip,但是nginx这个容器很简单里面查看ip的很多命令都没有,此时我们知道它是连接bridge网络,我们可以通过这来得知其ip地址:

[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "4d8bf95cdadf4cb2d50cffdb9edb2416060e684d198a62d68f5908201a03f5bf",
        "Created": "2020-02-01T10:34:47.076499589+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "3da548e8625ea371091922e7460c80e26a0650d50a51dc8f2f95bd4c945e2dea": {
                "Name": "web-nginx",
                "EndpointID": "2c0f8a5efb5dc62c28a405bb52ef121ffa3e39ffcfae9a354e0217f897f2b8d2",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

可以看到Containers这一项中web-nginx的ip是172.17.0.2,我们在本机(容器的宿主机)是可以访问到的:

[root@localhost ~]# curl 172.17.0.2:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

但是显然外网是无法访问到的,此时我们需要端口的映射,保证外网是可以访问到。

3、端口映射

[root@localhost ~]# docker run -d --name web-nginx -p 80:80 nginx
3b2966afb7406c2abce6da67d9bc16e35d92c03870829ae5be58bb36f359f765
#通过-p参数指定端口映射 -p 容器服务端口:宿主机端口

此时,可以访问宿主机的80端口:

[root@localhost ~]# ifconfig
...
...

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.109  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::84a4:73f5:46d2:79d3  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:f4:16:7e  txqueuelen 1000  (Ethernet)
        RX packets 2427  bytes 189210 (184.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 628  bytes 64717 (63.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 

 4、总结

 

 

 通过容器的端口映射将容器地址的80端口映射到虚拟机的地址80端口上,外部网络访问虚拟机地址的80端口即可。

二、多容器部署应用 

1、创建app.py和Dcokerfile文件

[root@localhost ~]# cd flask-web/
[root@localhost flask-web]# ls
[root@localhost flask-web]# touch app.py
[root@localhost flask-web]# touch Dockerfile
  • app.py文件
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)  #REDIS_HOST环境变量


@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
  • Dockerfile文件
FROM python:2.7
LABEL maintaner="shenjianping@gmail.com"
COPY . /app/
WORKDIR /app/
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]

2、Dockerfile文件build成镜像

[vagrant@localhost ~]$ docker image ls
REPOSITORY                               TAG                 IMAGE ID            CREATED              SIZE
shenjiangping0307/flask-web              latest              e424dd15f9a2        About a m

3、运行redis容器

可以看到这个应用中使用到了redis,所以需要先部署redis容器,然后应用的容器进行连接即可:

  • 拉取redis镜像
[root@localhost vagrant]# docker pull daocloud.io/daocloud/dao-redis
latest: Pulling from library/redis
f5d23c7fed46: Pull complete 
a4a5c04dafc1: Pull complete 
605bafc84bc9: Pull complete 
f07a4e35cd96: Pull complete 
17944e5e3eb7: Pull complete 
6f875a8605e0: Pull complete 
Digest: sha256:9815a0d456dbbef05a5fd5efe4406db003d32a2f91de40f01b62457562e1d7f6
Status: Downloaded newer image for daocloud.io/library/redis:latest
daocloud.io/library/redis:latest
 docker pull daocloud.io/library/redis:latest #其它类似这样
镜像加速下载
  • 启动redis容器

[root@localhost flask-web]# docker run -d --name redis daocloud.io/daocloud/dao-redis

431dc11f9c9c5240a7179efd97273ac557e55ffaa646d8e37fba1ecba193aa64
[root@localhost flask-web]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS               NAMES
431dc11f9c9c        daocloud.io/library/redis   "docker-entrypoint.s…"   21 seconds ago      Up 20 seconds       6379/tcp            redis

4、启动app应用

[root@localhost flask-web]# docker run -d --link redis --name web-flask -e REDIS_HOST=redis shenjianping0307/flask-web
3a32fbba037ad165064bc2aebc71c9dced269755005d5393f7e14f0b1d853c1b
#-d后台启动
#-p端口映射
#--link 连接redis容器
#-e设置环境变量

可以进入到这个容器内部查看其环境变量:

[root@localhost flask-web]# docker exec -it web-flask /bin/sh
# env
REDIS_PORT=tcp://172.17.0.2:6379
PYTHONIOENCODING=UTF-8
REDIS_PORT_6379_TCP_ADDR=172.17.0.2
HOSTNAME=3a32fbba037a
REDIS_NAME=/web-flask/redis
PYTHON_PIP_VERSION=20.0.2
REDIS_PORT_6379_TCP_PORT=6379
HOME=/root
REDIS_PORT_6379_TCP_PROTO=tcp
REDIS_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-5.0.5.tar.gz
GPG_KEY=C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF
REDIS_ENV_REDIS_VERSION=5.0.5
REDIS_PORT_6379_TCP=tcp://172.17.0.2:6379
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/42ad3426cb1ef05863521d7988d5f7fec0c99560/get-pip.py
TERM=xterm
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
REDIS_ENV_REDIS_DOWNLOAD_SHA=2139009799d21d8ff94fc40b7f36ac46699b9e1254086299f8d3b223ca54a375
LANG=C.UTF-8
PYTHON_VERSION=2.7.17

另外,可以进入到app应用的容器查看redis是否连接成功:

[root@localhost flask-web]# docker exec -it web-flask /bin/sh
# ping redis
PING redis (172.17.0.2) 56(84) bytes of data.
64 bytes from redis (172.17.0.2): icmp_seq=1 ttl=64 time=0.136 ms
64 bytes from redis (172.17.0.2): icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from redis (172.17.0.2): icmp_seq=3 ttl=64 time=0.052 ms

5、访问app应用

此时我们在app容器内部可以访问:

[root@localhost vagrant]# docker exec -it web-flask /bin/sh
# curl 127.0.0.1:5000

但是在容器外部却是访问拒绝:

[root@localhost vagrant]# curl 127.0.0.1:5000
curl: (7) Failed connect to 127.0.0.1:5000; Connection refused

这是因为我们没有把端口暴露出来,通过-p命令来进行暴露:

[root@localhost vagrant]# docker run -d -p 5000:5000  --link redis --name web-flask -e REDIS_HOST=redis shenjianping0307/flask-web

这样就可以外部进行访问容器了。

 

推荐阅读