docker使用详解

简介:

docker是什么?docker不是虚拟机,是容器.

虚拟机可以理解为大房子里面的套间房,套间里面有客厅/厕所/厨房等,其他套间的使用人不能使用别人的厕所和厨房等,各自不知道各自房间里面有什么,就连房主(母机)也不知道里面有什么.

容器可以理解为大房子里面的独立房间,客厅/厕所/厨房等是公用的,所有房间的使用人都有权使用它们这些共有资源,但是各自不知道各自房间里面有什么,不过房主(母机)会知道他们占用了什么资源.

Docker是基于cgrouplxc开发的容器工具.

cgroup原本是用来分割限制linux不同用户使用系统资源的工具.例如:A用户分配为1cpu2G内存,B用户分配2cpu4G内存,限制了用户使用的资源.

lxc是基于cgroup提出的早期容器工具,不但可以分割限制资源,还可以隔离容器间的资源和通信,使其互不干扰,做到类似于虚拟机的存在,不同于虚拟机的是共享了内核和系统本身的文件系统和结构,相当轻量化,不用像虚拟机那样需要用就必须先安装整套系统,相当臃肿.不过因为安装麻烦,稳定性不佳,所以最终没有大规模使用.

最后,dockerlxc进一部改进,引入镜像功能和加强了稳定性,安装也简单,操作简单明了,而且也继承了其前任轻量化的经验,社区支持力度也很大,所以最终成为时下最流行的微服务的主流应用.不过也不得不说,因为功能还是比较多,很多文章也不够全面,下面转入正题.

 

安装

不得不说,Docker由于比较新,对于系统内核要求也要比较新,最起码要用3.1以上的内核,3.8的内核是最好的,至于3.1以下的内核,事实上是可以使用的,但是稳定性会比较差一些,一般来说,我们选择centos7.2ubuntu14.04以上的版本,就问题不大了,还有就是docker的版本,也尽量用最新的比较好,因为社区不断的在改进中,新版本的稳定性自然也有改善了.

安装其实很简单,因为docker类似redis,只需要命令就可以了,所以一般来说,yum安装和简单编译就可以了.

Ubuntu:

1
2
3
apt-get update
apt-get  install  -y docker.io
ln  -sf  /usr/bin/docker .io  /usr/local/bin/docker

Centos:

1
yum  install  -y docker-io

关于docker安装完之后,会有一个docker的命令,以后所有相关操作都是围绕这个命令,例如下面是我们创建一个容器的简单语句:

1
docker run -- rm  -ti centos:latest  /bin/bash

然后,docker默认的安装目录是/var/lib/docker/,任何和容器相关的东西都存放在这个文件夹里.不过显然这个默认目录不一定符合我们的使用标准,例如大多数人喜欢将数据盘挂载到/data目录,这样就不能很好的合理利用了.

这个时候,我们第一时间想到的是改配置文件,然而docker的配置文件不是很好改,但是也可以用软连接的方式替代原本的目录,这个方法我觉得更加通用一些和灵活一些,不过缺点就是必须停掉所有容器来做了,方法如下:

1
2
3
4
5
6
7
8
9
10
/etc/init .d /docker  stop
#创建新的docker目录路径,例如/data是数据盘
mkdir  /data/dockerhome
#将docker安装目录的文件全部迁移过来
mv  /var/lib/docker/ *   /data/dockerhome/
#删了原本的目录,并创建软连接
rm  -rf  /var/lib/docker
ln  -sf  /data/dockerhome  /var/lib/docker
#启动docker服务
/etc/init .d /docker  start

   这个时候你可以看到目录就是一个软连接,但这完全不影响使用

1
2
root@xxxxxx:~ # ll /var/lib/docker
lrwxrwxrwx 1 root root 13 Oct 17 13:25  /var/lib/docker  ->  /data/dockerhome/

这个时候,安装就算完成了,下面来看怎么使用,

 

使用

使用docker之前,除了要理解容器是什么之外,还要先理解下镜像是什么.

Docker的镜像功能正是docker优于lxc的地方,以往lxc的母机是什么发行版的系统,容器就是什么发行版的系统,例如系统是centos,那容器就必然是centos.

而docker就灵活很多,系统是什么发行版本都没所谓,可以自己编辑自己想要的镜像,也可以去社区下载别人上传的镜像,通常别人上传的镜像还有特殊的功能和软件,例如remine,java等,下载了就直接能用相关功能了,不再需要自己去安装依赖包和编译什么的,相当方便.

