第一个Docker应用栈 HelloWorld

第一个Docker应用栈 HelloWorld

按照国际惯例,学习一门编程技术,第一步是从HelloWorld开始。此处,学习Docker也不例外。 下面将通过搭建一个一台机器上的简化的Docker集群,了解如何基于Docker构建一个特定的应用,基于Docker集群构建的应用称为Docker APP Stack,即Docker应用栈。

HelloWorld应用栈的结构

准备搭建一个包含6个节点的Docker应用栈,其中包括一个代理节点、两个Web的应用节点、一个主数据库节点及两个从数据库节点。具体结构如下:
Docker应用栈结构图

  1. HAProxy是负载均衡代理节点;
  2. Redis是非关系型的数据库,由一个主数据库节点和两个从数据库节点组成;
  3. APP是应用,这里使用Python语言、基于Django架构设计的一个访问数据库的基础Web应用。

搭建过程

1.获取应用栈各节点所需镜像

$ sudo docker pull ubuntu
$ sudo docker pull django
$ sudo docker pull haproxy
$ sudo docker pull redis
$ sudo docker images    #查看Docker的所有镜像

运行后应该出来4个镜像,分别是Redis, haproxy, django和ubuntu,否则不正确,请倒回去查看问题。以上完成了Docker镜像的获取。

2.容器间互联及容器启动顺序

在Docker中通过–link选项来建立容器间的连接,可以避免容器的IP和端口暴露到外网所导致的安全问题,还可以防止容器在重启后IP地址变化导致的访问失效,它的原理类似于DNS服务器的域名和地址映射。
此应用栈的正确启动顺序为:
redis-master–>redis-slave->APP->HAProxy

3.启动容器并建立容器节点间互联关系

注意:以下启动一个容器时,成功后会立即进入到容器中,但是仍需返回到宿主机中继续创建。此时需要返回,请务必使用ctrl+p ctrl+q组合键退出,保证容器仍在后台运行。后面的操作也建议这样退出容器。

# 启动Redis容器
$ sudo docker run -it --name redis-master redis /bin/bash
$ sudo docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
$ sudo docker run -it --name redis-slave2 --link redis-master redis:master /bin/bash

# 启动Django容器
$ sudo docker run -it --name APP1 --link redis-master:db -v ~/Projects/Django/App1:/usr/src/app django /bin/bash
$ sudo docker run -it --name APP2 --link redis-master:db -v ~/Projects/Django/App2:/usr/src/app django /bin/bash

# 启动HAProxy容器
$ sudo docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v ~/Projects/HAProxy:/tmp haproxy /bin/bash

设定/bin/bash命令,是给每个新启动的容器分配一个终端执行,为了方便后续与容器进行交互操作。
此时,查看容器运行情况。

$ sudo docker ps

此时正确的情况应该是有6个容器正在运行中,如果您不小心退出了容器,请在上述命令加-a参数。

4.对应用栈各容器进行配置

由于为了保证容器的轻量化,容器自身没有编辑器,我们也无需给他单独安装编辑器,此处我们使用Volume进行配置的编写。

  1. Redis Master主数据库容器节点的配置
    首先利用sudo docker ps来查看Redis-master的容器ID,并记住前4位,假设是bc8e;接下来使用
$ sudo docker inspect --format "{{ .Volumes }}"  bc8e

根据书上这样操作,会报错,报错信息为:Template parsing error: template: :1:3: executing “” at <.Volumes>: map has no entry for key “Volumes”
可以通过以下命令解决:

$ sudo docker inspect redis-master | grep Mounts -A 10

此时,会得到一个Source,该地址为volume在主机中的目录,假设为:/var/lib/docker/volumes/0a3d70900bd0fa46c797f7aa7ff5176b7f6a5a798b6a282cd6c532facfd24925/_data。
接下来进入主机的volume目录,利用启动配置文件模板来创建我们的主数据库的启动配置文件,执行命令如下:

$ cd /var/lib/docker/volumes/0a3d70900bd0fa46c797f7aa7ff5176b7f6a5a798b6a282cd6c532facfd24925/_data
$ vi redis.conf

