云计算之docker篇

云计算之docker篇

http://www.jixuege.com/?id=45&utm_source=tuicool&utm_medium=referral

写在前面的话:

  由于最近公司开始着手做云计算,自己有幸参与整个项目的全过程,所以呢,准备在blog中记录整个项目从无到有,从测试到生产的全过程,希望对自己的每一步进行一个记录以及在项目中遇到的坑和如何解决。希望大家能够在此找到一点点借鉴。

==华丽分割线====================================================================

什么是docker?

  docker的字面意思是码头工人,与集装箱有关,那么docker就可以理解为是一个集装箱(容器)。

详细的说:

  dockers是dockers.inc  公司开源的一个基于LXC技术之上构建的container容器引擎(说个题外话 openstack基于KVM ,docker基于LXC),源代码托管在GITHUB上,基于GO 语言并遵从apache2.0 协议开源。(可以商业,改吧改吧就可以卖钱了)。

  docker是通过内核虚拟化技术((namespaces及cgroups等),KVM呢是通过硬件虚拟化技术,CPU支持的。)来提供容器的资源隔离与 安全保障等。

  在非linux平台是没法使用docker的,因为他是基于内核技术来实现资源隔离和安全保障的。

  由于dockers通过操作系统层的虚拟化实现隔离,所以docker容器在运行的时候,不需要类似虚拟机(VM)额外的操作系统开销,提高了资源的利用率。

  docker官网在此 https://www.docker.com/,截个图来说明一下docker的三大理念。

1.png如上图所示:Build  ,ship ,Run(构建,运输, 运行)。

构建:这就是docker的三大核心理念,认为一个东西我构建上了,放在某个地方就可以运行起来,可以用java来进行一个对比,怎么说呢?我有JVM虚拟机,一次构建,备考之后到处运行。但是呢,也有不同的地方,因为docker里面运行的是一个应用(apache ,nginx,tomcat),  它的构建是基于docker的镜像,可以基于这个镜像起任何的容器。

运输: 我们知道openstack 的镜像传到glance ,那么docker是传在dockerhub,一个私有的地方,谁有权访问我就可以给它。

运行:docker运行是起一个容器。


docker的组成

  docker是一个传统的CS结构的架构:客户端服务器。BS是什么呢?浏览器和服务器模式。

有一个dockerclient  和docker server

三个组件: 镜像(image) 、容器(container)、仓库(repository)。


docker与openstack的对比:


类别
docker
open
部署难度 非常简答 组件多,部署复杂
启动速度 秒级 分钟级
执行性能 和物理机系统几乎一至 VM会占用一些资源
镜像体积 镜像是MB级别 虚拟机镜像GB级别
管理效率 管理简单 组件相互依赖,管理复杂
隔离性 隔离性高 彻底隔离
可管理性 单进程,不建议启动SSH 完整的系统管理
网络连接 比较弱 借助neutron可以灵活组件各类网络架构



 

为什么不建议启动SSH?

这就是docker的理念,我们起一个docker容器,我在里面安装一个zabbix-agent ,saltstack-agent,ssh   当作虚拟机使用,那为什么不直接用虚拟机?

难道就差启动的分钟级这个时间么,docker的真正的最佳实践不是当作虚拟机使用,但是为什么有的还是当虚拟机使用呢?因为没有openstack,关键到底还是要看业务,我们知道IT管理的PPT(流程,人员,工具),比如说,一个新型的公司,架构从头规划,可以根据docker模式来规划,但是如果架构已经成型,流程组织结构都已固话,那么就得考虑业务是否要使用容器来启动。

   

docker能干什么?

1、简化配置

工作中有很多环境,比如测试环境,开发环境,性能测试,生产和预生产,环境不一致,配置不一致会导致上线失败,测试安装了一个python的依赖,线上没有,测试通过,上生产就开始报错。(不能导入某个模块,起不来了)。

docker可以简化配置,做好一个镜像,直接拿镜像就起得来。openstack也能干这事,saltstack也可以做这些事。

docker解决的不是openstack的问题,应该和RPM包进行对比或者saltstack来对比。

saltstack就可以简化环境,一条命令解决。

2、代码流水线管理

开发写代码-开发环境-提交SVN-测试拉下来测试-预生产环境-灰度发布(生产环境)。