需要注意的是,当你安装完docker之后,并没有带有任何镜像,需要自己去下载,默认的下载地址就是docker的官网,而他们的官网在国内没有节点,时不时就被国家防火墙隔绝,会出现DNS解析不到,或者找不到镜像等狗血提示,所以如果有这些提示了,就别太惊讶了.

解决的方法有三个:

第一,就是不断尝试,因为墙也不是完全隔绝,偶尔还是有可以的时候,虽然比较费时,不过我个人还是比较推荐,毕竟官网镜像比较纯净简约.

第二,添加加速器,现在国内做docker的公司还是挺多,所以他们为了给用户和自己方便,搞了加速器,其中有:阿里云,孔雀云,DaoCloud等,安装方法就不列举了,大家可以自己去网上搜一下相关的,个人建议用DaoCloud,因为方法比较简单一些.

第三,更换下载地址,虽然默认是从官方网站下载,但是不代表不可以改,而且国内镜像站也有不少,可以考虑,不过安全性和纯净度就见仁见智了,我个人是不建议的,因为我没用过,方法也不多说了,下面列举了几个.

1
2
3
4
5
6
#阿里云
docker pull registry.cn-hangzhou.aliyuncs.com /acs-sample/redis-sameersbn
#时速云
docker pull index.tenxcloud.com /tenxcloud/ubuntu
#网易蜂巢
docker pull hub.c.163.com /xbingo/jdk8 :latest

说了那么多,怎么下载镜像呢?其实我们说的第一条命令,就是可以自动下载镜像并创建一个容器.

1
docker run -- rm  -ti centos:latest  /bin/bash

只下载镜像,不创建容器就是

1
docker pull centos:latest

上面两条命令都会先查找当前镜像库有没有相关名字的镜像,没有的话就去下载相关镜像名的镜像.

查找有什么镜像就用下面的命令,他列举出所有相关名字内容的docker镜像名,包含官方的,也包含社区其他用户上传的,一般来说会注明镜像包含了什么软件和功能,然后自己按需求来下载选择,这里也是docker强大的地方

1
docker search centos

嫌下载太慢吗?确实也是慢,我们可以从其他机器把镜像导出来,再导到目的服务器

先从有镜像的服务器导出来镜像来,参数的说明在最后,导出导入可以有两种方法,一般用下面这种,导出来就是tar格式,别去解压了.

1
2
3
4
5
6
7
8
#先看看有没有想要的镜像
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              latest              9baab0af79c4        6 weeks ago         196.8 MB
#导出到tar文件
docker save centos:latest > centos-dockerimages. tar
#拷贝到目的机器
scp  -P 22 -o StrictHostKeyChecking=no centos-dockerimages. tar  root@10.0.0.19: /opt/

再过去目的服务器导进去,导进去也是原始tar格式就可以了

1
2
3
4
5
6
7
cd  /opt
#开始导进去
docker load <centos-dockerimages. tar
#看看镜像导成功没有
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              latest              9baab0af79c4        6 weeks ago         196.8 MB

手头上完全没镜像吗?去这里下载吧,是我从官方下载的centos的最精简化镜像,要解压一次,就是tar文件了,别解压两次了

http://pan.baidu.com/s/1gfPsXFl

好了,我们回归正题,这个时候,我们来研究执行第一条命令

1
docker run -- rm  -ti centos:latest  /bin/bash

这条命令意思是通过镜像centos:latest创建了一个未命名的容器,run就是运行并创建容器,--rm是当容器退出就直接删除容器的意思,-ti的意思是创建了容器之后立刻进入交互模式,/bin/bash则是指定在容器内执行什么操作,一般来说,视乎镜像包含了什么软件和环境,你的容器就有什么软件和环境.

这个自然也就延伸成可以自己创建镜像,这样命令运行之后的容器,也有你当时创建镜像时的软件和环境,甚至可以自启动软件什么的.

这条命令执行之后,就会直接进入创建容器的系统内部,因为是交互模式,类似下面这样

1
2
3
4
[root@76728f45d90b /] # ps aux 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  11752  1872 ?        Ss   05:56   0:00  /bin/bash
root        15  0.0  0.0  47424  1652 ?        R+   05:59   0:00  ps  aux

