这段时间在看docker,想弄明白它究竟有什么功能,能用在什么地方,然后就去官网上看了下它的用户指南,按照其内容自己整理了一份笔记,其中可能会有错误,望大家多多指教。

    docker用户指南网址:http://docs.docker.com/userguide/


=====1.在一个docker容器中运行应用=====

1)在容器中运行一次输出“Hello world”

docker run ubuntu:14.04 /bin/echo 'Hello world'

     #docker run 就是运行容器

     #之后需要指定一个p_w_picpath,这里是ubuntu:14.04

     #若本地有p_w_picpath就直接用,若docker找不到就到Docker Hub上下载一个。

     #之后就是在容器里运行的命令了,输出Hello world


2)交互式的容器

docker run -t -i ubuntu:14.04 /bin/bash         #进入容器的bash

     #-t     表示在新的容器里分配一个虚拟终端

     #-i     表示允许我们用一个交互式的连接

     

3)后台运行容器 

docker run -d ubuntu:14.04 /bin/sh -c 
"while true; do echo hello world; sleep 1; done"

     1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147    #返回该容器的id。

   #-d     表示让docker运行一个容器并放到后台执行。   

  docker ps          #返回正在运行的容器以及其运行的应用等信息

 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1e5535038e28 ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage

#container id就是容器的短id;ports name是自动生成的该容器的名字,只要开启一个容器,docker就会给它去一个名字。

docker logs insane_babbage    #查看容器里面的标准输出,后面跟上容器名

     hello world

     hello world

     hello world

     . . .     

docker stop insan_babbage    #停止运行的docker容器,成功的话会返回该容器的名字




===========2.docker容器============


1)docker命令

     命令格式:[sudo] docker [flags] [command] [arguments] ..

     eg.

docker run -i -t ubuntu /bin/bash

     查看docker版本

docker version    #docker client和docker server都会有,还有go语言版本,以及git的版本

   

2)查看docker客户端的功能

 docker

 Usage: docker [OPTIONS] COMMAND [arg...]

 -H=[unix:///var/run/docker.sock]: tcp://host:port to bind/connect to or unix://path/to/socket to use


A self-sufficient runtime for linux containers.


Commands:

    attach    Attach to a running container

    build     Build an p_w_picpath from a Dockerfile

    commit    Create a new p_w_picpath from a container's changes

    cp        Copy files/folders from the containers filesystem to the host path

    diff      Inspect changes on a container's filesystem

    events    Get real time events from the server

    export    Stream the contents of a container as a tar archive

    history   Show the history of an p_w_picpath

    p_w_picpaths    List p_w_picpaths

    import    Create a new filesystem p_w_picpath from the contents of a tarball

    info      Display system-wide information

    inspect   Return low-level information on a container

    kill      Kill a running container

    load      Load an p_w_picpath from a tar archive

    login     Register or Login to the docker registry server

    logs      Fetch the logs of a container

    port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT

    pause     Pause all processes within a container

    ps        List containers

    pull      Pull an p_w_picpath or a repository from the docker registry server

    push      Push an p_w_picpath or a repository to the docker registry server

    restart   Restart a running container

    rm        Remove one or more containers

    rmi       Remove one or more p_w_picpaths

    run       Run a command in a new container

    save      Save an p_w_picpath to a tar archive

    search    Search for an p_w_picpath in the docker index

    start     Start a stopped container

    stop      Stop a running container

    tag       Tag an p_w_picpath into a repository

    top       Lookup the running processes of a container

    unpause   Unpause a paused container

    version   Show the docker version information

    wait      Block until a container stops, then print its exit code


3)查看docker命令的用法

 dicker command [--help]


4)在docker里面运行一个网页应用

docker run -d -P training/webapp python app.py

     -d     后台运行一个容器

     -P     从容器映射所有需要的端口到宿主机

     #training/webapp是一个已经创建好的包含一个简单的python flask web 应用的容器,其开放5000端口供客户端访问

     #由于本地没有,自行从docker hub上下载,所以执行这条命令需要保证能够联网