3、开发效率

开发人员入职第一天配环境,用docker镜像构建好,需要啥都装好,RUN起来就完事。

openstack也可以做,给个虚拟镜像就完事。给个IP地址,用户密码SSH上去就完事。举个例子:

这么对比来说,openstack效率更高,给开发每人一台虚拟机,把6080对外(NOVNCPROXY端口),这样开发在家都可以使用,虚拟机在远端,跟你是否在本地没有关系,但是docker不行,因为docker是启在本地。

4、应用隔离

虚拟机是完全隔离,docker只是一个隔离,只是没有占用资源

5、整合服务器

服务器可以跑多个容器来提高利用率,但是也可以其多个虚拟机进程

6、debug能力

docker开发想调试很难,虚拟机爱怎么调都可以

7、多租户

openstack设计就是多租户,一个租户可以有多个用户

8、快速部署

docker是秒级,体积小,完胜openstack


docker就是以快为容器,比如,抢红包,我可以1秒钟启动上千个容器,但是起虚拟机不行。

但是呢,一切的一切还是看业务。


使用docker的几个理由:

1、技术储备

2、跟上潮流

3、符合当前业务需求

大多数都是第2个,很少说有业务需求的。

安装SSH来进行管理,其实我们也是这么做的。

优势就是快,但是缺点很多。

docker组成基于CS,如果server宕了呢?所有的容器都会停止运行,没有多server,业界虽有提出,但是还是不行。

所以说,现在基本上都是混合使用docker,不能把鸡蛋放到一个篮子里,如果docker报了一个大bug,所有容器都宕掉了,怎么办?

作为一个合格的架构师要考虑到不可能的可能。还是那句话,不能把鸡蛋放到一个篮子里。


那么docker改变了什么呢?

1、面向产品: 产品交付

2、面向开发: 简化环境配置

3、面向测试: 多版本测试

4、面向运维: 环境一致性

5、面向架构: 自动化扩容(微服务)


=================================分割线=====================================================

实战来了:

1、安装docker

1
[root@jixuege ~]# yum install docker

2、启动docker

1
[root@jixuege ~]# systemctl start docker

3、pull镜像

1
[root@jixuege ~]# docker pull centos

4、查看镜像

1
2
3
4
[root@jixuege ~]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/centos                    latest              60e65a8e4030        6 weeks ago         196.6 MB
属于哪个仓库                         标签               唯一ID               创建时间              大小

镜像怎么来的?

可以自己导入一个,方法如下

导出镜像到/opt目录

1
2
3
[root@jixuege ~]# docker save centos >/opt/centos.tar.gz
[root@jixuege ~]# ll /opt/
-rw-r--r--  1 root root 204205056 Feb  5 16:09 centos.tar.gz

从/opt目录下导入镜像

1
[root@jixuege ~]# docker load < /opt/centos.tar.gz

这样就可以导入镜像了

5、如何删除一个镜像呢?

1
2
[root@jixuege ~]# docker rmi   ID号              
注意,如果镜像创建了容器,那么镜像不能被删除,如果想删除,需要加参数 -f 即      docker  rmi -f ID号


6、创建并启动第一个容器

1
2
[root@jixuege ~]# docker run centos /bin/echo "hehe" 
hehe

说明:

docker run 所有容器都使用这个参数     centos指的是镜像的名称,后面跟着是一个命令,启动一个容器执行了一个命令:echo "hehe"

运行完之后就退出了,没有为容器指定名字

7、查看一下刚才创建的容器:

1
2
3
4
[root@jixuege ~]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                     PORTS                                            NAMES
c2e9c96f6f9c        centos                     "/bin/echo hehe"         4 minutes ago       Exited (0) 4 minutes ago                                                    hungry_chandrasekhar
容器的ID             镜像                        命令                    创建时间           状态(退出)           端口没有                                          不给名字它自己起了一个名字


8、启动一个有名字的容器不让退出

1
2
3
4
5
6
[root@jixuege ~]# docker run --name mydocker -t -i centos /bin/bash
[root@a15b76fd966d /]
--name 起一个名字
-t   分配一个伪终端
-i     容器的标准输入为打开状态,这2个要一起使用
/bin/bash  执行一个命令,这个命令是/bin/bash

 启动容器是秒级的

