您的位置:首页 > 运维架构 > Docker

Docker命令介绍及实战

2017-03-19 21:00 344 查看
对Docker的命令即组件关系作下梳理,以备不时之需。

  
子命令分类子命令
Docker环境信息info,version
容器生命周期管理create,exec,kill,pause,restart,rm,run,start,stop,unpause
镜像仓库命令login,logout,pull,push,search
镜像管理build,images,import,load,rmi,save,tag,commit
容器运维操作attach,export,inspect,port,ps,rename,stats,stop,wait,cp,diff
系统日志信息events,history,logs
命令关系图:



命令实践:搭建第一个APP Stack

Docker的设计理念是希望用户能够保证一个容器只运行一个进程,即只提供一种服务。然而,对于用户而言,单一容器是无法满足需求的。通常用户需要利用多个容器,分别提供不同的服务,并在不同的容器间互连通信,最后形成一个Docker集群,以实现特定的功能。对于Docker而言,现在已经有了很多优秀的工具来帮助用户搭建和管理集群。下面通过示例搭建一个一台机器上的简化的Docker集群,基于Docker集群构建的应用称为Docker App Stack,即Docker应用栈。

获取应用栈各节点所需镜像:
直接使用docker官网hub实在太慢,这里推荐使用DaoCloud的服务,真的好快。

参考文章:http://www.oschina.net/news/57894/daocloud

# docker pull ubuntu

# docker pull django

# docker pull haproxy

# docker pull redis

应用栈容器节点启动
启动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容器,即应用

$ 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

查看集群启动情况:

$ sudo docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES

8d3f339b8bad        haproxy             "/docker-entrypoint.s"   2 minutes ago       Up 2 minutes        0.0.0.0:6301->6301/tcp   HAProxy

cb7056eb047b        django              "/bin/bash"              4 minutes ago       Up 3 minutes                                 APP2

929c498fc10b        django              "/bin/bash"              5 minutes ago       Up 5 minutes                                 APP1

da9cbab4a734        redis               "docker-entrypoint.sh"   8 minutes ago       Up 8 minutes        6379/tcp                 redis-slave2

238b6931fc76        redis               "docker-entrypoint.sh"   17 minutes ago      Up 17 minutes       6379/tcp                 redis-slave1

60be2f9a1f2d        redis               "docker-entrypoint.sh"   18 minutes ago      Up 18 minutes       6379/tcp                 redis-master

集群示意图:





应用栈容器节点配置
Redis-master配置

查看对应容器挂载的Volumes目录:
# docker inspect -f "{{.Mounts}}" $(docker ps -a | grep redis-master | awk '{print $1}')

[{28d77df1f0fc827f7e48d9406ffe8321d50b0f641c6fb5648072aa74b38bf765 /var/lib/docker/volumes/28d77df1f0fc827f7e48d9406ffe8321d50b0f641c6fb5648072aa74b38bf765/_data /data local  true }]

可以看到宿主机中的"/var/lib/docker/volumes/28d77df1f0fc827f7e48d9406ffe8321d50b0f641c6fb5648072aa74b38bf765/_data"目录对应容器中的"/data"目录。

拷贝redis.conf到容器中
# cd `docker inspect -f "{{.Mounts}}" $(docker ps -a | grep redis-master | awk '{print $1}') | awk '{print $2}'`

将一个redis.conf文件拷贝过来

# cp /etc/redis/redis.conf ./

启动redis
切换到容器中:

# docker attach `docker ps -a | grep redis-master | awk '{print $1}'`

root@60be2f9a1f2d:/data# ls

redis.conf

将文件拷贝到/usr/loca/bin

创建redis启动需要的目录:

# mkdir -p /var/lib/redis

# mkdir -p /var/log/redis

启动

# redis-server redis.conf

注意:如果slave不能和master建立集群,需要修改redis.conf中的bind ip为容器的实际ip.默认的127.0.0.1可能不行。

确认

# ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  20248  3232 ?        Ss   07:48   0:00 /bin/bash

root        20  0.0  0.2  33308  9064 ?        Ssl  08:16   0:00 redis-server 127.0.0.1:6379

Redis Slave配置

先拷贝redis.conf

# docker inspect -f '{{.Mounts}}' $(docker ps -a | grep redis-slave1 | awk '{print $1}')[{c13c1bd2660a5b25171a8d924a6af7279b23c56ff58cca64d145de9eda9cfa7c
/var/lib/docker/volumes/c13c1bd2660a5b25171a8d924a6af7279b23c56ff58cca64d145de9eda9cfa7c/_data /data local  true }]

root@ubuntu:/home/zhangxa# cp /etc/redis/redis.conf /var/lib/docker/volumes/c13c1bd2660a5b25171a8d924a6af7279b23c56ff58cca64d145de9eda9cfa7c/_data/



对于从数据库,修改以下几个参数:

# cat redis.conf  | grep slave
slaveof master 6379

