Docker搭建简单的应用栈与容器Hello World访问详解

本文实例讲述了Docker搭建简单的应用栈与容器Hello World访问。分享给大家供大家参考,具体如下:

这里参考《Docker容器和容器云》 2.3.2章节应用栈搭建过程,对原书中出现的问题 -镜像不断的更新导致- 做了修改,特此说明。

系统环境

操作系统版本

$ cat /etc/issue
Debian GNU/Linux 8 \n \l

内核版本

$ uname -r
3.16.0-4-amd64

Docker版本

 docker version
Client:
 Version:   1.12.1
 API version: 1.24
 Go version:  go1.6.3
 Git commit:  23cf638
 Built:    Thu Aug 18 05:02:53 2016
 OS/Arch:   linux/amd64

Server:
 Version:   1.12.1
 API version: 1.24
 Go version:  go1.6.3
 Git commit:  23cf638
 Built:    Thu Aug 18 05:02:53 2016
 OS/Arch:   linux/amd64

应用栈搭建

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

获取应用栈节点所需的镜像

根据应用栈结构,需要从Docker Hub获取HAProxy、Redis和Django的镜像:

# docker pull ubuntu:14.04
# docker pull haproxy
# docker pull redis
# docker pull django
# docker images
REPOSITORY     TAG         IMAGE ID      CREATED       SIZE
haproxy       latest       65599e2ea3f2    2 weeks ago     139.1 MB
redis        latest       0d1cbfaa41da    2 weeks ago     185 MB
ubuntu       14.04        4a725d3b3b1c    3 weeks ago     188 MB
django       latest       79d802ec2b6c    4 weeks ago     437.4 MB

应用栈容器节点互联

docker run --link redis:redis --name console ubuntu bash

此处将在Ubuntu镜像上启动一个容器,并命名为console,同时将新启动的console容器连接到名为redis的容器上。docker run 命令的 --link选项用于添加连接到一个容器。这里还使用了 --name选项为容器指定名称。

关于Docker link用法可参考本站《Docker如何使用link建立容器之间的连接》

应用栈节点启动

启动应用栈节点之前先整理应用栈节点的连接过程:

  • 启动redis-master容器节点;
  • 两个redis-slave容器节点启动时连接到redis-master;
  • 两个APP容器节点启动时连接到redis-master;
  • HAProxy容器节点启动时连接到两个APP节点。

此外,为了能够从外网访问应用栈,并通过HAproxy节点访问应用栈中的APP,在启动HAProxy节点时使用-p参数将端口暴露给主机。

综上,容器启动顺序为:

redis-master -》redis slave -》APP -》HAProxy

启动Redis容器

# docker run -it --name redis-master redis /bin/bash
# docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
# docker run -it --name redis-slave2 --link redis-master:master redis /bin/bash

启动Django容器

# docker run -it --name APP1 --link redis-master:db -v ~/Projects/Django/APP1:/usr/src/app django /bin/bash
# docker run -it --name APP2 --link redis-master:db -v ~/Projects/Django/APP2:/usr/src/app django /bin/bash

启动HAproxy容器

# docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v ~/Projects/HAProxy:tmp haproxy /bin/bash

说明:启动每个容器时都需分配一个终端。

容器启动信息查看:

# docker ps
CONTAINER ID    IMAGE        COMMAND         CREATED       STATUS       PORTS          NAMES
ab25650701f0    haproxy       "/docker-entrypoint.s"  3 hours ago     Up 3 hours     0.0.0.0:6301->6301/tcp  HAProxy
ace790044e06    django       "/bin/bash"       3 hours ago     Up 3 hours                  APP2
64963af16131    django       "/bin/bash"       3 hours ago     Up 3 hours                  APP1
aa77330aee2a    redis        "docker-entrypoint.sh"  3 hours ago     Up 3 hours     6379/tcp         redis-slave2
1fd72289d4f2    redis        "docker-entrypoint.sh"  3 hours ago     Up 3 hours     6379/tcp         redis-slave1
518b41200dab    redis        "docker-entrypoint.sh"  3 hours ago     Up 3 hours     6379/tcp         redis-master

应用栈容器节点配置

Redis Master主数据库容器节点配置