因为没有指定hostname,所以计算机名是随机的,因为是容器,不是虚拟机,不会出现除了你指定执行的程序(这里是/bin/bash)外的任何程序.

好了,既然进入了系统,其他怎么装软件和怎么装依赖包什么的,我就不打算说太多,就当做是一般虚拟机来用就行了,是ubuntu的就用apt,是centos的就用yum,自己定义好安装源就好了.我下面重点说几个基本上是必用的参数和事例.

 

重点讲解

先来看看常用命令和参数解析:

docker images:    查看本地已经存在的镜像,-a 列出所有(默认不包括中间镜像);

docker rmi IMAGE:    删除指定的镜像,-f 强制删除;

docker ps:    查看运行中的 Docker 容器,-a 列出所有(默认不包括未运行的容器);

docker rm CONTAINER:    删除指定的容器,-f 强制删除;

docker attach containerID:    进入指定ID的容器内,不过要慎用,有隐患,建议用docker exec -it  containerID/containerNAME bash来替代

docker inspect containerID:    查看指定ID的容器配置

docker commit containerID 镜像名:    将指定ID的容器制作成镜像,方便以后复用,可以重新提交来更新镜像

-d :    后台运行容器,并返回容器ID;

-i :    以交互模式运行容器,通常与 -t 同时使用;

-t :    为容器重新分配一个伪输入终端,通常与 -i 同时使用;

-c:    分配cpu资源,并不是按核数区分,可以分配1-1024任何一个数字,默认是1024,只是一个对比值,比如A和B两个容器,A配置的是1024,B配置的是512,那么A最大可以使用的CPU资源是B的两倍,如果A容器一直闲着,那B容器还是可以使用空闲资源的。

-m:    分配内存,支持k/m/g/t/p单位,例如分配1G内存:-m 1g

--memory-swap:    分配多少(非负数值)swap资源,-1即完全不分配

-p:    映射母机端口到容器端口,例如:将母机的8001端口映射给容器的80端口:-p 8001:80,将母机内网44444端口映射到容器的22端口:192.168.1.10:44444:22,甚至可以把tcp协议换成udp(我是不太建议):192.168.0.225:300:3000/udp

-v:    把母机的文件夹挂载到容器内的文件夹,例如将母机的/data/soft挂载到容器内的/soft文件夹:-v /data/soft:/soft

--name="nginx-lb" :    为容器指定一个名称(和计算机名不是一回事);

--dns 8.8.8.8 :    指定容器使用的DNS服务器,默认和宿主一致;

--dns-search example.com :    指定容器DNS搜索域名,默认和宿主一致;

-h "mars":     指定容器的hostname(和容器名不是一回事);

-e username="ritchie" :    设置环境变量;

--env-file=[]:     从指定文件读入环境变量;

--net="bridge" :    指定容器的网络连接类型,支持 bridge /host / none

--restart=on-failure:3 :    容器意外停止后的操作方式,这里是尝试重启3次的意思

 

例如我们现在搭建了一个可以运行web的容器:

1
2
3
root@xxxxx:~ # docker ps -a
CONTAINER ID    IMAGE            COMMAND            CREATED        STATUS        PORTS                NAME
6b21dcdefffe    centos:latest     "/bin/init.sh" 43    hours ago    Up 43 hours    0.0.0.0:22222->22 /tcp     testweb1

然后我们把他创建成镜像,准备复用,如果已经存在相同的镜像名称,则代表更新这个镜像,所以执行这个命令之前,要先确定自己想要的是不是这样的结果.

1
docker commit 6b21dcdefffe centos /test :webdemo1

最后我们创建一个自己想要的容器,要开通端口,要挂载web代码数据,那么命令就如下:

1
docker run -ti -e  "TZ=Asia/Shanghai"  --name testweb1 --restart=on-failure:3 -c 250 -m 1g --memory-swap=-1 -p 8001:80 -p 22222:22 - v  /data/webdata : /data/htdocs/www  centos /test :webdemo1   /bin/init .sh

意思就是创建一个容器,用镜像centos/test:webdemo1来做模板,设置时区是Asia/Shanghai,名字叫testweb1,分配了250份cpu和1G内存,把母机8001端口映射到容器的80端口,把22222端口映射给22端口,把目录/data/webdata挂载到/data/htdocs/www,在容器内运行初始化脚本/bin/init.sh(需要自己编写),这样你想要的容器就搭建完成了,你用web访问母机IP加8001端口就能访问了,想ssh登录就用22222端口.

