从Docker到Kubernetes——Docker构建应用栈(一)

文章目录

  • 应用栈介绍
    • 获取应用栈各个节点所需镜像
    • 应用栈容器节点互联
    • 应用栈容器节点启动
    • 应用栈容器节点配置
      • Redis-master配置
      • Redis-slave配置
    • Redis数据库容器节点的测试

应用栈介绍

在Docker中,镜像是容器的基础,可以通过镜像来运行容器。本文将介绍如何用Docker Hub中已有的镜像资源来搭建一个Docker应用栈。

在开始搭建过程前,对应用栈进行一个介绍:我们将搭建一个包含6个节点的Docker应用栈,其中包括一个代理节点、两个Web应用节点、一个祝数据库节点以及两个从数据库节点。
应用栈结构图如下:
从Docker到Kubernetes——Docker构建应用栈(一)_第1张图片
其中,HAProxy是负载均衡的代理节点;Redis是非关系型的数据库,它由一个主数据节点和两个从数据节点构成,App是应用(这里使用Python语言、基于Django架构设计一个访问数据库的基础Web应用)。

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

在搭建过程中,可以从Docker Hub获取现有可用的镜像,在这些镜像的基础上启动容器,按照需求进行修改来实现既定的功能。
在这个过程中,需要好好体会Docker的高可移植性所带来的便利。
根据应用栈的描述,使用下面几个命令来获取HAProxy、Redis、Django的镜像。

docker pull ubuntu
docker pull django
docker pull haproxy
docker pull redis

查看下载的镜像

