1.Docker介绍

1.1Docker是什么?

       Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。    

       Docker 是 Docker.Inc 公司开源的一个基于 LXC技术之上构建的Container容器引擎, 源代码托管在 GitHub 上, 基于Go语言并遵从Apache2.0协议开源。 Docker在2014年6月召开DockerConf 2014技术大会吸引了IBM、Google、RedHat等业界知名公司的关注和技术支持,无论是从 GitHub 上的代码活跃度,还是Redhat宣布在RHEL7中正式支持Docker, 都给业界一个信号,这是一项创新型的技术解决方案。 就连 Google 公司的 Compute Engine 也支持 docker 在其之上运行, 国内“BAT”先锋企业百度Baidu App Engine(BAE)平台也是以Docker作为其PaaS云基础。

       一款开源软件能否在商业上成功,很大程度上依赖三件事 - 成功的 user case(用例), 活跃的社区和一个好故事。 dotCloud 自家的 PaaS 产品建立在docker之上,长期维护且有大量的用户,社区也十分活跃,接下来看看docker的故事。

       Docker产生的目的就是为了解决以下问题:

       环境管理复杂 - 从各种OS到各种中间件到各种app, 一款产品能够成功作为开发者需要关心的东西太多,且难于管理,这个问题几乎在所有现代IT相关行业都需要面对。

       云计算时代的到来 - AWS的成功, 引导开发者将应用转移到 cloud 上, 解决了硬件管理的问题,然而中间件相关的问题依然存在 (所以openstack HEAT和 AWS cloudformation 都着力解决这个问题)。开发者思路变化提供了可能性。

       虚拟化手段的变化 - cloud 时代采用标配硬件来降低成本,采用虚拟化手段来满足用户按需使用的需求以及保证可用性和隔离性。然而无论是KVM还是Xen在 docker 看来,都在浪费资源,因为用户需要的是高效运行环境而非OS, GuestOS既浪费资源又难于管理, 更加轻量级的LXC更加灵活和快速

       LXC的移动性 - LXC在 linux 2.6 的 kernel 里就已经存在了,但是其设计之初并非为云计算考虑的,缺少标准化的描述手段和容器的可迁移性,决定其构建出的环境难于迁移和标准化管理(相对于KVM之类image和snapshot的概念)。docker 就在这个问题上做出实质性的革新。这是docker最独特的地方。

    

       面对上述几个问题,docker设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后个标准化组件是用户的app)。这也就是基于docker的PaaS产品的原型。

1.2什么是Docker引擎?

       Docker Engine是一个主要组件的客户端 - 服务器应用程序::

    • 这是一种长期运行程序的服务器称为守护进程。

    • 一个REST API,它指定的程序可以用交谈的守护进程,并指示做什么用的接口。

    • 命令行界面(CLI)客户端。

Docker Engine Components Flow

       CLI中使用了Docker REST API来控制或通过脚本或直接CLI命令Docker守护进程交互。许多其他的Docker应用程序使用底层API和CLI的。

       守护程序创建和管理Docker对象。Docker对象包括图片,容器,网络,数据量,等等。

1.3Docker优缺点

    优点

       其基于LXC的轻量级虚拟化的特点,docker相比KVM之类最明显的特点就是启动快,资源占用小。因此对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku),构建自动化测试和持续集成环境,以及一切可以横向扩展的应用(尤其是需要快速启停来应对峰谷的web应用)。

       构建标准化的运行环境,现有的方案大多是在一个baseOS上运行一套puppet/chef,或者一个image文件,其缺点是前者需要base OS许多前提条件,后者几乎不可以修改(因为copy on write 的文件格式在运行时rootfs是read only的)。并且后者文件体积大,环境管理和版本控制本身也是一个问题。

       PaaS环境是不言而喻的,其设计之初和dotcloud的案例都是将其作为PaaS产品的环境基础。

       因为其标准化构建方法(buildfile)和良好的REST API,自动测试和持续集成/部署能够很好的集成进来。

因为LXC轻量级的特点,其启动快,而且docker能够只加载每个container变化的部分,这样资源占用小,能够在单机环境下与KVM之类的虚拟化方案相比能够更加快速和占用更少资源。

    局限

       Docker是基于Linux 64bit的,无法在Windows/Unix或32bit的Linux环境下使用。

       LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base的。

       隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库。

       网络管理相对简单,主要是基于namespace隔离。

       cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)

       docker对disk的管理比较有限

       container随着用户进程的停止而销毁,container中的log等用户数据不便收集。

      参考:博客

