用docker toolBox 搭建 nginx + flask + redis 环境

本篇博客,主要是了解一下docker-compose的使用,docker-compose是官方给出的同时部署多个容器的解决方案;当你需要多个容器同时运行作为你的解决方案时:比如构建一个网站,需要php + apache + postgrel ,这里面的每一个组件(web server,数据库等)都是一个容器,如果自己一个一个建立,并且还要维护容器之间的互联关系的话,是一件复杂的事情;docker-compose就是来帮助我们来做这个事情的;

本文从一个简单的例子开始来介绍一下docker-compose的使用方法,本文章涉及的工程代码放在了附件中 https://files.cnblogs.com/files/yuhan-TB/docker-compose-test.tar.gz 可以下载;;

场景如下:

ngnix在最前端做负载均衡;nginx之后是三个flask web server容器,用来处理实际用户的请求;redis用来存储一些数据,flask app与redis相连来获取数据,然后根据实际情况来输出相应的消息;

我的系统是mac os,

(1) 首先安装docker toolbox工具箱,toolbox工具箱集成了很多工具,docker-compose,docker-machine,docker-client, virtualBox等等;

为啥需要virtualBox呢,因为docker是不支持mac 和 windows 的,所以要想在这两个OS上运行的话,做法是安装一个虚拟机,然后在虚拟机上启动docker,然后安装docker-client,docker-client与虚拟机中的docker engine连接;

之前mac 或 windows下的安装都是使用boot2docker,原理也是采用虚拟机实现的。从docker官方发布docker toolBox之后,就不建议使用boot2docker了。

(2) 用docker machine 建立一个虚拟机,docker-machine的作用是在本机或在云端环境建立一个docker的运行环境;以下是建立命令;

docker-machine create --driver virtualbox hehe-dev 这里面我起的虚拟机的名字是hehe-dev 呵呵~

docker-machine ls 建立好之后,可以通过ls命令来查看自己建立的虚拟机是否已经起来;

docker-machine env hehe-dev, 接下来,通过env命令可以查看 hehe-dev 虚拟机的环境变量,对这些环境变量(就是弹出的一些export,这些export 要自己在终端中设置一下)要进行设置一下,好让docker client可以找到 docker engine的地址;

docker version,然后 docker version一下,看看docker-machine是否安装成功;

(3)接下来就是docker-compose了。

mkdir docker-compse-test 首先建立一个docker-compose的文件夹,这里我起名叫做docker-compose-test;

touch docker-compose.yml 在文件夹下建立一个yml文件;docker-compose是通过yml文件来对各个容器进行配置的;下面将我的配置贴出来:

flask_a:

restart: always

build: ./flask_a

ports:

- "5002:5000"

links:

- redis:redis

flask_b:

restart: always

build: ./flask_b

ports:

- "5003:5000"

links:

- redis:redis

flask_c:

restart: always

build: ./flask_c

ports:

- "5004:5000"

links:

- redis:redis

nginx:

restart: always

build: ./nginx

ports:

- "5001:80"

links:

- flask_a:flask_a

- flask_b:flask_b

- flask_c:flask_c

redis:

restart: always

build: ./redis

ports:

- "6379:6379"

首先是三个flask_server的实例,分别连上redis,将flask的5000端口与docker-machine虚拟机的端口进行映射,由于有三个flask实例:flask_a, flask_b,flask_c,所以分别映射端口 5002,5003,5004;

然后是nginx,nginx由于要做负载均衡,需要与三个flask server都link起来;nginx映射的虚拟机的端口是 5001;

这里在docker-compose-test文件夹下,分别建立flask_a, flask_b, flask_c, nginx, redis的文件夹,在里面分别创建Dockerfile;

为了了解一下简要的逻辑,将flask中的app代码这里列出来:

from flask import Flask,request

import os

import redis

app = Flask(__name__)

@app.route('/index', methods=['POST','GET'])

def hello_world():

request_args = {}

if request.method == 'POST':

request_args = request.form

elif request.method == 'GET':

request_args = request.args

username = request_args.get('username','')

r = redis.Redis(host=os.environ['REDIS_1_PORT_6379_TCP_ADDR'], port=6379, db=0)

if r.get(username):

return 'flask instance a: %s exists' % (username,)

else:

return 'flask instance a: %s not exists' % (username,)

if __name__ == '__main__':

app.run(debug=True,host='0.0.0.0')

就是接受用户请求的参数,去redis中去查一下用户是否存在,存在打印exists信息,不存在打印not exists信息,并且打印instance a、b或者c的消息,这个主要来判断负载均衡是不是起作用了。

dockeer-compose在build的过程中,可能会遇到两个问题:

(a)当build flask的时候的可能会遇到:

Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='pypi.python.org', port=443): Read timed out. (read timeout=15)",)': /simple/flask/

这个是dns的问题。解决方法是修改宿主机的 /etc/resolv.conf 在里面添加google的 nameserver

nameserver 8.8.8.8

nameserver 8.8.4.4

然后重启docker-machine docker-machine stop && docker-machine start

(b)第二个问题是,由于初次build,有些需要镜像需要从官方下载,官方的镜像有时下载很慢,这里可以使用daocloud 的官方加速工具;这里也给daocloud 打一个广告;

做法是 docker-machine ssh hehe-dev,登陆到虚拟机中,运行: curl -sSL https://get.daocloud.io/daomonit/install.sh | sh -s db634a0ee990daaf2843cdecbf843907f63825e0

这样就可以在虚拟机中,运用命令 "dao pull 镜像名:tag" 来下载镜像了,这样会很快;

(3)上面已经将整个工程启动起来了,由于flask需要访问redis,但是redis中还没有数据,需要在redis中加入要访问的数据;从上面的yml文件可以知道。redis的端口是6379;我的做法是在宿主机下载redis程序;

然后使用redis-cli 连接虚拟机上的redis,虚拟机的ip 通过 docker-machine ip hehe-dev获得,然后用redis-cli -h 虚拟机ip -p 6379连接到redis server;接着插入两条数据:

set tom 100

set harry 100

(4)最后一步就是去验证flask 是否已经起作用,通过浏览器访问 http://虚拟机ip:5001/index?username=tom ,连续访问三次,可以看到负载均衡起作用了。tom exists

然后连续访问三次 http://虚拟机ip:5001/index?username=jerry,可以看到负载均衡也起作用了。jerry not exists;