5)查看web应用容器

 docker ps -l

CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                     NAMES
2a2243aabeef        training/webapp:latest   python app.py       9 seconds ago       Up 8 seconds        0.0.0.0:49154->5000/tcp   trusting_archimedes 

     -l     返回最近一个容器的详细信息

     -a     查看已经停止的容器的信息


     其中ports部分,是在我们通过docker run的-P选项来映射p_w_picpath中开启的端口到宿主机上。这里是将docker容器中的开放端口(5000端口)映射到了宿主机的49154端口。

     spacer.gifwKiom1PF5ifzKXkPAACxMn36xFE941.jpg

     网络端口映射在docker中是可配置的。-P在这里其实等价于-p 5000(这个应用就是开放5000端口),使得容器中的5000端口映射到宿主机上的49000~49900端口上。在run的时候也可以直接使用-p选项来映射:

 docker run -d -p 5001:5000 training/webapp python app.py

     这里就是将另一个容器的5000端口映射到宿主机的5001端口。

wKioL1PF51uAnGmmAACmqDoEqq8127.jpg

                    注:访问的是另一个容器的5000端口


   

6)快速查看网络端口

     docker port [name|ID] 容器端口

     eg.

docker port jolly_fermi 5000

          0.0.0.0:49200


7)查看web应用的日志

     docker logs [-f] [name|ID]

     -f     查看容器的标准输出

docker logs -f jolly_fermi

     * Running on http://0.0.0.0:5000/
     192.168.125.1 - - [09/Jul/2014 11:50:47] "GET /favicon.ico HTTP/1.1" 404 -
     192.168.125.1 - - [09/Jul/2014 11:50:47] "GET / HTTP/1.1" 200 -
     192.168.125.1 - - [09/Jul/2014 11:50:47] "GET / HTTP/1.1" 200 -


8)查看web应用容器的进程

     docker top [name|ID]

     eg.

docker top jolly_fermi

UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                2338                1173                0                   19:50               ?                   00:00:02            python app.py


9)检查web应用容器配置

docker inspect jolly_fermi
[{
    "Args": [
        "app.py"
    ],
    "Config": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "python",
            "app.py"

          ...

     也可以指定一个元素来查看

 docker inspect -f '{{ .Config.Cmd }}' jolly_fermi

     [python app.py]


10)停止web应用容器

  docker stop jolly_fermi


11)重启web应用容器

  docker start jolly_fermi

     #docker attach jolly_fermi,若该容器可以进入的话,这句就是连到容器里面。


12)删除web应用容器

     docker rm jolly_fermi


=======3.docker镜像(p_w_picpaths)=======


管理和使用本地的docker镜像

创建一个基本的镜像

上传镜像到docker hub


1)列出本地镜像  

docker p_w_picpaths

     REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

       centos                    latest              0c752394b855        4 weeks ago         124.1 MB
       training/webapp      latest              31fa814ba25a        5 weeks ago         278.6 MB

     这些都是从docker hub上下载的

     每个repository都可能有多个不同的镜像,如centos:6.5,centos:6.4。这些都是取决于在pull镜像的时候所下载的镜像。

     所以在运行一个镜像的时候需要加上后面的TAG标签,如:

 docker run -t -u ubuntu:14.04 /bin/bash

     若不添加这个标签,docker就是用latest这个标签的镜像。


2)获取一个新的镜像

     docker pull 镜像名

     eg.

docker pull ubuntu


3)找镜像

     (1)可以直接上官网找

spacer.gifwKioL1PF6ALxmWMbAAFC8Shl1Hs552.jpg

     (2)通过命令行来找

     docker search 镜像名

     eg.

