Docker命令介绍及实战
2017-03-19 21:00
344 查看
对Docker的命令即组件关系作下梳理,以备不时之需。
命令关系图:
命令实践:搭建第一个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:
需要注意的是,我们连接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
然后编辑urls.py,引入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
# 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环境信息 | 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访问。
相关文章推荐
- Dockerfile命令介绍
- Docker实战(一):Docker基础命令
- Dockerfile命令介绍及实例
- Docker学习总结之Run命令介绍
- docker命令介绍(二)
- Docker学习总结之Run命令介绍
- Docker中镜像构建文件Dockerfile与相关命令的详细介绍
- Docker实战(一):基础命令
- APP开发实战132-Git命令介绍
- Docker学习总结之Run命令介绍
- 【Docker】基本命令使用介绍
- trap信号捕捉命令介绍与shell结合实战讲解
- Docker学习总结之Run命令介绍
- Docker介绍及基础命令
- Docker学习总结之Run命令介绍
- Docker学习总结之Run命令介绍
- Dockerfile命令介绍及实例
- docker简单介绍和常用命令
- Docker学习总结之Run命令介绍
- docker-compose介绍及常用命令