大家看了上面的参数说明,其实就大概应该明白命令是什么意思,只是最后的/bin/init.sh是不了解为什么要这样写,后面来看一些注意事项,把一个容器真正当成服务器来使用.

 

经验之谈

以下纯属经验之谈,是对一些容易被忽略而又比较有意思的点的总结,如果有不对,欢迎指正.

首先说说/bin/init.sh是什么东西,因为这个是我自己定义的东西,不说清楚就都不知道了.

我知道很多相关文章教启动docker都是/bin/bash,他的意思是创建一个bash会话,用处是不让容器自己退出,因为容器默认是启动并执行完命令就退出的,虽然也可以从新启动,但是任务结束了,容器也还是会退出,而启动bash会话会一直等待输入,类似死循环,所以指定容器运行/bin/bash的话,如果不主动让这个容器停止的话,就永远不会退出(除非用户发送命令退出),这样就可以随便在上面配置你想要的东西了.

而我的/bin/init.sh意义和/bin/bash差不多,只是功能更多一些,先来看看这个脚本究竟有什么东西:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
touch  /var/lock/subsys/local
ulimit  -HSn 65535
/bin/sh  /etc/init .d /sshd  start > /dev/null  2>&1
/bin/sh  /etc/init .d /php-fpm  start > /dev/null  2>&1
/bin/sh  /etc/init .d /nginx  start > /dev/null  2>&1
/bin/sh  /etc/init .d /crond  start > /dev/null  2>&1
source  /etc/profile
/bin/bash
exit  0

我这个脚本就是启动完ssh,php-fpm,nginx,crond和加载/etc/profile之后再执行/binbash,所以才说功能和/bin/bash差不多,只是功能多了一些,至于为什么要这样做呢,正是我下面要说的事情.

从lxc开始到docker,容器终究是容器,不是虚拟机,一些本应在系统启动的时候加载的软件和环境变量并不会主动加载到容器内部,这个给我们带来的难度是有些本来应该已经加载到容器内直接使用的东西,要手动去启动和加载,相当不方便.

虽然有一些可以在创建可复用镜像前做好(例如时区和语言环境),然而有一些还是要手动执行和启动,我们终究是要解决的,所以就出现这种处理方式了,在启动容器的时候,就让他用脚本去启动和加载,也就是/bin/init.sh的用途了.

下面来说一些坑点:

比较容易解决的是时区和语言环境,容器内不一定有你需求的语言包,例如zh_CN.UTF-8这个字符集,除了你要先确保母机有这个字符集,你可能还要先安装两个软件包

1
2
yum  install  kde-l10n-Chinese
yum reinstall glibc-common

不过,有可能还是不行的特殊情况,我感觉是yum软件版本问题,然后自己创建字符集吧

1
2
3
4
5
6
7
#创建字符集zh_CN.UTF-8
localedef -i zh_CN -f UTF-8 zh_CN.UTF-8
#如果你想用传统的英文字符集en_US.UTF-8
#localedef -i en_US -f UTF-8 en_US.UTF-8
#添加到环境变量文件最后一行
echo  "export LANG=zh_CN.UTF-8"  >> /etc/profile
echo  "export LC_ALL=zh_CN.UTF-8"  >> /etc/profile

时区问题就比较狗血,如果没定义好,很可能是UTC时间,这个就要修改指定时区了,各种系统不尽相同,下面仅供参考

1
ln  -sf  /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime

还有就是一个还不清楚原因的简单问题,linux的计划任务crontab在容器内是不能自动生效的,甚是奇怪,需要修改一个地方才可以变得和一般机器一样使用.

1
sed  -i  's/required/sufficient/g'  /etc/pam .d /crond

还有就是关于容器登录密码的问题,容器也是可能密码登录的,所以也是可以用ssh来远程连接,这也是为什么要映射22端口,和启动sshd的原因,设置密码的方法就不多说了,passwd root就是了,反正就是给root用户设置密码了,如果把容器制作成镜像,那么容器的密码也会自动随镜像加载.

然后又一个关于centos7容器的特有问题,就是systemctl不能使用,导致服务不能启动,解决的办法非常麻烦,但是用回centos6的方式"/etc/init.d/XXX start"就没问题了,不过,你需要有centos6方式的脚本,例如sshd,httpd等,需要自己去找.