docker search sinatra
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
training/sinatra                       Sinatra training p_w_picpath                          0                    [OK]
marceldegraaf/sinatra                  Sinatra test app                                0
mattwarren/docker-sinatra-demo                                                         0                    [OK]
luisbebop/docker-sinatra-hello-world                                                   0                    [OK]
bmorearty/handson-sinatra              handson-ruby + Sinatra for Hands on with D...   0
subwiz/sinatra                                                                         0
bmorearty/sinatra                                                                      0. . .

#列表中有名字、描述、星值(类似“赞”)、官方、自动创建(可以去扩充)。


4)从docker hub上拖“我们”的镜像

 docker pull training/sinatra

     然后团队就可以用自己的镜像了

docker run -t -i training/sinatra


5)创建我们自己的镜像

     下载的镜像可能不能完全满足自身的需要,需要做一些改动。有两个方法可以更新和创建镜像

     (1)通过更新容器并同步到一个镜像中

     (2)通过Dockerfile来指定创建镜像


6)更新并提交一个镜像(5)的方法一)

     (1)通过该镜像创建一个容器      

docker run -t -i centos /bin/bash
    bash-4.1#

          在这个镜像没有标出其容器的ID,可以通过docker ps查看到是08b6d2e3c87e

     (2)在容器里通过yum安装vim和httpd并退出容器

    yum -y install httpd vim
    exit

#这里通过centos的base的repo成功联网安装。

很好奇docker 的容器网络设置,后来发现,docker的容器使用的是nat的方法,docker生成容器的同时,宿主机上会创建与容器联通的一个虚拟网卡,然后docker 的容器就可以通过这个网卡来联网了。类似于vmware的nat。

               宿主机上的操作:

               [root@localhost ~]# ifconfig

          docker0   Link encap:Ethernet  HWaddr 46:D4:FB:67:3B:36            

          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0

          inet6 addr: fe80::5817:1ff:fe25:615d/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:13852 errors:0 dropped:0 overruns:0 frame:0

          TX packets:23720 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:565006 (551.7 KiB)  TX bytes:28907343 (27.5 MiB)

          ...

               docker容器:

               bash-4.1# traceroute www.baidu.com

          bash-4.1# traceroute www.baidu.com

traceroute to www.baidu.com (180.97.33.71), 30 hops max, 60 byte packets
1  172.17.42.1 (172.17.42.1)  0.040 ms  0.012 ms  0.010 ms
2  192.168.125.2 (192.168.125.2)  0.108 ms  0.080 ms  0.077 ms
3  * * *
4  * * *

       (3)现在已经有了这个与基本的镜像不同的容器,通过commit来创建镜像

docker commit -m="Added vim and httpd" -a="liuling"  
08b6d2e3c87e myown/centos:v1

          -m     描述信息

          -a      操作者

          后面跟容器的id,以及镜像的标签。

          其中myown是只用户,centos是镜像名,后面的v2是版本

        (4)查看刚才建立的镜像

docker p_w_picpaths
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
myown/centos        v1                  1ab425143ef8        3 minutes ago       260.3 MB

          

7)通过Dockerfile创建镜像(从头做一个新的镜像)

mkdir centos
cd centos
vi Dockerfile

# make /data directory and yum install vsftpd

FROM myown/centos:v1

MAINTAINER liuling

RUN mkdir /data

RUN yum -y install vsftpd

       

      

docker build -t="myown/centos:v2" .    #docker build -t=“镜像名” dockerfile的路径,注意这里有一个“.”

Sending build context to Docker daemon  2.56 kB

Sending build context to Docker daemon 

Step 0 : FROM myown/centos:v1

 ---> 1ab425143ef8

Step 1 : MAINTAINER liuling

 ---> Using cache

 ---> b977f42fb08c

Step 2 : RUN mkdir /data

 ---> Using cache

 ---> 80d492289b95

Step 3 : RUN yum -y install vsftpd

 ---> Running in a742917e9b67

Loaded plugins: fastestmirror

Loading mirror speeds from cached hostfile

 * base: centos.ustc.edu.cn

...