1.4Docker理念

        blob.png

        如上图所示:Build(构建)、ship (运输)、Run(运行)

  • 构建:docker认为一个东西我构建上了,放在某个地方就可以运行起来。可以用java来进行一个对比,JVM虚拟机,一次构建,拷贝到各种环境之后到处运行。但是呢,也有不同的地方,因为docker里面运行的是一个应用(apache、nginx、tomcat),它的构建是基于docker的镜像,可以基于这个镜像起任何的容器。

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

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

1.5Docker改变了什么?

  • 面向产品: 产品交付

  • 面向开发: 简化环境配置

  • 面向测试: 多版本测试

  • 面向运维: 环境一致性

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

1.6Docker能做什么?

  • 简化配置

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

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

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

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

  • 代码流水线管理

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

  • 开发效率

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

    openstack也可以做,给个虚拟镜像就完事。给个IP地址,用户密码SSH上去就完事。举个例子:这么对比来说,openstack效率更高,给开发每人一台虚拟机,把6080对外(NOVNCPROXY端口),这样开发在家都可以使用,虚拟机在远端,跟你是否在本地没有关系,但是docker不行,因为docker是启在本地。

  • 应用隔离

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

  • 整合服务器

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

  • debug能力

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

  • 多租户

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

  • 快速部署

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

2.Docker安装

2.1安装Docker的要求

        Docker需要64位的系统,而且内核最低要求是3.10版本。

[root@linux-node2 ~]# uname -a
Linux linux-node2.example.com 3.10.0-327.18.2.el7.x86_64 #1 SMP Thu May 12 11:03:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

2.2安装Docker

       安装Docker官方给了两种方法

  • 本地添加yum源,进行安装。

  • .使用curl命令进行安装。

       本次采用的是yum源的方法进行安装

         1.添加本地yum源

[root@linux-node2 ~]# tee /etc/yum.repos.d/docker.repo <<-'EOF'
> [dockerrepo]
> name=Docker Repository
> baseurl=https://yum.dockerproject.org/repo/main/centos/7/
> enabled=1
> gpgcheck=1
> gpgkey=https://yum.dockerproject.org/gpg
> EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg

       2.安装

[root@linux-node2 ~]# yum install docker -y

       3.启动和设置开机启动