还有一个关于docker母机重启和docker升级的问题,母机重启是无可奈何,但是docker升级就要慎重,因为升级后需要重启docker进程,他们造成的问题都是docker会重启,由于docker内部的net网络是随机分配IP的DHCP,所以每次重启都可能会出现IP地址和之前不一致的情况,如果做了什么反向代理或地址直连的脚本什么的,就可能会失效了.

上面这些做完之后,一般来说你的容器已经和一般服务器环境已经基本差不多了,然后使用类似我的脚本那样的,自动把你想要的服务(例如ssh和web相关)启动起来,加载profile环境(例如java环境)变量,这样就真的和一台服务器一样了.


其他参数说明:

Attach--将终端依附到容器上

Build--通过Dockerfile创建镜像

Commit--通过容器创建本地镜像

Cp--在宿主机和容器之间相互COPY文件

Create--创建一个新的容器,注意,此时,容器的status只是Created

Diff--查看容器内发生改变的文件,以我的mysql容器为例

Events--实时输出Docker服务器端的事件,包括容器的创建,启动,关闭等。

Exec--用于容器启动之后,执行其它的任务,也可以创建容器,例如:docker exec -ti cc /bin/bash

Export--将容器的文件系统打包成tar文件

History--显示镜像制作的过程,相当于dockfile

Images--列出本机的所有镜像

Import--根据tar文件的内容新建一个镜像,与之前的export命令相对应

Info--查看docker的系统信息

Inspect--用于查看容器的配置信息,包含容器名、环境变量、运行命令、主机配置、网络配置和数据卷配置等。

Kill--强制终止容器

load --与下面的save命令相对应,将下面sava命令打包的镜像通过load命令导入

Login--登录到自己的Docker register,需有Docker Hub的注册账号

Logout--退出登录

Logs--用于查看容器的日志,它将输出到标准输出的数据作为日志输出到docker logs命令的终端上。常用于后台型容器

Pause--暂停容器内的所有进程,

Port--输出容器端口与宿主机端口的映射情况

Ps--列出所有容器,其中docker ps用于查看正在运行的容器,ps -a则用于查看所有容器。

Pull--从docker hub中下载镜像

Push--将本地的镜像上传到docker hub中

Rename--更改容器的名字

Restart--重启容器

rm --删除容器,注意,不可以删除一个运行中的容器,必须先用docker stop或docker kill使其停止。

Rmi--删除镜像

Run--让创建的容器立刻进入运行状态,该命令等同于docker create创建容器后再使用docker start启动容器

Save--将镜像打包,与上面的load命令相对应

Search--从Docker Hub中搜索镜像

Start--启动容器

Stats--动态显示容器的资源消耗情况,包括:CPU、内存、网络I/O

Stop--停止一个运行的容器

Tag--对镜像进行重命名

Top--查看容器中正在运行的进程

Unpause--恢复容器内暂停的进程,与pause参数相对应

Version--查看docker的版本

Wait--捕捉容器停止时的退出码

 

附图:


wKiom1jQwxGwyKFoAAFAkxeaUyg777.jpg




     本文转自arthur376 51CTO博客,原文链接:http://blog.51cto.com/arthur376/1863986,如需转载请自行联系原作者






相关文章
|
7月前
|
NoSQL 安全 Redis
|
8月前
|
JSON API 数据格式
docker详解
docker详解
63 0
|
9月前
|
Linux 虚拟化 开发者
|
10月前
|
Linux 测试技术 API
【Docker】什么是Docker,它用来干什么
【Docker】什么是Docker,它用来干什么
216 0
|
10月前
|
存储 运维 关系型数据库
Docker(2)
Docker(2)
|
运维 Linux Go
首先我们要知道 Docker 是什么?能干什么?
首先我们要知道 Docker 是什么?能干什么?
2159 1
|
运维 NoSQL 关系型数据库
docker详细介绍
作者主页:https://www.couragesteak.com/
docker详细介绍
|
存储 Kubernetes Linux
Docker-01-初识
Docker-01-初识
|
关系型数据库 Java MySQL
为什么需要Docker?
估计大家也可能听过Docker这项技术(在论坛上、招聘技能上、交流群上等等),要是不了解Docker,都不好意思在网上冲浪的时候吹牛逼了。 所以这几天学了一下Docker,总结了Docker入门的相关知识,分享给大家(好让我们一起吹牛逼)。
214 0
为什么需要Docker?