复制以下内容进入文本:

# redis 主配置文件
# 本翻译基于redis 2.6.10,只作部分翻译,如有部分参数不明确请翻阅英文原文

# 请使用 redis-server 配置文件路径 来启动redis

# 请注意一下配置文件的数据单位,大小写不敏感
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes

################################################################################
#                               redis 的基础配置                                 #
################################################################################

# 是否作为守护进程运行,生产环境用yes
daemonize yes

# 如果作为守护进程运行的话,redis会把pid打印到这个文件
# 主要多实例的时候需要写成不同的文件
pidfile /var/run/redis.pid

# redis监听的端口,注意多实例的情况
port 6379

# 允许访问redis的ip
# 测试环境注释该选项,生产环境把所有允许访问的ip都打一次
# bind xxx.xxx.xxx.xxx

# 关闭无消息的客户端的间隔,0为关闭该功能
timeout 0

# 对客户端发送ACK信息,linux中单位为秒
tcp-keepalive 0

# 数据库的数量,我们的游戏建议为1,然后多开实例
databases 1

################################################################################
#                              redis 的持久化配置                                #
################################################################################

# save 间隔 最小更新操作
# 900秒(15分钟)之后,且至少1次变更
# 300秒(5分钟)之后,且至少10次变更
# 60秒之后,且至少10000次变更
# 如果完全作为缓存开启把save全删了

# save 900 1
# save 300 10
# save 60 2000

# 持久化失败以后,redis是否停止
stop-writes-on-bgsave-error no

# 持久化的时候是否运行对字符串对象进行压缩,算法为LZF
rdbcompression yes

# 文件末尾是否包含一个CRC64的校验和
rdbchecksum yes

# redis存储数据的文件,注意多实例的时候该不同名字或者用不同的工作目录
dbfilename dump.rdb

# redis的工作目录,注意多实例的时候该不同名字或者用不同的工作目录
# 建议用不同的工作目录
dir ./


################################################################################
#                                 redis 的限制                                  #
################################################################################

# 设置最多同时连接客户端数量。
# 默认没有限制,这个关系到Redis进程能够打开的文件描述符数量。
# 特殊值"0"表示没有限制。
# 一旦达到这个限制,Redis会关闭所有新连接并发送错误"达到最大用户数上限(max number of 
# clients reached)"
#
# maxclients 128

# 不要用比设置的上限更多的内存。一旦内存使用达到上限,Redis会根据选定的回收策略
#(参见:maxmemmory-policy)删除key。
#
# 如果因为删除策略问题Redis无法删除key,或者策略设置为 "noeviction",Redis会回复需要更多内存
# 的错误信息给命令。
# 例如,SET,LPUSH等等。但是会继续合理响应只读命令,比如:GET。
#
# 在使用Redis作为LRU缓存,或者为实例设置了硬性内存限制的时候(使用 "noeviction" 策略)的时候,
# 这个选项还是满有用的。
#
# 警告:当一堆slave连上达到内存上限的实例的时候,响应slave需要的输出缓存所需内存不计算在使用内存
# 当中。
# 这样当请求一个删除掉的key的时候就不会触发网络问题/重新同步的事件,然后slave就会收到一堆删除指
# 令,直到数据库空了为止。
#
# 简而言之,如果你有slave连上一个master的话,那建议你把master内存限制设小点儿,确保有足够的系统
# 内存用作输出缓存。
# (如果策略设置为"noeviction"的话就不无所谓了)
#
maxmemory 2gb

# 内存策略:如果达到内存限制了,Redis如何删除key。你可以在下面五个策略里面选:
# 
# volatile-lru -> 根据LRU算法生成的过期时间来删除。
# allkeys-lru -> 根据LRU算法删除任何key。
# volatile-random -> 根据过期设置来随机删除key。
# allkeys->random -> 无差别随机删。
# volatile-ttl -> 根据最近过期时间来删除(辅以TTL)
# noeviction -> 谁也不删,直接在写操作时返回错误。
# 
# 注意:对所有策略来说,如果Redis找不到合适的可以删除的key都会在写操作时返回一个错误。
#
#     这里涉及的命令:set setnx setex append
#     incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#     sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#     zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#     getset mset msetnx exec sort
#
# 默认值如下:
#
# maxmemory-policy volatile-lru