[root@linux-node2 ~]# systemctl start docker
[root@linux-node2 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242eb1d4a6a       no
[root@linux-node2 ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@linux-node2 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2016-09-10 23:26:27 CST; 49s ago
     Docs: http://docs.docker.com
...................

        启动后会创建一个网桥,brctl show(安装yum install -y bridge-utils此命令的方法)进行查看。


 2.3Docker的Hello World

       很多语言学习之前都需要进行一个仪式,打印Hello World,既然都举行这个仪式,学习Docker也要举行这个仪式,打印Hello World。

       1.Docker镜像命令介绍

  • docker pull centos        #拉取镜像

  • docker images              #查看镜像

  • docker serach               #搜索镜像

  • docker rmi ID号            #删除镜像

  • docker load  < 镜像文件   #导入镜像

  • docker load  --input 镜像文件  #导入镜像

  • docker save -o 保存镜像文件名称  镜像文件  #本地保存镜像。

       2.下载一个CentOS的镜像

[root@linux-node2 ~]# docker pull centos
Using default tag: latest
Trying to pull repository docker.io/library/centos ... 
Pulling repository docker.io/library/centos
Network timed out while trying to connect to https://index.docker.io/v1/repositories/library/centos/images. You may want to check your internet connection or if you are behind a proxy.
Network timed out while trying to connect to https://index.docker.io/v1/repositories/library/centos/images. You may want to check your internet connection or if you are behind a proxy.

       国内网速不是很好,下载失败,只能本地导入了,如果你想用pull下载可以看这个网站:https://segmentfault.com/q/1010000006032930

       本地导入

[root@linux-node2 ~]# rz -y
rz waiting to receive.
 zmodem trl+C ȡ
  100%  199527 KB 7981 KB/s 00:00:25       0 Errorss
[root@linux-node2 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@linux-node2 ~]# docker load < centos.tar.gz 
[root@linux-node2 ~]# docker images
#仓库             版本                 ID号           时间               大小  
REPOSITORY          TAG                 IMAGE ID         CREATED               SIZE
docker.io/centos       latest               980e0e4c79ec        2 weeks ago           196.7 MB

       3.打印Hello World

[root@linux-node2 ~]# docker run centos /bin/echo 'hello world'
hello world

3.容器管理

        容器命令介绍

  • docker run nginx    #启动容器

    • --name:指定容器名,方便操作。

    • -P:映射随机端口。

    • -p:指定映射端口。

      • -p 81:80指定多个端口写法-p 81:80 -p 443:443。

    • -d:容器在后台运行,打印容器ID。

    • -t:分配一个伪终端。

    • -i:容器的标准输入为打开状态。

    • --rm:容器退出时,自动删除。

    • -u:指定用户。

  • docker rm PID    #删除容器

    • -f:强制删除使用中的容器。

  • docker stop nginx #停止容器

  • docker ps #查看容器

    • -a:查看所有容器包括停止的。

  • docker attach 容器名(ID):进入容器。(不推荐此种进入方法)

  • nsenter  -t PID -m -u -i -n -p :进入容器。(推荐)

    • 最好使用编写一个脚本,传参给ID或者name直接进入,然后增加执行权限(chmod +x 脚本名)

    #!/bin/bash
    # Use nsenter to acces docker 
    docker_in() {
      NAME_ID=$1
      PID=$(docker inspect -f "{{ .State.Pid }}" $NAME_ID )
      nsenter -t $PID -m -u -i -n -p
    }
    
    docker_in $1
  • docker run -it  nginx /bin/bash:启动容器并进入容器。

  • docker inspect -f "{{ .State.Pid }}"  ID号:获取PID。

3.1网络映射

    随机映射

       1.安装nginx镜像

[root@linux-node2 ~]# docker load --input nginx.tar.gz 
[root@linux-node2 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              980e0e4c79ec              3 days ago          196.7 MB
docker.io/nginx     latest              4efb2fcdb1ab              2 weeks ago         183.4 MB

       2.启动容器

[root@linux-node2 ~]# docker run -P -d --name nginxtest nginx
823b186b79c22345ec1511198f46103766dcbba0b50f0650fd09e5f7ef608e32
[root@linux-node2 ~]# netstat -lnutp|grep docker
tcp6       0      0 :::10000                :::*                    LISTEN      26705/docker-proxy  
tcp6       0      0 :::10001                :::*                    LISTEN      26712/docker-proxy

       3.查看映射在那个端口并测试

[root@linux-node2 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                                           NAMES
823b186b79c2        nginx               "nginx -g 'daemon off"   About a minute ago   Up About a minute   0.0.0.0:10001->80/tcp, 0.0.0.0:10000->443/tcp   nginxtest
[root@linux-node2 ~]# curl -I 192.168.56.12:10001
HTTP/1.1 200 OK
Server: nginx/1.11.3
Date: Sat, 10 Sep 2016 17:18:27 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Jul 2016 14:54:48 GMT
Connection: keep-alive
ETag: "579779b8-264"
Accept-Ranges: bytes

blob.png

    指定端口映射

        1.启动容器

[root@linux-node2 ~]# docker run -p 88:80 -d --name nginxtest2 nginx
3180b8925cc0cc2b5fdf49515dc1001228b069f4a684623a6e64d3410015462a
[root@linux-node2 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
3180b8925cc0        nginx               "nginx -g 'daemon off"           54 seconds ago      Up 52 seconds       443/tcp, 0.0.0.0:88->80/tcp                     nginxtest2
823b186b79c2        nginx               "nginx -g 'daemon off"           6 minutes ago       Up 6 minutes        0.0.0.0:10001->80/tcp, 0.0.0.0:10000->443/tcp   nginxtest

       2.查看测试

[root@linux-node2 ~]# netstat -lnutp|grep -w 88
tcp6       0      0 :::88                   :::*                    LISTEN      26820/docker-proxy  
[root@linux-node2 ~]# curl -I 192.168.56.12:88
HTTP/1.1 200 OK
Server: nginx/1.11.3
Date: Sat, 10 Sep 2016 17:23:38 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Jul 2016 14:54:48 GMT
Connection: keep-alive
ETag: "579779b8-264"
Accept-Ranges: bytes

blob.png

3.2数据管理

    数据卷

       1.启动容器

[root@linux-node2 ~]# mkdir /data/docker
[root@linux-node2 ~]# docker run -d --name data-test -v /data/docker/:/data nginx
4d8e0cb8ef89cb1e04469aea79eda844d94d3e9140f8d7208754db092502706a
[root@linux-node2 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
4d8e0cb8ef89        nginx               "nginx -g 'daemon off"   4 seconds ago       Up 2 seconds        80/tcp, 443/tcp     data-test

       2.进入容器测试

[root@linux-node2 ~]# ./docker_in.sh  4d8e0cb8ef89
root@4d8e0cb8ef89:/# echo "test nginx data" >/data/test.log
root@4d8e0cb8ef89:/# exit
logout

       3.查看数据

[root@linux-node2 ~]# cat /data/docker/test.log 
test nginx data

       上边这个是指定数据目录,如果指定会存放那里?

       使用如下命令可以进行查看

docker -inspect -f {{ ,Mounts }} ID(name)

     数据卷容器

        1.启动容器

[root@linux-node2 ~]# docker run -d --name data-test-2 -v /data/docker/:/data nginx
019abd2073f62c3420eb2e456c85a45379b34301831ead07f0397cff387ab108
[root@linux-node2 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS         PORTS               NAMES
019abd2073f6        nginx               "nginx -g 'daemon off"   7 seconds ago       Up 6 seconds        80/tcp, 443/tcp     data-test-2
4d8e0cb8ef89        nginx               "nginx -g 'daemon off"   5 minutes ago       Up 5 minutes        80/tcp, 443/tcp     data-test

        2.查看数据

[root@linux-node2 ~]# ./docker_in.sh data-test-2
root@019abd2073f6:/# cat /data/test.log 
test nginx data

3.3手动构建容器

       1.启动容器

[root@linux-node2 ~]# docker run --name mynginx -it centos

       2.安装nginx

[root@10a5563b32a8 /]# rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
Retrieving http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
warning: /var/tmp/rpm-tmp.6sEKDZ: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:epel-release-7-8                 ################################# [100%]
[root@10a5563b32a8 /]# yum install nginx -y && yum clean all

        3.更改nginx配置文件

[root@10a5563b32a8 /]# echo "daemon off;" >>/etc/nginx/nginx.conf
[root@10a5563b32a8 /]# exit
exit

        4.提交制作好的容器

[root@linux-node2 ~]# docker commit  -m "My Nginx" 10a5563b32a8 stanley/mynginx:v1
sha256:5ccf41e2ea9ad4ba587252db2c5a0cace7ed7a93d0ce824fae45db4466fefe4a
[root@linux-node2 ~]# docker images
REPOSITORY         TAG                 IMAGE ID            CREATED           SIZE
stanley/mynginx     v1                  5ccf41e2ea9a        8 seconds ago       261.9 MB
docker.io/centos    latest                980e0e4c79ec        3 days ago         196.7 MB
docker.io/nginx     latest               4efb2fcdb1ab        2 weeks ago         183.4 MB

        5.启动测试制作的镜像

[root@linux-node2 ~]# docker run --name mynginxv1 -d -p 81:80 stanley/mynginx:v1 nginx
17d430f89326a22aa3e1e35d6b4e2355b50b0daca69c1a21bd511564c0438612
[root@linux-node2 ~]# curl -I localhost:81
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Sat, 10 Sep 2016 18:16:59 GMT
Content-Type: text/html
Content-Length: 3700
Last-Modified: Sat, 02 Jul 2016 19:41:19 GMT
Connection: keep-alive
ETag: "577818df-e74"
Accept-Ranges: bytes

blob.png

3.3编写Dockerfile制作容器


       1.编写Dockerfile

[root@linux-node2 Docker]# cat Dockerfile 
# This Dockerfile
# Base image
FROM centos
# Maintainer
MAINTAINER test.test xxx@mail.com
#Commands 
RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
RUN yum install nginx -y && yum clean all
RUN echo "daemon off;" >>/etc/nginx/nginx.conf
ADD index.html /usr/share/nginx/html/index.html
EXPOSE 82
CMD ["nginx"]

       2.执行Dockerfile文件

[root@linux-node2 Docker]# echo "hehe" >index.html
[root@linux-node2 Docker]#  docker build -t stanley/mynginx:v2 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM centos
 ---> 980e0e4c79ec
Step 2 : MAINTAINER test.test xxx@mail.com
 ---> Running in fd1095349bfe
 ---> 12cd72affb73
Removing intermediate container fd1095349bfe
Step 3 : RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
 ---> Running in cf19679b22ba
 ................

       3.启动容器测试

[root@linux-node2 Docker]# curl 192.168.56.12:82
hehe
[root@linux-node2 Docker]# curl -I 192.168.56.12:82
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Sun, 11 Sep 2016 05:18:29 GMT
Content-Type: text/html
Content-Length: 5
Last-Modified: Sun, 11 Sep 2016 05:17:26 GMT
Connection: keep-alive
ETag: "57d4e8e6-5"
Accept-Ranges: bytes

blob.png




     详细请参考:官方网站 InfoQ 赵班长Dockerfile编写 鸡血哥