docker是一门很火的开源技术,发展迅速,而且很有前景。本次新开的docker实战是继运维笔记后的一个新尝试,尽本人所能,写出自己学习使用docker时候的体会。本次的docker系列会采用docker-ce(17之后的版本)基本上就是最新的docker版本来测试,目的是多踩坑,能让大家遇到问题时有个参考。本博客的参考主要来源仍然是docker官方文档,还是那句话,看官方文档不踩坑。
本次第一篇博客主要是为了解决我自己的一个问题,我在写python自动命令分发脚本的时候运用了多线程的模块来让并发的将命令分配到后端的多态测试主机上,但是我自己并没有那么多真实主机,而且就算是使用VMware或者kvm这样的虚拟化我也很难开启100台主机这时候我就想起了docker,只有他能让我一下子拥有那么多的测试机,但是我的开发环境是win8.1,这就给我出了难题,官网上docker-ce要求windows起码是win10-professional版本,仔细查阅官网发现低版本windows还可以通过docker-toolbox来搞docker。docker toolbox官方文档 docker-toolbox的下载地址就在官方文档页面中点击下载。
直接打开下载下来的安装包安装即可,这里没什么说的
安装好后会在桌面上出现一个“Docker Quickstart Terminal”,通过他可以完成初始化,但其实我从来没用这个初始化成功过。我们使用命令自己初始化即可也十分简单。
现在以管理员权限打开你的powershell(注意不是cmd)。输入
docker-machine ls
查看virtualbox虚拟机的状态。如果显示如下那么就代表安装正常了。
这里我们就解释下我们下载那200多mb的docker-toolbox里面的东西,除了像docker-machine这样的docker管理命令包之外,还有一个virtualbox虚拟机
由于win10之前的版本并不支持Hyper-v功能所以我们的docker其实是运行在一个虚拟机上面的。这就是为什么要安装virtualbox的原因。
现在初始环境搭建完成开始创建docker所依附的虚拟机
docker-machine create --driver=virtualbox default
使用上面的命令就创建了一台名字为default的虚拟机,通过打开virtualbox可以看到。在创建这个虚拟机的过程中可能会出现一些错误,其中网络问题最常见。根据命令行给的提示说是个bug,它会建议你升级virtualbox来解决,但我升级后发现仍然没有解决,最后直接重启windows就好了。
获取虚拟机的环境变量
PS C:\Windows\system32> docker-machine.exe env
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.99.100:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\mo\.docker\machine\machines\default"
$Env:DOCKER_MACHINE_NAME = "default"
$Env:COMPOSE_CONVERT_WINDOWS_PATHS = "true"
# Run this command to configure your shell:
# & "D:\Program Files\Docker Toolbox\docker-machine.exe" env | Invoke-Expression
获取这些环境变量的目的就是为我们使用docker创建环境,所以只要执行一遍上面的环境变量赋值即可,我们使用Invoke-Expression命令。
PS C:\Windows\system32> docker-machine.exe env default | Invoke-Expression
现在就能像在linux下一样使用docker了。
PS C:\Windows\system32> docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
sshd latest b562369b502c 6 days ago
230MB
ubuntu-sshd latest 30bb645e7c4b 6 days ago
230MB
ubuntu latest 07c86167cdc4 14 months ago
188MB
但是现在我们docker的文件都还存储在c盘中为了防止以后下载很多docker镜像后过多的占用c盘,我们修改这个存储目录到其他盘面。
上面就是我现在使用的default虚拟机的硬盘分出去的存储,已经占用了600多mb。如果在c盘肯定会占用很多空间。
现在打开virtualbox虚拟机,点击管理,进入虚拟机介质管理器。
假如我们要给default2虚拟机的docker存储分出c盘。
PS C:\Windows\system32> docker-machine.exe ls
NAME ACTIVE DRIVER STATE URL SWARM D
OCKER ERRORS
default - virtualbox Running tcp://192.168.99.100:2376 v
17.05.0-ce
default2 - virtualbox Running tcp://192.168.99.101:2376 v
17.05.0-ce
default3 - virtualbox Running tcp://192.168.99.102:2376 v
17.05.0-ce
但在修改存储路径之前要先关闭default2
PS C:\Windows\system32> docker-machine.exe stop default2
Stopping "default2"...
Machine "default2" was stopped.
根据下面显示的详细信息,我们可以确定这个这个就是default2的磁盘介质。
选择复制后出现上图,点击下一步。
这部选择的格式为vmdk,继续下一步即可。最终在其他盘中将硬盘副本创建好即可。但是现在虚拟机还没将他所选择的硬盘镜像切换过去,需要手动切换。
对default2虚拟机单击右键,选择设置。
在这里修改disk的路径后选择ok,再启动default2这样就完成了存储路径的修改。
1.我们在windows8.1中使用的docker其实是基于虚拟机的,也就是说虚拟机是docker的宿主机,那么我们如何进入虚拟机呢?
PS C:\Windows\system32> docker-machine.exe ssh default
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\_______/
_ _ ____ _ _
| |__ ___ ___ | |_|___ \ __| | ___ ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__| < __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 17.05.0-ce, build HEAD : 5ed2840 - Fri May 5 21:04:09 UTC 2
017
Docker version 17.05.0-ce, build 89658be
通过这条命令即可访问。
2.在前端直接访问容器
docker run -it --name test ubuntu bash
run是执行容器
-i: interactive交互性
-t: tty
–name: 你可以加也可以不加,不加的话会随机给你生成一个名字。
3.将容器在后端执行
docker run -d --name test1 ubuntu sh -c "touch a && tail -f /var/log/btmp"
上面的命令就是让容器在后天运行,又不退出的方法,因为默认,docker容器在后台运行的时候,如果执行的命令没有占用终端的话,就会直接退出,比如我们想在创建容器时候创建一个文件,在之后再访问容器,就需要使用上面的方法。加一条可以占用终端的命令。
4.如何进入docker容器
方法1:
docker attach test
attach是接入一个docker容器的stdin,进行输入并执行指令,这里注意既然是attach是接入stdin,也就是0文件描述符,所有进程都是共享的,当其他人终端去attach的时候,终端1输入了什么终端2也会相应输入,终端1输出了什么,终端2也会相应输出。
就像下图一样。
两边是镜像的,这显然不是我们希望的。
方法2:
PS C:\Windows\system32> docker exec -it test1 /bin/bash
root@0fd2465e3a86:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
使用exec就十分方便了,他的使用方法和run很相似。而且不会有共用stdin的问题。
5.导入/导出容器
这里注意一下,是容器的导入与导出,是一种容器 的持久化方式,如果你对一个纯净的容器做了很多操作之后,希望将他导出到本地一直保存就需要使用容器的导出。
我有两个容器test1,test2他们两个现在是一样的
现在我想将name为test1的容器做一点修改后然后导出。并和test2比对
我在test1容器根目录下创建了test文件,然后准备导出。
6.镜像的导入导出
注意和上面的区别这里是镜像的持久化方式。
我们现在有三个镜像,想把他导出到硬盘上,应该使用
docker save -o test.tar image_name
导入镜像
docker load -i/--input test.tar
7.给容器打标签
这个功能就是为了标识我们的容器,好似没有什么很大的作用,但其实他与后面的commit,回滚,上传都有关系,不好的标签习惯会让我们对容器造成误解,比如一个镜像名字叫sshd,如果我们没有指定过,那么他的标签默认就是“latest”。
PS C:\Windows\system32> docker tag sshd sshd:test
PS C:\Windows\system32> docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
sshd latest b562369b502c 7 days ago
230MB
sshd test b562369b502c 7 days ago
230MB
ubuntu-sshd latest 30bb645e7c4b 7 days ago
230MB
ubuntu latest 07c86167cdc4 14 months ago
188MB
给镜像加标签的速度非常快,但是这样打标签没有什么作用,要和commit结合起来才会看起来更有用。
8.创建镜像
创建镜像可以通过前面的导入镜像和加载镜像的方式创建,还可以通过官方的registry拉取,这种方式我们会在下节具体讲解。这次是通过commit命令,把我们自己使用的容器导出成镜像。
PS C:\Windows\system32> docker commit -m "test commit" -a "nored" test10 sshd:te
st1
sha256:23a24cda69f506d70bb75bbbc026fc72317f11ccbd0e915430469d1c791c3a74
PS C:\Windows\system32> docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
sshd test1 23a24cda69f5 4 seconds ago
230MB
sshd test 148e4b2c2ffb 14 seconds ago
230MB
sshd latest b562369b502c 7 days ago
230MB
ubuntu-sshd latest 30bb645e7c4b 7 days ago
230MB
ubuntu latest 07c86167cdc4 14 months ago
188MB
可以看到直接生成了标签为test1的镜像
9.docker的数据管理
挂载数据
docker和宿主机的数据是可以通过挂载来交互的。在run的时候使用-v参数即可。
docker run -it --name test -v /etc/passwd:/data ubuntu
这样就将/etc/passwd共享给了容器,而且注意,默认是读写挂载,你在容器中修改了这个文件后就会影响宿主机的文件。
docker run -it --name test -v /etc/passwd:/data:ro ubuntu
这样子就是只读挂载。
数据卷容器
所谓数据卷容器,就是用容器存储数据。
docker run -it --name test -v /data ubuntu
这样就在test容器的根目录下生成了/data的目录,当容器间需要动态共享数据的时候使用这个就可以了,类似与容器间的nfs是的。
docker run -it --volumes-from test --name test1 -v /data ubuntu
这样就共享了/data的数据。
10.docker网络暴露
容器的基本操作都会了但是怎样让他像真正的一个网络应用一样提供服务呢,这就需要端口暴露机制了。这里的端口暴露是将真机上的一个端口,比如80给容器里的应用使用,这样当外部访问80端口的时候,其实是访问容器内的web应用。
docker run -it -p 80:80 --name test nginx
-p是可以指定映射的端口
-P就是随机分配一个端口暴露
现在我们完成一开始需要的100台可以提供ssh服务的测试docker实例。
现在基本操作问题都已经搞定,配置好ssh服务的镜像也已准备好,剩下的就是循环创建,但是注意ssh要对外暴露端口在一台机器上,所以选择,每台ssh容器的端口号暴露的均不一样。这样问题就解决了。使用下面命令在powershell下。
for($i=10003;$i -le 10103;$i++)
{
docker run -d -p "${i}:22" sshd sh -c '/etc/init.d/ssh start && tail -f /var/log/btmp'
}
这样就出现了100台测试容器,而且机器一点都不卡顿。
python分发命令代码:
#coding:utf-8
import threading
import paramiko
def sshcommand(port):
paramiko.util.log_to_file('./test.log')
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.99.100',port=port,username='root',password='****')
stdin,stdout,stderr=ssh.exec_command('touch /%s' %port)
if stderr.read() == '':
print '%s is succed' %port
ssh.close()
for i in range(10003,10104):
t=threading.Thread(target=sshcommand,args=(i,))
t.start()
t.join()
参考文章:
Docker的save和export命令的区别
在Windows中玩转Docker Toolbox