maxmemory-policy allkeys-lru

# LRU和最小TTL算法的实现都不是很精确,但是很接近(为了省内存),所以你可以用样例做测试。
# 例如:默认Redis会检查三个key然后取最旧的那个,你可以通过下面的配置项来设置样本的个数。
#
# maxmemory-samples 3

################################################################################
#                               redis 的累加模式                                 #
################################################################################

# 默认情况下,Redis是异步的把数据导出到磁盘上。这种情况下,当Redis挂掉的时候,最新的数据就丢了。
# 如果不希望丢掉任何一条数据的话就该用纯累加模式:一旦开启这个模式,Redis会把每次写入的数据在接收
# 后都写入 appendonly.aof 文件。
# 每次启动时Redis都会把这个文件的数据读入内存里。
#
# 注意,异步导出的数据库文件和纯累加文件可以并存(你得把上面所有"save"设置都注释掉,关掉导出机制)。
# 如果纯累加模式开启了,那么Redis会在启动时载入日志文件而忽略导出的 dump.rdb 文件。
#
# 重要:查看 BGREWRITEAOF 来了解当累加日志文件太大了之后,怎么在后台重新处理这个日志文件。
appendonly no

# 纯累加文件名字(默认:"appendonly.aof")
# appendfilename appendonly.aof

# 纯累加文件的flush频率
# always    ->  每次写入都flush,最安全,资源开销最大
# everysec  ->  每秒 (推荐)
# no        ->  由系统确定

# appendfsync always
appendfsync everysec
# appendfsync no

# 当纯累加文件进行rewrite时,是否需要fsync
# 当且仅当appendfsync = always || everysec 时该参数生效
no-appendfsync-on-rewrite no

# 纯累加文件下次rewrite的比例,与纯累加文件文件的最小size
# 下面的参数意味着纯累加文件会在512mb的时候进行一次rewrite
# 若rewrite后的文件大小为x mb,则下次纯累加文件将会在2x mb时rewrite
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 512mb

################################################################################
#                                redis 的高级配置                                #
################################################################################

# 如果hash中的数量超出hash-max-ziplist-entries,或者value的长度超出
# hash-max-ziplist-value,将改成保存dict,否则以ziphash的方式存储以节省空间。以下同理。
hash-max-ziplist-entries 64
hash-max-ziplist-value 128

list-max-ziplist-entries 64
list-max-ziplist-value 128

set-max-intset-entries 64

zset-max-ziplist-entries 64
zset-max-ziplist-value 128

# 是否resize hash? 如果你设置成no需要在源码做一定的修改以防止有人进行hash攻击
activerehashing yes

################################################################################
#                              redis 的其他配置文件                               #
################################################################################

# 日志配置
# include /etc/redis/log.conf

# 主从配置
# include /etc/redis/slave.conf

# 安全配置
# include /etc/redis/security.conf

# LUA配置
# include /etc/redis/lua.conf

在主机创建好启动配置文件后,切换到容器中的volume目录,并复制启动配置文件到Redis的执行工作目录,然后启动Redis服务器,具体过程如下:

# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf  (这是在启动Redis服务器)
  1. Redis Slave从数据库的配置
    与master数据库一样,都是先找到volume的目录,然后进行redis.conf配置文件的配置,配置内容如下:
# redis 主配置文件
# 本翻译基于redis 2.6.10,只作部分翻译,如有部分参数不明确请翻阅英文原文

# 请使用 redis-server 配置文件路径 来启动redis

# 请注意一下配置文件的数据单位,大小写不敏感
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes

################################################################################
#                               redis 的基础配置                                 #
################################################################################
# 设置当本机为slav服务时,设置master服务的ip地址及端口,在Redis启动时,它会自动从master进行数据同步
# slaveof <masterip> <masterport>
slaveof master 6379
# 是否作为守护进程运行,生产环境用yes
daemonize yes