我们知道通过volume可以在宿主机和容器之间共享数据,因此可在宿主机上创建和编辑Redis的启动配置文件。使用docker inpect命令查看volume挂载情况:

# docker inspect -f '{{ .Mounts }}' redis-master
[{5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c /var/lib/docker/volumes/5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c/_data /data local true }]

可以看出,redis-master的volume在宿主机上为目录/var/lib/docker/volumes/5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c/_data,在容器中为/data。

执行如下命令创建Redis的启动配置文件redis.conf:

# cd /var/lib/docker/volumes/5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c/_data
# cp /~/redis.conf .
# vim redis.conf

对于redis主数据库,修改如下模板文件中的几个参数:

daemonize yes
pidfile /var/run/redis.pid

redis.conf模板下载:https://github.com/yhsong-linux/docker-redis/blob/master/redis.conf

在宿主机上创建好启动配置文件后,切换到容器中的/data目录,将redis.conf拷贝到执行工作目录,然后启动redis服务:

# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf

Redis Slave从数据库容器节点配置

与Redis Master容器节点类似,在启动Redis Slave容器节点之后,需要查看vloume信息,并创建启动配置文件。

对于Redis从数据库,需要修改如下几个参数:

daemonize yes
pidfile /var/run/redis.pid
slaveof master 6379

在宿主机上创建好启动配置文件后,切换到容器中的/data目录,将redis.conf拷贝到执行工作目录,然后启动redis服务:

# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf

Redis数据库容器节点测试

在Redis Master和Redis Slave容器节点的配置和服务启动后,可以通过启动Redis的客户端程序来测试数据库。

首先,在Redis Master容器内,启动Redis的客户端程,并存储一个数据:

# redis-cli
127.0.0.1:6379> set master 518b
OK
127.0.0.1:6379> get master
"518b"

接着,在两个Redis Slave容器内,分别启动Redis的客户端程,查询之前在Master数据库中存储的数据:

# redis-cli
127.0.0.1:6379> get master
"518b"

根据响应可知,Master数据库中的数据已经同步到Slave数据库中。至此,应用栈的数据库部分搭建完成。

APP容器节点(Django)的配置

Django容器启动后,需要利用Django框架,开发一个简单的Web程序。为了访问数据库,需要在容器中安装Python的Redis支持包:

# pip install redis

安装完成后,验证支持包是否安装成功:

# python
Python 3.4.5 (default, Aug 22 2016, 20:55:07)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import redis
>>> print(redis.__file__)
/usr/local/lib/python3.4/site-packages/redis/__init__.py

如上面的输出,则表示现在可以使用Pythob语言调用Redis数据库了。接下来创建Web程序。以APP1为例,进入宿主机的volume目录对新建APP进行编辑。

在容器的volume目录下/usr/src/app下,开始创建APP:

# cd /usr/src/app
# mkdir dockerweb
# cd dockerweb
# django-admin.py startproject redisweb
# ls
redisweb
# cd redisweb
# ls
manage.py redisweb
# python manager.py startapp helloworld
# ls
helloworld manage.py redisweb

在容器中创建APP后,切换到宿主机的volume目录~/Projects/Django/App1下:

# cd ~/Projects/Django/App1
# ls
dockerweb

可以看到,在容器内创建的APP文件在宿主机的volume目录下同样可见。然后修改helloword应用的视图文件views.py:

# cd dockerweb/redisweb/helloworld
# ls
admin.py __init__.py migrations models.py tests.py views.py
# vim views.py

修改后的views.py文件如下:

from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
import redis
def hello(requset):
  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)

注意,连接Redis数据库时,使用–link参数创建db连接来代替具体的IP地址;同理,对于APP2,使用想要的db连接即可。

接下来,修改redisweb项目的配置文件setiing.py,添加新建的helloworld应用:

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

在setting.py文件中的INSTALLED_APPS选项下添加helloworld:

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

最后,修改redisweb项目的URL模板文件urls.py,它将设置访问应用的URL模式,并为URL模式调用的视图函数之间的映射表:

# vim urls.py

在url.py文件中,引入helloworld应用的hello视图,并为hello视图添加一个urlpatterns变量。修改后的urls.py文件如下:

from django.conf.urls import *
from django.contrib import admin
admin.autodiscover()
from helloworld.views import hello
urlpatterns = [
  url(r'^admin/', include(admin.site.urls)),
  url(r'^helloworld$', hello),
]