Complete!

 ---> 14f9e7b5be23

Removing intermediate container a742917e9b67

Successfully built 14f9e7b5be23

      这里是使用build命令,-t指定镜像归属/名:标签,后面通过"."来指定Dockerfile的所在路径。

     通过Dockerfile创建文件,首先发送给docker daemon。其实就是建立一个容器,执行一条命令,然后commit出一个镜像,再使用这个镜像建立一个容器,再执行一条命令,再commint出一个镜像。最后命令执行完毕,commit出最后一个镜像,就将前面所有过渡用的容器删除。

docker p_w_picpaths

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

myown/centos        v2                  14f9e7b5be23        2 minutes ago       292.8 MB


8)设置镜像的标签(版本)

     docker tag [p_w_picpathID] [username]/[repository name]:[new tag]

     eg.

     docker tag 14f9e7b5be23 myown/centos:v3
     docker p_w_picpaths
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
myown/centos        v2                  14f9e7b5be23        36 minutes ago      292.8 MB
myown/centos        v3                  14f9e7b5be23        36 minutes ago      292.8 MB

     这里就给myown/centos:v2添加了一个新的标签。(个人有点觉得像一个不同标签名的快捷方式0.0)


9)将镜像上传到Docker Hub,分享给其他人

    docker push myown/centos


10)删除本地的镜像

docker rmi myown/centos:v3

     Untagged: myown/centos:v3

     #由于这个是添加的标签,因此会有untagged,即取消标签

docker rmi myown/centos:v2
Error: Conflict, cannot delete d47258e47dc3 because the container bae61e4726e4 is using it (docker untagged the p_w_picpath), use -f to force
2014/07/10 18:47:59 Error: failed to remove one or more p_w_picpaths

      #若该镜像上面已经创建了容器,是不能够直接删除的,需要先删除容器

docker rm bae61e4726e4

bae61e4726e4

#由于第一次删除的时候虽然没有成功,但是名字和tag已经没了,就只有通过id来删除了。

docker rmi 14f9e7b5be2

       Deleted: d47258e47dc3310ab857c44a818c0112a2784674b5dc9f3dbd3075db141322a1

Deleted: c8d2bc86f41e11e529e204af5f47876d5a7f72cbcfd8af00a6910af375858e02

Deleted: eaee52520045a1e3d39f260bd5d7fe40fa750fab5e541269deae6bdea4a40d73




=======4.将容器连接在一起=======


1)网络端口映射

docker run -d -P training/webapp pyton app.py

     #使用-P则表示将容器内的端口随机映射到宿主机端口(49000~49900)。

     注:容器中是有一个内网以及内网端口(可以通过docker inspect来查看容器的ip地址)。

     可以通过docker ps 来查看端口映射“宿主机端口->容器端口”

docker ps training/webapp

CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                     NAMES

b7b1263fa1f7        training/webapp:latest   python app.py       10 seconds ago      Up 8 seconds        0.0.0.0:49153->5000/tcp   sick_nobel

     

     通过-p指定端口映射规则

docker run -d -p 49000:5000 training/webapp python app.py

     #将容器的5000端口与宿主机的49000端口映射出去,但这并不是一个好方法,因为一个-p只能让一个容器使用一个端口,而-P则是使用将容器的所有开放端口映射出去。


     上面两种方法都是开发端口给所有用户(所有能连到该host的用户都可以访问),通过-p还可以指定只允许本地(宿主host)访问端口49000来访问web应用。

docker run -d -p 127.0.0.1:49000:5000 training/webapp python app.py

     #这里的127.0.0.1也可以改成localhost

 elinks --dump 127.0.0.1:49000  #宿主机上测试

        Hello world!


     也可以不指定宿主机的端口让其随机选择

     docker run -d -p 127.0.0.1::5000 training/webapp python app.py
     docker ps
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                       NAMES
ad644d473938        training/webapp:latest   python app.py       4 seconds ago       Up 3 seconds        127.0.0.1:49155->5000/tcp   determined_samme


     还可以指定使用udp端口

     docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
     docker ps
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                                NAMES
33a5ce0d825e        training/webapp:latest   python app.py       3 seconds ago       Up 3 seconds        5000/tcp, 127.0.0.1:5000->5000/udp   naughty_yonath

     

     查看该容器5000端口映射到宿主机的端口