# 如果作为守护进程运行的话,redis会把pid打印到这个文件
# 主要多实例的时候需要写成不同的文件
pidfile /var/run/redis.pid

# redis监听的端口,注意多实例的情况
port 6379

# 允许访问redis的ip
# 测试环境注释该选项,生产环境把所有允许访问的ip都打一次
# bind xxx.xxx.xxx.xxx

# 关闭无消息的客户端的间隔,0为关闭该功能
timeout 0

# 对客户端发送ACK信息,linux中单位为秒
tcp-keepalive 0

# 数据库的数量,我们的游戏建议为1,然后多开实例
databases 1

################################################################################
#                              redis 的持久化配置                                #
################################################################################

# save 间隔 最小更新操作
# 900秒(15分钟)之后,且至少1次变更
# 300秒(5分钟)之后,且至少10次变更
# 60秒之后,且至少10000次变更
# 如果完全作为缓存开启把save全删了

# save 900 1
# save 300 10
# save 60 2000

# 持久化失败以后,redis是否停止
stop-writes-on-bgsave-error no

# 持久化的时候是否运行对字符串对象进行压缩,算法为LZF
rdbcompression yes

# 文件末尾是否包含一个CRC64的校验和
rdbchecksum yes

# redis存储数据的文件,注意多实例的时候该不同名字或者用不同的工作目录
dbfilename dump.rdb

# redis的工作目录,注意多实例的时候该不同名字或者用不同的工作目录
# 建议用不同的工作目录
dir ./


################################################################################
#                                 redis 的限制                                  #
################################################################################

# 设置最多同时连接客户端数量。
# 默认没有限制,这个关系到Redis进程能够打开的文件描述符数量。
# 特殊值"0"表示没有限制。
# 一旦达到这个限制,Redis会关闭所有新连接并发送错误"达到最大用户数上限(max number of 
# clients reached)"
#
# maxclients 128

# 不要用比设置的上限更多的内存。一旦内存使用达到上限,Redis会根据选定的回收策略
#(参见:maxmemmory-policy)删除key。
#
# 如果因为删除策略问题Redis无法删除key,或者策略设置为 "noeviction",Redis会回复需要更多内存
# 的错误信息给命令。
# 例如,SET,LPUSH等等。但是会继续合理响应只读命令,比如:GET。
#
# 在使用Redis作为LRU缓存,或者为实例设置了硬性内存限制的时候(使用 "noeviction" 策略)的时候,
# 这个选项还是满有用的。
#
# 警告:当一堆slave连上达到内存上限的实例的时候,响应slave需要的输出缓存所需内存不计算在使用内存
# 当中。
# 这样当请求一个删除掉的key的时候就不会触发网络问题/重新同步的事件,然后slave就会收到一堆删除指
# 令,直到数据库空了为止。
#
# 简而言之,如果你有slave连上一个master的话,那建议你把master内存限制设小点儿,确保有足够的系统
# 内存用作输出缓存。
# (如果策略设置为"noeviction"的话就不无所谓了)
#
maxmemory 2gb

# 内存策略:如果达到内存限制了,Redis如何删除key。你可以在下面五个策略里面选:
# 
# volatile-lru -> 根据LRU算法生成的过期时间来删除。
# allkeys-lru -> 根据LRU算法删除任何key。
# volatile-random -> 根据过期设置来随机删除key。
# allkeys->random -> 无差别随机删。
# volatile-ttl -> 根据最近过期时间来删除(辅以TTL)
# noeviction -> 谁也不删,直接在写操作时返回错误。
# 
# 注意:对所有策略来说,如果Redis找不到合适的可以删除的key都会在写操作时返回一个错误。
#
#     这里涉及的命令:set setnx setex append
#     incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#     sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#     zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#     getset mset msetnx exec sort
#
# 默认值如下:
#
# maxmemory-policy volatile-lru

maxmemory-policy allkeys-lru

# LRU和最小TTL算法的实现都不是很精确,但是很接近(为了省内存),所以你可以用样例做测试。
# 例如:默认Redis会检查三个key然后取最旧的那个,你可以通过下面的配置项来设置样本的个数。
#
# maxmemory-samples 3