以上修改完成后,再次进入容器,在目录/usr/src/app/dockerweb/redisweb下生成项目:

# python manage.py makemigrations
No changes detected
# python manage.py migrate
Operations to perform:
 Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
 Rendering model states... DONE
 Applying contenttypes.0001_initial... OK
 Applying auth.0001_initial... OK
 Applying admin.0001_initial... OK
 Applying admin.0002_logentry_remove_auto_add... OK
 Applying contenttypes.0002_remove_content_type_name... OK
 Applying auth.0002_alter_permission_name_max_length... OK
 Applying auth.0003_alter_user_email_max_length... OK
 Applying auth.0004_alter_user_username_opts... OK
 Applying auth.0005_alter_user_last_login_null... OK
 Applying auth.0006_require_contenttypes_0002... OK
 Applying auth.0007_alter_validators_add_error_messages... OK
 Applying auth.0008_alter_user_username_max_length... OK
 Applying sessions.0001_initial... OK

至此,所有APP1容器的配置已经完成,APP2容器的配置也是同样的过程。配置完成APP1和APP2的容器后,就完成了应用栈的APP部分的全部配置。

在启动APP容器的Web服务器时,可以指定服务器的端口和IP地址,为了通过HAproxy容器节点接受外网所有的公共IP地址访问,实现负载均衡,需要指定服务器的IP地址和端口。对于APP1使用8001端口,而APP2使用8002端口,同时,都使用0.0.0.0地址。以APP1为例,启动服务器的过程如下:

# python manage.py runserver 0.0.0.0:8001
# python manage.py runserver 0.0.0.0:8001
Performing system checks...

System check identified no issues (0 silenced).
September 20, 2016 - 23:16:44
Django version 1.10, using settings 'redisweb.settings'
Starting development server at http://0.0.0.0:8001/
Quit the server with CONTROL-C.

HAproxy容器节点配置

所有对应用栈的访问均通过HAproxy负载均衡代理容器节点实现负载均衡。
首先,将HAProxy的启动配置我呢间复制到容器中,在宿主机的volumes目录~/Projects/HAProxy/下:

# cd ~/Projects/HAProxy/
# vim haproxy.cfg

修改后的haproxy.cfg文件如下:

global
  log 127.0.0.1  local0
  maxconn 4096
  chroot /usr/local/sbin
  daemon
  nbproc 4
  pidfile /usr/local/sbin/haproxy.pid
defaults
  log   127.0.0.1  local3
  mode  http
  option dontlognull
  option redispatch
  retries 2
  maxconn 2000
  balance roundrobin
  timeout connect 5000ms
  timeout client 50000ms
  timeout server 50000ms
listen redis_proxy
  bind 0.0.0.0:6301
  stats enable
  stats uri /haproxy-stats
  stats auth phil:NRG93012
    server APP1 APP1:8001 check inter 2000 rise 2 fall 5
    server APP2 APP2:8002 check inter 2000 rise 2 fall 5

随后,进入容器的volume目录/tmp下,将Haproxy的启动配置文件复制到HAproxy的工作目录:

# cd /tmp
# cp haproxy.cfg /usr/local/sbin
# cd /usr/local/sbin
# ls
haproxy haproxy-systemd-wrapper haproxy.cfg

然后,利用配置文件启动HAProxy代理:

# haproxy -f haproxy.cfg

应用栈访问测试

在浏览器中访问http://172.17.0.7:6301/helloworld,可以看到APP1或APP2的页面(本地主机访问应用栈):

说明:172.17.0.7是HAProxy容器的地址。

本地测试通过后,尝试在其他主机上通过应用栈入口地址的IP地址和6301端口访问应用栈APP,即http://192.168.1.104:6301/helloworld,如下图所示(外网其他主机访问应用栈):

说明:192.168.1.104是宿主机的IP地址。

希望本文所述对大家docker容器使用有所帮助。

(0)