9、查看

1
2
3
4
5
[root@a15b76fd966d /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.1  11772  1868 ?        Ss   03:55   0:00 /bin/bash
root         14  0.0  0.1  35888  1472 ?        R+   03:57   0:00 ps aux
[root@a15b76fd966d /]#

  这个容器里面只有一个进程就是/bin/bash,也就是说这个容器只运行了一个进程,这个进程是在启动容器的时候让它执行的。

我们在主机上查看,运行的容器

1
2
3
[root@jixuege ~]# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                            NAMES
a15b76fd966d        centos                     "/bin/bash"              2 minutes ago       Up 2 minutes                                                         mydocker

容器的主机名和容器的ID是一样的。

当执行docker run的时候,它会在本地检查有没有centos这个镜像,如果没有就在dockerhub上去下载一个,有的话就直接启动,利用这个镜像启动容器。

10、退出容器

1
2
[root@a15b76fd966d /]# exit
exit

退出以后,容器就自动终止了。

11、镜像的管理

搜索镜像:

docker search  +镜像名(centos 、 nginx 等)

1
2
3
4
5
6
7
[root@jixuege ~]# docker search centos
INDEX       NAME                                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/centos                          The official build of CentOS.                   1902      [OK]       
docker.io   docker.io/jdeathe/centos-ssh              CentOS-6 6.7 x86_64 / EPEL/IUS Repos / Ope...   14                   [OK]
docker.io   docker.io/jdeathe/centos-ssh-apache-php   CentOS-6 6.7 x86_64 / Apache / PHP / PHP M...   11                   [OK]
docker.io   docker.io/million12/centos-supervisor     Base CentOS-7 with supervisord launcher, h...   9                    [OK]
docker.io   docker.io/blalor/centos                   Bare-bones base CentOS 6.5 image                8                    [OK]


获取镜像:

docker pull  + 镜像的name

1
2
3
[root@jixuege ~]# docker pull  docker.io/jdeathe/centos-ssh-apache-php
Using default tag: latest
Trying to pull repository docker.io/jdeathe/centos-ssh-apache-php ... latest: Pulling from jdeathe/centos-ssh-apache-php

注意,这个地方pull的后面需要接整个镜像的name,如果有标签需要加上标签,不加的话默认是Using default tag: latest


查看镜像:

docker images

1
2
3
[root@jixuege ~]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
test/mynginx                        v4                  109dc6393163        5 weeks ago         350.9 MB


删除镜像:

docker rmi  +镜像ID


启动容器:

docker run --name test -it  centos  /bin/bash


查看容器:

docker ps     查看运行的容器

docker ps -a 查看所有容器包括已停止的

docker start ID  把停止的容器启动起来

进入容器呢?

docker attach +容器的ID    这样就进入到容器里面了

举例:

1
2
3
[root@jixuege ~]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                         PORTS                                            NAMES
a15b76fd966d        centos                     "/bin/bash"              56 minutes ago      Exited (0) 50 minutes ago                                                       mydocker

这个是已停止的容器,那么启动容器

1
2
[root@jixuege ~]# docker start a15b76fd966d
a15b76fd966d

进入容器

1
2
3
4
5
[root@jixuege ~]# docker attach a15b76fd966d
[root@a15b76fd966d /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.1  11772  1860 ?        Ss   04:53   0:00 /bin/bash
root         15  1.0  0.1  35888  1468 ?        R+   04:54   0:00 ps aux

现在如果我exit出去,容器就停止了。这个不是我们想看到的,为什么呢?因为你退出了bash

所以说容器适合单进程,比如说我起个nginx,我就只起一个nginx,容器的理念就是单进程,可以当虚拟机使用,但是理念不是一个虚拟机。


另外一种方法进入容器exit不让其退出就是nsenter,如果没有需要安装util-linux,这个可以访问另一个进程的名字空间namespace。

我们需要知道进程的PID

启动容器,因为一个静止的容器不会有PID

1
2
[root@jixuege ~]# docker start a15b76fd966d 
a15b76fd966d

查看启动的容器

1
2
3
[root@jixuege ~]# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                            NAMES
a15b76fd966d        centos                     "/bin/bash"              About an hour ago   Up 2 seconds                                                         mydocker

查看PID

1
2
[root@jixuege ~]# docker inspect --format "{{.State.Pid}}" a15b76fd966d 
31106

进入容器

1
2
[root@jixuege ~]# nsenter -t 31106 -u -i -n -p
[root@a15b76fd966d ~]#

退出,发现依旧在运行

1
2
3
4
5
[root@a15b76fd966d ~]# exit
logout
[root@jixuege ~]# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                            NAMES
a15b76fd966d        centos                     "/bin/bash"              About an hour ago   Up 3 minutes                                                         mydocker

写成脚本,传PID就可以进入

1
2
3
4
5
6
7
8
9
10
[root@jixuege ~]# cat ns.sh 
#!/bin/bash
PID=$(docker inspect --format "{{.State.Pid}}" $1)
nsenter -t $PID -u -i -n -p
[root@jixuege ~]# chmod +x ns.sh 
[root@jixuege ~]# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                            NAMES
a15b76fd966d        centos                     "/bin/bash"              About an hour ago   Up 6 minutes                                                         mydocker
[root@jixuege ~]# ./ns.sh a15b76fd966d
[root@a15b76fd966d ~]#

比较推荐进入docker容器的方式。


如何删除容器呢?

docker rm ID      删除已停止运行的容器

docker rm -f ID     强行删除正在运行的容器


创建容器,容器退出自动删除

1
docker run --rm centos /bin/echo "hehe"


删除正在运行的容器

1
[root@jixuege ~]# docker kill $(docker ps -a -q)


还有2种进入容器的方式

docker exec |docker attach  这2种方式不推荐,还是推荐使用nsenter -t $PID -u -i -n -p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Usage:
 nsenter [options] <program> [args...]
Options:
 -t, --target <pid>     target process to get namespaces from  后面接PID
 -m, --mount [=<file>]  enter mount namespace
 -u, --uts   [=<file>]  enter UTS namespace (hostname etc)  
 -i, --ipc   [=<file>]  enter System V IPC namespace
 -n, --net   [=<file>]  enter network namespace
 -p, --pid   [=<file>]  enter pid namespace
 -r, --root  [=<dir>]   set the root directory
 -w, --wd    [=<dir>]   set the working directory
 -F, --no-fork          do not fork before exec'ing <program>
 -h, --help     display this help and exit
 -V, --version  output version information and exit
For more details see nsenter(1).


12、docker的网络访问

默认是帮忙做了一个映射,有个桥接网卡,帮忙做端口映射


1
2
3
[root@jixuege ~]# brctl show
bridge namebridge idSTP enabledinterfaces
docker08000.024241919583no

让容器里的某一个端口对外,映射有两种方式,随机映射和指定端口映射

1
2
3
4
5
6
[root@jixuege ~]# docker run -d -P nginx
99ce23e7ef812403fc46c797fb4ac1631eacd34a335d59588112160d716d4132
[root@jixuege ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
99ce23e7ef81        nginx               "nginx -g 'daemon off"   16 seconds ago      Up 14 seconds       0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp   berserk_kowalevski
[root@jixuege ~]#

访问以下

2.png

查看访问日志

1
2
3
4
[root@jixuege ~]# docker logs 99ce23e7ef81
192.168.56.1 - - [06/Feb/2016:05:31:54 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36" "-"
2016/02/06 05:31:54 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.56.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.56.123:32769", referrer: "http://192.168.56.123:32769/"
192.168.56.1 - - [06/Feb/2016:05:31:54 +0000] "GET /favicon.ico HTTP/1.1" 404 570 "http://192.168.56.123:32769/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36" "-"


指定端口映射: 参数-p

再启动一个nginx,81对应容器里面的80

1
2
3
4
5
[root@jixuege ~]# docker run -d -p 81:80 nginx
74dd6739a63009777113f7953a3da4e912eab33125ba0d06d8c2998d51869743
[root@jixuege ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
74dd6739a630        nginx               "nginx -g 'daemon off"   3 seconds ago       Up 2 seconds        443/tcp, 0.0.0.0:81->80/tcp                     berserk_wozniak

访问一下:

2.png

这个就是docker的网络访问了。


13、docker数据管理

docker的数据存储默认有2种方式来管理容器中的数据

1)数据卷:一个特殊的容器,所有其他的docker都可以连到这个容器,共享一个data,类似于搞一个NFS

启动一个看看

1
2
3
[root@jixuege ~]# docker run -it --name volume-test1 -v /data/ centos
[root@f7635bd01032 /]# ll /data/
total 0

怎么查看数据放在哪了呢?

#列出所有的信息

[root@jixuege ~]# docker inspect  f7635bd01032

找到下面这个Source

1
2
3
4
5
6
7
8
9
10
 "Mounts": [
        {
            "Name""ede625a5f6da0417ec616b30368e6b7d2181f89f882d9c7f7824dfe74c9acc5e",
            "Source""/var/lib/docker/volumes/ede625a5f6da0417ec616b30368e6b7d2181f89f882d9c7f7824dfe74c9acc5e/_data",
            "Destination""/data",
            "Driver""local",
            "Mode""",
            "RW"true
        }
    ],

进入到这个目录下,创建一个文件,然后在容器的/data/目录下查看看是否有这个文件

1
2
3
4
[root@jixuege ~]# cd /var/lib/docker/volumes/ede625a5f6da0417ec616b30368e6b7d2181f89f882d9c7f7824dfe74c9acc5e/_data
[root@jixuege _data]# touch test
[root@jixuege _data]# ls
test

去容器下查看并验证

1
2
3
[root@f7635bd01032 /]# ll /data/
total 0
-rw-r--r-- 1 root root 0 Feb  6 11:48 test

说明:上面的命令是起一个容器,然后呢,把容器的/data/目录挂载到物理机的source下的目录下,这样我在物理机上创建的文件都可以直接同步到容器里面。


#还可以,启动一个容器,挂载到物理机的指定目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@jixuege ~]# docker run -it -v /opt/:/opt centos
[root@eeb1353b4cae /]# ll /opt/
total 1200816
-rw-r--r--  1 root root        33 Jan 12 09:52 a.sh
drwxr-xr-x  9 root root       149 Dec 29 02:36 apache-tomcat-8.0.30
-rw-r--r--  1 root root   9150593 Dec  1 22:56 apache-tomcat-8.0.30.tar.gz
-rw-r--r--  1 root root 204205056 Feb  5 08:09 centos.tar.gz
drwxr-xr-x  3 root root        18 Dec 29 13:21 dockerfile
-rw-r--r--  1 root root         0 Dec 29 12:12 hehe
-rw-r--r--  1 root root 181260798 Dec 29 03:02 jdk-8u65-linux-x64.tar.gz
drwxr-xr-x  8   10  143      4096 Oct  7 00:29 jdk1.8.0_65
-rw-r--r--  1 root root  18082304 Jan  4 02:10 microbox_etcd.tar.gz
drwxr-xr-x  2 root root        61 Dec 30 09:15 nginx
-rw-r--r--  1 root root 442205184 Jan 13 11:36 registry.tar.gz
-rw-r--r--  1 root root 188601344 Jan  4 01:41 rethinkdb.tar.gz
drwxr-xr-x. 2 root root         6 Oct 29  2014 rh
-rw-r--r--  1 root root  61221888 Jan  7 16:57 shipyard.tar.gz
-rw-r--r--  1 root root 107682084 Jan  8 02:42 shipyard.zip
-rw-r--r--  1 root root  17193472 Jan  7 16:37 swarm.tar.gz
-rw-r--r--  1 root root        12 Jan 12 09:52 test.sh

可以把物理机 的一个目录挂到/data/目录下,适用于什么场景呢?

比如说我开发写好了代码在物理机的/data/目录,我可以把这个目录挂载到一台nginx的容器,然后呢吧容器里的nginx的路径指定到挂载点即可。


#还可以挂载单个文件

1
2
3
[root@jixuege ~]# docker run -it -v ~/.bash_history:/.bash_histroy centos
[root@df1ddc3ee603 /]# ll .bash_histroy 
-rw------- 1 root root 12146 Feb  6 05:01 .bash_histroy


#挂载并指定权限为只读

1
2
[root@jixuege ~]# docker run -it -v /opt:/opt:ro centos
[root@963470b40e76 /]# ll /opt/

这样进入容器之后不能修改文件,只能读

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页