################################################################################
#                               redis 的累加模式                                 #
################################################################################

# 默认情况下,Redis是异步的把数据导出到磁盘上。这种情况下,当Redis挂掉的时候,最新的数据就丢了。
# 如果不希望丢掉任何一条数据的话就该用纯累加模式:一旦开启这个模式,Redis会把每次写入的数据在接收
# 后都写入 appendonly.aof 文件。
# 每次启动时Redis都会把这个文件的数据读入内存里。
#
# 注意,异步导出的数据库文件和纯累加文件可以并存(你得把上面所有"save"设置都注释掉,关掉导出机制)。
# 如果纯累加模式开启了,那么Redis会在启动时载入日志文件而忽略导出的 dump.rdb 文件。
#
# 重要:查看 BGREWRITEAOF 来了解当累加日志文件太大了之后,怎么在后台重新处理这个日志文件。
appendonly no

# 纯累加文件名字(默认:"appendonly.aof")
# appendfilename appendonly.aof

# 纯累加文件的flush频率
# always    ->  每次写入都flush,最安全,资源开销最大
# everysec  ->  每秒 (推荐)
# no        ->  由系统确定

# appendfsync always
appendfsync everysec
# appendfsync no

# 当纯累加文件进行rewrite时,是否需要fsync
# 当且仅当appendfsync = always || everysec 时该参数生效
no-appendfsync-on-rewrite no

# 纯累加文件下次rewrite的比例,与纯累加文件文件的最小size
# 下面的参数意味着纯累加文件会在512mb的时候进行一次rewrite
# 若rewrite后的文件大小为x mb,则下次纯累加文件将会在2x mb时rewrite
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 512mb

################################################################################
#                                redis 的高级配置                                #
################################################################################

# 如果hash中的数量超出hash-max-ziplist-entries,或者value的长度超出
# hash-max-ziplist-value,将改成保存dict,否则以ziphash的方式存储以节省空间。以下同理。
hash-max-ziplist-entries 64
hash-max-ziplist-value 128

list-max-ziplist-entries 64
list-max-ziplist-value 128

set-max-intset-entries 64

zset-max-ziplist-entries 64
zset-max-ziplist-value 128

# 是否resize hash? 如果你设置成no需要在源码做一定的修改以防止有人进行hash攻击
activerehashing yes

################################################################################
#                              redis 的其他配置文件                               #
################################################################################

# 日志配置
# include /etc/redis/log.conf

# 主从配置
# include /etc/redis/slave.conf

# 安全配置
# include /etc/redis/security.conf

# LUA配置
# include /etc/redis/lua.conf

同样的方法,启动Redis服务器。
同样的,第2个从数据库也一样方式配置。

  1. Redis数据库容器节点的测试
    接下来启动Redis master容器,打开客户端程序。
# redis
127.0.0.1:6379> set master bc8e
OK
127.0.0.1:6379> get master
"bc8e"

随后,在两个slave数据库中分别打开客户端,查看结果。

# redis-cli
127.0.0.1:6379> get master
"bc8e"

5.APP容器节点的配置

首先进入到Django容器中,安装redis数据库。

# pip install redis

验证是否成功:

# python
>>> import redis
>>> print(redis.__file__)
/usr/local/python3.4/site-packages/redis/__init__.py

没有报错的话,证明安装成功。接下来在容器中创建APP:

# 在容器内
# cd /usr/src/app/
# mkdir dockerweb
# cd dockerweb/
# django-admin.py startproject redisweb
# ls
redisweb
# cd redisweb/
# ls
manage.py redisweb
# python manage.py startapp helloworld
# ls
hello manage.py redisweb

转到主机中,利用VIm编辑配置APP文件。

# 在主机内
$ cd ~/Project/Django/App1
$ ls
dockerweb
$ cd dockerweb/redisweb/helloworld/
$ ls
admin.py __init__.py migrations model.py test.py views.py
# sudo vi views.py

文件内容如下:

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
import redis