由于我们使用了--link参数,因此容器能够解析master的IP。我们可以看下docker自动添加了域名:

# 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 60be2f9a1f2d redis-master

172.17.0.3    238b6931fc76

最后启动redis-server

# redis-server redis.conf

root@238b6931fc76:/data# ps aux | grep redis

root        21  0.5  0.2  35404  9348 ?        Ssl  08:30   0:00 redis-server 127.0.0.1:6379

同理完成另外一个Slave2的配置



测试R


测试Redis数据库配置



在master容器上redis-cli

> set master "aaa"

OK

172.17.0.2:6379> get master

"aaa"在slave上测试

# redis-cli

127.0.0.1:6379> get master

"aaa"


APP容器节点配置

进入容器APP1

# docker attach $(docker ps -a | grep APP1| awk '{print $1}')

安装python redis模块


# pip install redis

Collecting redis

  Downloading redis-2.10.5-py2.py3-none-any.whl (60kB)

    100% |████████████████████████████████| 61kB 129kB/s

Installing collected packages: redis

Successfully installed redis-2.10.5

验证安装:

 python

Python 3.4.5 (default, Dec 14 2016, 18:54:20)

[GCC 4.9.2] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import redis

>>>

创建webapp

我们在创建容器时已经挂载了宿主机的~/Projects/APP1目录,

在容器内创建app应用。

# cd /usr/src/

root@929c498fc10b:/usr/src# ls

app

root@929c498fc10b:/usr/src# cd app

root@929c498fc10b:/usr/src/app# mkdir dockerweb

root@929c498fc10b:/usr/src/app# cd dockerweb/

root@929c498fc10b:/usr/src/app/dockerweb# django-admin.py startproject redisweb

root@929c498fc10b:/usr/src/app/dockerweb# ls

redisweb

# python manage.py startapp helloworld

root@cb7056eb047b:/usr/src/app/dockerweb/redisweb# ls

helloworld  manage.py  redisweb

root@cb7056eb047b:/usr/src/app/dockerweb/redisweb#

在对应的宿主机内编写:

# cd dockerweb/redisweb/helloworld/

root@ubuntu:/home/zhangxa/Projects/Django/APP2/dockerweb/redisweb/helloworld# ls

admin.py  apps.py  __init__.py  migrations  models.py  tests.py  views.py

#vim 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)


需要注意的是,我们连接redis数据库时,使用了--link参数创建的db连接来代替具体的IP地址;同理对于APP2使用相同的db连接即可。

接着继续编辑redisweb项目的setting.py,加入'helloworld'

# cd ../redisweb/

root@ubuntu:/home/zhangxa/Projects/Django/APP2/dockerweb/redisweb/redisweb# ls

__init__.py  __pycache__  settings.py  urls.py  wsgi.py

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

然后编辑urls.py,引入helloworld的hello视图:

from helloworld.views import hello

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

进入容器的/usr/src/app/dockerweb/redisweb目录完成项目的生成:

# docker attach $(docker ps -a | grep APP2 | cut -d ' ' -f 1)

# python manage.py makemigrations

No changes detected

# python manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, sessions

Running migrations:

  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

另外一个APP也是同样的配置过程。这样就完成了Docker App Stack应用栈的配置。

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

# python manage.py runserver 0.0.0.0:8001

Performing system checks...

System check identified no issues (0 silenced).

March 19, 2017 - 11:56:42

Django version 1.10.4, using settings 'redisweb.settings'

Starting development server at http://0.0.0.0:8001/
Quit the server with CONTROL-C.

HAProxy节点的配置

# docker inspect -f '{{.Mounts}}' $(docker ps -a | grep HA | cut -d ' ' -f 1)

[{ /home/zhangxa/Projects/HAProxy /tmp   true rprivate}]

利用容器启动时挂载的Volume将HAProxy的启动配置文件复制进容器中,在主机的Volume目录~/Projects/HAProxy目录下:

# cd $(docker inspect -f '{{.Mounts}}' $(docker ps -a | grep HA | cut -d ' ' -f 1) | cut -d ' ' -f 2 )

vim 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
        server APP1 APP1:8001    check    inter    2000    rise    2    fall    5
        server APP2 APP2:8002    check    inter    2000    rise    2    fall    5
随后,进入容器的/tmp目录下,将配置文件拷贝到HAProxy的工作目录下:

# cp /tmp/haproxy.cfg /usr/local/sbin

root@8d3f339b8bad:/# cd /usr/local/sbin

启动haproxy

# haproxy -f haproxy.cfg

然后在本地主机上就可以通过haproxy的地址进行访问web服务了http://172.17.0.7:6301/helloworld.

还可以在另外主机上通过本地主机IP访问,因此在创建容器时我们暴露了容器的内部端口http://192.168.17.133:6301/helloworld

我们还可以尝试干掉一台APP1后,仍然能够继续通过APP2访问。









内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  docker haproxy redis django