[root@master ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              cf0f3ca922e0        14 hours ago        64.2MB
haproxy             latest              c09d2530df01        2 days ago          91.2MB
redis               latest              de25a81a5a0b        2 days ago          98.2MB
django              latest              eb40dcf64078        2 years ago         436MB

应用栈容器节点互联

我们搭建的应用栈是在同一个主机下搭建的。
然而,如果是一个真正的分布式架构集群还需要处理容器的跨主机通信问题,但是我们先在本文不表,以后再做介绍。

鉴于在同一个主机下搭建的容器应用栈环境,只需要完成容器间的互联来实现容器间的通信即可。

这里采用docker run 命令的–link选项建立容器间的互联关系。介绍一下--link选项的用法,通过--link选项能够进行容器间安全的交互通信,这样做的好处是 不但可以避免容器的Ip和端口暴露到外网所导致的安全问题,还可以防止容器在重启后IP地址变化导致的访问失败 ,它的原理类似于DNS服务器的域名和地址映射,当容器IP地址发生变化的时候,Docker将自动维护映射关系中的Ip地址。

使用示例如下:

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

通过--link name:alias实现容器间的交互通信,上面的例子是在ubuntu镜像上启动一个容器,并命名为console,同时将新启动的console容器连接到名为redis的容器上。

当然了,现在还不能直接使用上面那行命令,因为容器还没有创建,我们只是下载了镜像而已。上面只是举例子,我们应用栈的连接信息如下:

  • 启动redis-master容器节点。
  • 启动两个redis-slave容器节点,同时两个slave要连接到master上。
  • 两个App容器节点启动,同时连接到redis-master上。
  • HAProxy容器节点启动,同时连接到两个APP节点上。

综上所示,只需要把把HAProxy容器节点利用-p参数暴露端口给主机,即可通过主机Ip加暴露的端口从外网访问应用栈。

应用栈容器节点启动

命令如下:

# 	启动redis
docker run -itd --name redis-master redis /bin/bash
docker run -itd --name redis-slave1 --link redis-master:master redis /bin/bash
docker run -itd --name redis-slave2 --link redis-master:master redis /bin/bash

-i开启了input(输入)功能,也称交互模式,始终保持输入流开放。
-t开启了一个连接容器里边的terminal(伪终端)。
-d是detach,让/bin/bash在后台运行,否则就会进入到容器。
--name就是命名容器,命名为redis-master之类的。
/bin/bash这是表示载入容器后运行bash ,docker中必须要保持一个进程的运行,要不然整个容器就会退出。这个就表示启动容器后启动bash。

# 启动Django容器,即App应用
docker run -itd --name APP1 --link redis-master:db -v ~/Projects/Django/APP1:/usr/src/app django /bin/bash
docker run -itd --name APP2 --link redis-master:db -v ~/Projects/Django/APP2:/usr/src/app django /bin/bash

-v用于挂载一个volume,可以用多个-v参数同时挂载多个volume。volume的格式为[host-dir]:[container-dir]:[rw|ro]

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

-p用于将容器的端口暴露给主机的端口,其格式为hostPort:containerPort

此外还有一些比较重要的命令:

-c用于给运行在容器中所有进程分配CPU的shares值,这是一个相对权重,实际的处理速度还与宿主机的CPU有关。
-m用于限制为容器中所有进程分配的内存总量,以B、K、M、G为单位。


查看所有容器通过`docker ps -a`查看,启动的容器通过下面的命令查看:
[root@master ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
d95abf1e230b        haproxy             "/docker-entrypoint.…"   6 seconds ago        Up 6 seconds        0.0.0.0:6301->6301/tcp   HAProxy
c995657c55b9        django              "/bin/bash"              About a minute ago   Up About a minute                            APP2
38a8c69511ea        django              "/bin/bash"              2 minutes ago        Up 2 minutes                                 APP1
a48912a7ef3a        redis               "docker-entrypoint.s…"   8 minutes ago        Up 8 minutes        6379/tcp                 redis-slave2
6048f74ebc6b        redis               "docker-entrypoint.s…"   8 minutes ago        Up 8 minutes        6379/tcp                 redis-slave1
1d6630c27d29        redis               "docker-entrypoint.s…"   11 minutes ago       Up 11 minutes       6379/tcp                 redis-master

通过attach [container id]进入容器,可以查看/etc/hosts文件。

[root@master ~]# docker attach a48912a7ef3a
root@a48912a7ef3a:/data# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      master 1d6630c27d29 redis-master
172.17.0.4      a48912a7ef3a

如果要正常退出不关闭容器,请按Ctrl+P+Q进行退出容器

应用栈容器节点配置

在应用栈的各个容器节点都启动后,需要对他们进行配置和修改,以便实现特定的功能和通信协作,下面按照容器启动顺序依次进行解释。

注意:上面启动的只是容器节点,并不是启动的Redis或者Django本身。

Redis-master配置


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

由于容器轻量化的设计,其中缺乏相应的文本编辑命令工具,如下所示。

[root@master ~]# docker attach redis-master
root@1d6630c27d29:/data# vi /etc/hosts
bash: vi: command not found

这时候,我们使用-v参数的目的就出现了。利用-v参数挂载volume,在主机和容器间共享数据,这样就可以直接在主机上创建和编辑相关的文件。

在利用Redis镜像启动容器时,镜像中已经集成了volume的挂载命令。所以我们需要通过docker inspect命令来查看所挂载的volume的情况。

可以执行如下命令:
docker inspect container_name | grep Mounts -A 10
或者
docker inspect container_id | grep Mounts -A 10
注意大小写。

grep mounts表示过滤(grep)掉其他信息,保留挂载(Mounts)信息 -A 1010行。

我执行的命令如下:

[root@master ~]# docker inspect 1d6630c27d29 | grep Mounts -A 10
        "Mounts": [
            {
                "Type": "volume",
                "Name": "6832a825182e926c630ee7229395a7e43fcfc7a7ccaa56e4c77a8c2ac4fdb2f7",
                "Source": "/var/lib/docker/volumes/6832a825182e926c630ee7229395a7e43fcfc7a7ccaa56e4c77a8c2ac4fdb2f7/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

我们看到容器地址/data映射的主机地址为/var/lib/docker/volumes/6832a825182e926c630ee7229395a7e43fcfc7a7ccaa56e4c77a8c2ac4fdb2f7/_data

所以,进入主机的上述目录

[root@master ~]# cd /var/lib/docker/volumes/6832a825182e926c630ee7229395a7e43fcfc7a7ccaa56e4c77a8c2ac4fdb2f7/_data
[root@master _data]# vi redis.conf

搜索redis对应版本的默认配置,可以直接复制到redis.conf中。
并修改以下几项:

# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1 
# 关闭保护模式
protected-mode no 
# 让redis服务后台运行
daemonize yes 
# 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码. 只是练习配置,就不使用密码认证了)
# requirepass masterpassword 

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

[root@master _data]# docker attach redis-master
root@1d6630c27d29:/data# ls
redis.conf
root@1d6630c27d29:/data# cp redis.conf /usr/local/bin
root@1d6630c27d29:/data# cd /usr/local/bin
root@1d6630c27d29:/usr/local/bin# ls
docker-entrypoint.sh  redis-check-aof  redis-sentinel  stdout
gosu                  redis-check-rdb  redis-server
redis-benchmark       redis-cli        redis.conf
root@1d6630c27d29:/usr/local/bin# redis-server redis.conf
30:C 19 Oct 2019 11:46:48.049 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
30:C 19 Oct 2019 11:46:48.049 # Redis version=5.0.6, bits=64, commit=00000000, modified=0, pid=30, just started
30:C 19 Oct 2019 11:46:48.049 # Configuration loaded

Redis-slave配置

同样的,也是找到挂载文件的位置,创建并修改redis.conf。
与master不同的是,redis的从数据库需要修改如下几个参数:

# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1 
# 关闭保护模式
protected-mode no 
# 让redis服务后台运行
daemonize yes 
# 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码)
requirepass masterpassword 
# 设定主库的密码,用于认证,如果主库开启了requirepass选项这里就必须填相应的密码
masterauth 
# 设定master的IP和端口号,redis配置文件中的默认端口号是6379
# 低版本的redis这里会是slaveof,意思是一样的,因为slave是比较敏感的词汇,所以在redis后面的版本中不在使用slave的概念,取而代之的是replica
# 将35.236.172.131做为主,其余两台机器做从。ip和端口号按照机器和配置做相应修改。
replicaof master 6379

即如果master不设置密码,那么直接在slave服务器配置replicaof(老版本是slaveof)即配置如下replicaof masterip port
这样设置的原因在于,对于masterip使用了–link参数设置的连接名来代替实际的IP地址。通过连接名互联通信时,容器会自动读取它的host信息,将连接名转换为实际IP地址。

Redis数据库容器节点的测试

在Redis-master容器内,启动redis的客户端程序,并存储一个数据,执行过程如下:

[root@master _data]# docker attach redis-master
root@1d6630c27d29:/usr/local/bin# ls
docker-entrypoint.sh  redis-benchmark  redis-cli       redis.conf
dump.rdb              redis-check-aof  redis-sentinel  stdout
gosu                  redis-check-rdb  redis-server
root@1d6630c27d29:/usr/local/bin# redis-cli
127.0.0.1:6379> set mastername "leesangHyuk" 
OK
127.0.0.1:6379> get mastername 
"leesangHyuk"

随后在两个Slave里面查询数据:

[root@master _data]# docker attach redis-slave1
root@6048f74ebc6b:/usr/local/bin# redis-cli 
127.0.0.1:6379> get mastername 
"leesangHyuk"

同时也可以使用下面的命令查询连接情况:
redos-cli -p 6379 info

更多redis配置,请参考Reids在Docker下的配置。

你可能感兴趣的:(Docker)