docker port naughty_yonath 5000/udp

          127.0.0.1:5000    

          Note: The -p flag can be used multiple times to configure multiple ports.

          #官网上的一句话,不过不知道怎样实现。


2)docker容器连接


     网络端口映射不是唯一的方法让容器连接到其他。docker也有一个连接系统可以


3)容器命名


     创建一个容器的时候docker会自动为容器命令,也可以自定义名字。

     eg.

docker run -d -P --name web training/webapp python app.py

     查看容器名字

docker ps -l
docker inspect -f "``.`Name`" 容器id

     容器名必须唯一。

     若想只用一次容器,可以再docker run 的选项中加上--rm,退出容器之后就会删除该容器了。


4)容器连接

     创建一个名为db的容器(包含PostgreSQL数据库)

 docker run -d --name db training/postgres

     创建一个新的网页容器并且link到db容器   

docker run -d -P --name web --link db:db training/webapp python app.py

     其中,--link name:alias,name是连接到得容器名,alias是连接的别名。   

docker ps
$ docker ps
CONTAINER ID  IMAGE                     COMMAND               CREATED             STATUS             PORTS                    NAMES
6d3af77b76eb        training/webapp:latest     python app.py          3 seconds ago       Up 2 seconds        0.0.0.0:49153->5000/tcp   web                 
cfad1bb78495        training/postgres:latest   su postgres -c '/usr   27 seconds ago      Up 27 seconds       5432/tcp                  db,web/db

     我们可以发现连接给db和web这两个容器创建了一个父-子关系。父容器(db)可以再子容器中连接信息。容器建立了一个安全的通道而不是一个公开一个端口。

     docker在子容器里通过两种方法为父容器公开一个连接的信息:

     a)环境变量

     b)更新/etc/hosts文件


    可以看docker的初始化环境变量的设置。通过env命令来列出容器的环境变量

docker run --rm --name web2 --link db:db training/webapp env
    DB_NAME=/web2/db
    DB_PORT=tcp://172.17.0.5:5432
    DB_PORT_5000_TCP=tcp://172.17.0.5:5432
    DB_PORT_5000_TCP_PROTO=tcp
    DB_PORT_5000_TCP_PORT=5432
    DB_PORT_5000_TCP_ADDR=172.17.0.5
    . . .

     注意:这些环境变量只是在容器的第一个进程中使用。一些进程(sshd)为了连接而生成新的shell将会清除掉这些环境变量。


     上面的变量都是DB_开头的,这个是连接的alias,连接的名字是什么,上面变量就是以什么来开头的。我们可以使用这些环境变量来配置应用去连接在db容器中的数据库。这个连接时安全、私有并且只有web容器才能够与db容器通信。

     

     除了环境变量之外,docker在子容器中为连接父节点而在/etc/hosts添加一个入口。(不能够随意修改/etc/hosts这个文件。)

 docker run -t -i --name web1 --link db:db training/webapp /bin/bash

root@6148503e55de:/opt/webapp# cat /etc/hosts

172.17.0.11     6148503e55de

...

172.17.0.9      db


     尝试ping一下db(由于python的webapp这个容器没有ping命令,需要安装)  

root@6148503e55de:/opt/webapp#apt-get install -yqq inetutils-ping
     root@6148503e55de:/opt/webapp# ping db

PING db (172.17.0.9): 48 data bytes

56 bytes from 172.17.0.9: icmp_seq=0 ttl=64 time=2.884 ms

56 bytes from 172.17.0.9: icmp_seq=1 ttl=64 time=0.068 ms