def hello(request):
        str=redis.__file__
        str+="<br>"
        r = redis.Redis(host='db', port=6379, db=0)
        info = r.info()
        str+=("Set Hi <br>")
        r.set('Hi', 'HelloWorld-APP1')
        str+=("Get Hi: %s <br>" % r.get('Hi'))
        str+=("Redis Info: <br>")
        str+=("Key: Info Value")
        for key in info:
                str+=("%s: %s <br>" % (key, info[key]))
        return HttpResponse(str)

接下来完成setting.py文件的配置:

# cd ../redisweb/
# ls
__init__.py __pycache__ settings.py urls.py wsgi.py
# sudo vi settings.py

在settings.py中的INSTALLED_APPS选项下添加helloworld,执行过程如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'helloworld',
]

然后,修改urls.py文件:

sudo vi urls.py
from django.conf.urls import include, url
from django.contrib import admin
from helloworld.views import hello

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^helloworld$', hello),
]

注意,书中导入的包还包括:patterns,这有可能导致应用启动出错!!!
最后,在APP容器中执行:

# python manage.py makemigrations
# python detected
# python manage.py syncdb

注意,在执行第3条命令的时候出错了,原因在于书中版本较低,应重复执行第2条命令便可。
同样的,对APP2也这样配置。
最后启动两个应用,在容器中:

# python manage.py runserver 0.0.0.0:8001

5.HAProxy容器节点的配置

在主机的volumes中配置HAProxy的配置文件。

$ cd ~/Projects/HAProxy
$ sudo vi haproxy.cfg

内容如下:


global
        log 127.0.0.1   local0  # 日志输出配置,所有日志都记录在本机
        maxconn 4096    # 最大连接数
        chroot /usr/local/sbin  # 改变当前工作目录
        daemon  # 以后台形式运行HAProxy
        nbproc  4       # 启动4个HAProxy实例
        pidfile /usr/local/sbin/haproxy.pid     # pid文件位置

defaults
        log             127.0.0.1       local3  # 日志文件的输出定向
        mode    http    # {tcp|http|health}设定启动实例的协议类型
        option  dontlognull     # 保证HAProxy不记录上级负载均衡发送过来的用于检测状态没有数据的心跳包
        option  redispatch      # 当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
        retries 2       # 重试两次连接失败就认为服务器不可用,主要通过后面的check检查
        maxconn 2000    # 最大连接数
        balance roundrobin      # balance有两个可用选项:roundrobin和source,其中,roundrobin表示轮询,
                                                # 而source表示HAProxy不采用轮询的策略,而是把来自某个IP的请求转发给一个固定的IP的后端
        timeout connect 5000ms  # 连接超时时间
        timeout client  50000ms # 客户端连接超时时间
        timeout server  50000ms # 服务器端连接超时时间
listen redis_proxy
        bind    0.0.0.0:6301
        bind-process    2
        stats   enable
        stats   uri     /haproxy-stats
                server APP1 APP1:8001 check inter 2000 rise 2 fall 5 # 你的均衡节点
                server APP2 APP2:8002 check inter 2000 rise 2 fall 5
                                                                        

随后,进入到容器中,将文件移动到正确位置。

# cd /tmp
# cp haproxy.cfg /usr/local/sbin/
# cd /usr/local/sbin/
# ls
haproxy haproxy-systemd-wrapper haproxy.cfg
# haproxy -f haproxy.cfg (利用配置文件来启动HAProxy代理)

至此,完成了整个Docker应用栈的配置和部署。

6.应用与测试

在本地电脑浏览器中,输入应用栈的访问IP+项目名,如:http://172.17.0.9:6301/helloworld可以查看APP1和APP2的内容。注意端口号是6301。
此时,会报错!!!

DisallowedHost at /helloworld
Invalid HTTP_HOST header: '192.168.5.128:6301'. 
You may need to add '192.168.5.128' to ALLOWED_HOSTS.

原因在于未开放应用中的允许访问IP。
解决办法,分别修改APP1,APP2的settings.py文件。

ALLOWED_HOSTS = ['访问的IP']

或直接开放全部IP

ALLOWED_HOSTS = ['*']

其中可以通过主机名:6301/haproxy-stats来查看HAProxy的后台管理页面。
在这里插入图片描述
至此,全部完成。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值