相关推荐

  • Docker堆栈的管理操作详解

    本文详细讲述了Docker堆栈的管理操作.分享给大家供大家参考,具体如下: 在Docker中,镜像是一个轻量级的,独立的可执行程序包,包含运行一个软件所需的所有东西,包括代码.运行环境.库.环境变量和配置文件.容器是镜像的运行实例,默认情况下,它与主机环境完全隔离,只有在配置时才访问主机文件和端口. 在<Docker集群的创建与管理>中,设置了一个运行Docker的机器集群,并部署了一个应用程序,容器在多台机器上运行.现在你可以了解分布式应用程序层次结构的顶层:堆栈.堆栈是一组相互关联的服务,

  • 详解Docker Swarm服务发现和负载均衡原理

    本文将介绍基于 DNS 的负载均衡.基于 VIP 的负载均衡和路由网格(Routing Mesh). 使用的技术 Docker 使用了 Linux 内核 iptables 和 IPVS 的功能来实现服务发现和负载均衡. iptables 是 Linux 内核中可用的包过滤技术,它可用于根据数据包的内容进行分类.修改和转发决策. IPVS 是 Linux 内核中可用的传输级负载均衡器. 准备工作 swarm 集群: [Manager]node1.[Worker]node2 客户端镜像: regis

  • 浅谈Docker数据持久化

    容器中数据持久化主要有两种方式: 数据卷(Data Volumes) 数据卷容器(Data Volumes Dontainers) 数据卷 数据卷是一个可供一个或多个容器使用的特殊目录,可以绕过UFS(Unix File System). 数据卷可以在容器之间共享和重用 对数据卷的修改会立马生效 对数据卷的更新,不会影响镜像 数据卷默认会一直存在,即使容器被删除 一个容器可以挂载多个数据卷 注意:数据卷的使用,类似于 Linux 下对目录或文件进行 mount. 创建数据卷 示例: docker

  • Docker使用Dockerfile创建支持ssh服务自启动的容器镜像

    本文实例为大家分享了Dockerfile创建支持ssh服务自启动的容器镜像,供大家参考,具体内容如下 1. 首先创建一个Dockerfile文件,文件内容如下 # 选择一个已有的os镜像作为基础 FROM centos:centos6 # 镜像的作者 MAINTAINER Fanbin Kong "kongxx@hotmail.com" # 安装openssh-server和sudo软件包,并且将sshd的UsePAM参数设置成no RUN yum install -y openssh

  • Docker-利用dockerfile来搭建tomcat服务的方法

    在前面的例子中,我们从下载镜像,启动容器,在容器中输入命令来运行程序,这些命令都是手工一条条往里输入的,无法重复利用,而且效率很低.所以就需要一 种文件或脚本,我们把想执行的操作以命令的方式写入其中,然后让docker读取并分析.执行,那么重复构建.更新将变得很方便,所以Dockerfile就此诞生了. 常用参数: FROM命令.用法,FROM <image>:<tag>.FROM命令告诉docker我们构建的镜像是以哪个(发行版)镜像为基础的 RUN命令.用法RUN <co

  • 详解Docker创建支持ssh服务的容器和镜像

    1. 这里使用的centos作为容器,所以首先下载centos的images # sudo docker pull centos 2. 下载后运行一个centos的容器,这里使用centos6作为我测试的容器 # sudo docker run --name=centos-ssh -i -t centos:centos6 /bin/bash  3. 安装openssh-server服务软件包 # yum install openssh-server 4. 编辑sshd的配置文件/etc/ssh/

  • CentOS 7安装Docker服务详细过程

    Docker 简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. Docker 官网:http://www.docker.com/ Docker 官方文档:https://docs.docker.com/ Docker Github 地址:https://github.com/docker/docker Docker 仓库:https:

  • Docker如何同时启动多个服务

    前几篇Docker的文章介绍启动容器时都是只启动一个后台服务,今天来说说怎样通过supervisor来启动多个服务 1. 首先创建一个目录并在目录下创建一个Dockerfile,文件内容如下 FROM centos:centos6 MAINTAINER Fanbin Kong "kongxx@hotmail.com" RUN rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rp

  • Docker搭建简单的应用栈与容器Hello World访问详解

    本文实例讲述了Docker搭建简单的应用栈与容器Hello World访问.分享给大家供大家参考,具体如下: 这里参考<Docker容器和容器云> 2.3.2章节应用栈搭建过程,对原书中出现的问题 -镜像不断的更新导致- 做了修改,特此说明. 系统环境 操作系统版本 $ cat /etc/issue Debian GNU/Linux 8 \n \l 内核版本 $ uname -r 3.16.0-4-amd64 Docker版本 docker version Client: Version: 1

  • 在docker中部署tomcat并且部署java应用程序的步骤详解

    先给大家简单说下Docker的概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. 1.先说如何在docker中部署tomcat 第一步:root用户登录在系统根目录下创建文件夹tomcat7,命令如:mkdir tomcat7,并且切换到该目录下:cd tomcat7: 第二步:创建Dockerfile,命令如:touch Docker

  • Java图形化界面设计之容器(JFrame)详解

    Java图形化界面设计--容器(JFrame) 程序是为了方便用户使用的,因此实现图形化界面的程序编写是所有编程语言发展的必然趋势,在命令提示符下运行的程序可以让我们了解java程序的基本知识体系结构,现在就进入java图形化界面编程. 一.Java基本类(JFC) Java基本类("JavaFoundationClasses",JFC),由一些软件包组成.这些软件包主要包括下面一些应用程序接口(API): ·抽象窗口工具集(AWT)(1.1及以上版本). ·Swing构件. ·Jav

  • spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean实例放入bean缓存池: 应用程序使用bean. 1.2.基于xml的配置 (1)xml文件概述 xmlns------默认命名空间 xmlns:xsi-------标准命名空间,用于指定自定义命名空间的schema文件 xmlns:xxx="aaaaa"-------自定义命名空间,xx

  • docker在win10家庭版下构建laravel开发环境的教程详解

    操作系统: win10 家庭版 安装docker: 官网下载的docker无法安装成功,提示操作系统版本问题~~~~ 所以直接下载了阿里提供的docker安装包: http://mirrors.aliyun.com/doc ... 社区版是-ce后缀的 阿里镜像加速 首先登录阿里云 查找容器镜像服务 win10找到C:Users用户.dockermachinemachinesdefault底下有个config.json文件,在属性RegistryMirror添加加速器地址,docker虚拟机重启

  • Java栈和基础队列的实现详解

    目录 栈(stack) 栈支持的三个核心操作: 栈的常见实际应用: 栈的实现 队列 无论是哪种队列,都必须支持三个核心操作: 基础队列的实现 栈和队列:都是线性表,都是基于List基础上的实现 线性表:数组,链表,字符串,栈,队列 元素按照一条“直线”排列,线性表这个结构中,一次添加单个元素 栈(stack) 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)

  • C++Vector容器常用函数接口详解

    目录 一.基础框架 二.迭代器实现 三.size capacity resize reserve 四.insert,erase 五.pop_back,push_back 六.operator[] 七.构造函数 析构函数 赋值重载 一.基础框架 template<class T> class vector { public: typedef T* iterator; typedef const T* const_iterator; private: iterator _start;//指向第一个

  • Spring容器刷新obtainFreshBeanFactory示例详解

    目录 Spring容器刷新—02—obtainFreshBeanFactory BeanFactory和ApplicationContext obtainFreshBeanFactory 1.GenericApplicationContext系列的实现 2.AbstractRefreshableApplicationContext系列的实现 该使用哪个BeanFactory? Servlet环境 SpringBoot环境 Spring容器刷新—02—obtainFreshBeanFactory

  • IOS 简单的本地json格式文件解析的实例详解

    IOS 简单的本地json格式文件解析的实例详解 ljweibo.json文件 { "data":[{ "name" : "孙悟空", "content" : "7月12日的国务院常务会议上,李克强明确要求,要将已审议的<快递条例(草案)>向社会公开征求意见.在会上,总理说了这么一段话:"几年前,快递业刚刚开始发展的时候,有些城市不允许快递存在,理由是影响市容整洁,快递员骑的摩的也不允许停放.但

  • 简单了解Java方法的定义和使用实现详解

    这篇文章主要介绍了简单了解Java方法的定义和使用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.概念 Java语言中的"方法"(Method)在其他语言当中也可能被称为"函数"(Function).对于一些复杂的代码逻辑,如果希望重复使用这些代码,并且做到"随时任意使用",那么就可以将这些代码放在一个大括号"{}"当中,并且起一个名字.使用代码的时候,直接找到名

随机推荐