56 bytes from 172.17.0.9: icmp_seq=2 ttl=64 time=0.069 ms

56 bytes from 172.17.0.9: icmp_seq=3 ttl=64 time=0.069 ms

          


=======5.在容器中管理数据=======


1)data volumes(数据卷


     数据卷是一个在一个活多个容器里特别设计的目录,围绕union file system来提供多个持久的或共享数据的特性:

     a)data volumes可以被多个容器共享和重用

     b)可以直接修改在dota volumes进行变动

     c)变动data volumes不包括更新一个镜像

     d)volumes将一直存在知道没有容器使用它们


2)添加一个data volumes

     docker run -t -i --name centos1 -v /mingchao centos /bin/bash
     bash-4.1# df

Filesystem           1K-blocks    Used Available Use% Mounted on

rootfs                10321208  300112   9496808   4% /

/dev/mapper/docker-253:0-132071-7020c1bf4840f24a984f12587a08f9bb2f5ec0f40e8fe0b1e8ded18c3b631c17

                      10321208  300112   9496808   4% /

tmpfs                   957244       0    957244   0% /dev

shm                      65536       0     65536   0% /dev/shm

/dev/mapper/VolGroup-lv_root

                      36744792 4333084  30545164  13% /.dockerinit

/dev/mapper/VolGroup-lv_root

                      36744792 4333084  30545164  13% /etc/resolv.conf

/dev/mapper/VolGroup-lv_root

                      36744792 4333084  30545164  13% /etc/hostname

/dev/mapper/VolGroup-lv_root

                      36744792 4333084  30545164  13% /etc/hosts

/dev/mapper/VolGroup-lv_root

                      36744792 4333084  30545164  13% /mingchao

tmpfs                   957244       0    957244   0% /proc/kcore

     这里是创建了一个新的volume在容器的/mingchao下。

     注:也可以通过在Dockerfile文件中使用VOLUME这个命令来添加一个或多个volumes使得所有用该镜像创建的容器都可以使用。


3)挂载一个宿主机目录当做data volumes  

docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

     这里是将本地的/src/webapp目录挂载到容器的/opt/webapp目录中。

     注:这个不能通过Dockerfile来使用。


     docker默认是实现可读可写的volume,不过我们也可以自定义为只读

docker run -d -P --name web -v /src/webapp:/opt/webapp:ro tra
ining/webapp python app.py


4)创建和挂载一个data volume 容器(容器挂载另一个容器的data volume)


     如果有需要保存的数据并且在容器中共享,或者被一些不长久使用的容器使用,最好是创建一个data volume的容器,然后再使用它的时候采取挂载。

     

     #创建一个容器,并且里面创建一个data volume。   

docker run -i -t -v /dbdata --name dbdata centos /bin/bash

   

     #创建另一个容器,挂载dbdata的data volume----/dbdata

docker run -i -t --volumes-from dbdata(容器名) --name db1 centos /bin/bash


     #创建第二个容器来挂载dbdata的data volume

docker run -i -t --volumes-from dbdata --name db2 centos /bin/bash


     这种挂载可以继续传递下去:

 docker run -i -t --volumes-from db1 --name db3 centos /bin/bash

     如果删除了其中的一些容器,甚至是一开始创建的dbdata这个容器,该volume都会存在,直到所有挂载volume的容器都删除掉,这个volume才会被删除掉。


5)data volumes备份、恢复或迁移   

 docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

     这里我们启动一个新的容器然后挂载dbdata容器的volume。接着挂载一个当前host的路径到/backup。最后,我们使用tar来将dbdata的volume备份到backup.tar(在/backup目录中,即是宿主机的当前目录)。当命令结束且容器停止了之后我们就获得了dbdata的volume的备份。


     可以将它恢复到相同的容器中,或者其他的任何地方。

  docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
  docker run --volumes-from dbdata2 -v $(pwd):/backup centos tar xvf /backup/backup.tar