Docker容器管理

容器是Docker第二个核心概念,简单的的说容器是镜像的一个运行实例,所不同的是,它带有额外的可写文件层。 如果说虚拟机是模拟运行了一整套操作系统(提供运行态环境和其他系统环境)和跑在上面的应用。那么Docker容器就是独立运行的一个或一组应用,以及他们的必须运行环境。

新建容器

Docker的容器十分轻量,用户可以随意的创建或删除容器。 可以使用docler create创建一个容器,比如创建一个Mysql的容器:

docker create -it mysql:latest

然后使用ps命令就可以查看所有的容器,不过要加上-a参数,因为create后的容器默认是不开启的。

docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED              STATUS                   PORTS               NAMES
5f660cfdf9b1        mysql:latest        "/entrypoint.sh --na   About a minute ago                                                goofy_newton        
d8990fec2141        ubuntu:latest       "/bin/bash"            3 hours ago          Exited (0) 3 hours ago                       serene_payne

如果要开启这个容器,就需要docker start

docker start 5f660cfdf9b1

在start可以加ID,也可以加容器的名字,可以用--name在创建的时候为容器起名字,如果不起名的话,docker会自动为它分配一个。

新建并启动容器

启动容器的方式有两种,一是创建一个容器并启动这个容器,另一种就是一个将一个处于中止状态的容器重新启动。 如果是创建一个容器并立即启动,就是使用的docker run命令,这个命令等价与docker create 加 docker start。 当用docker run来创建一个容器时,操作包括:

  1. 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  2. 利用镜像创建并启动一个容器
  3. 分配一个文件系统,并在只读的镜像层外面挂在一层可读写层
  4. 从宿主主机配置的网桥接口中桥接一个虚拟借口到容器中去
  5. 从地址池配置一个IP地址给容器
  6. 执行用户制定的应用程序
  7. 执行完毕后容器被终止

比如使用ubuntu镜像执行bash终端:

docker run -t -i ubuntu:14.04 /bin/bash
root@ce5e7fe50200:/# 

其中-t参数是让docker分配一个伪终端并绑定到容器的标准输入上,-i则让容器的标准输入保持打开。 exit或ctrl+D退出之后,容器也就处于了终止状态,因为bash程序结束了。 更多时候,需要容器在后台以守护态运行,可以通过添加-d参数来实现。 比如:

docker run -d ubuntu:14.04

终止容器

可以使用docker stop终止一个正在运行的容器,命令格式为:

docker stop [-t|--time[=10]]

它会首先想容器发送SIGTERM信号,然后等待一段时间(默认10s),再发送SIGKILL信号终止容器。 当然,可以使用docker kill命令直接发送SIGKILL信号强行终止容器。 如果想重新启动一个容器只需要docker restart

进入容器

因为在使用-d参数之后,容器启动之后便会进入后台,用户无法看到容器中的信息,某些时候需要近土容器进行操作,有多种方法进入容器,包括docker attach命令、docker exec命令,以及nsenter工具。

attach命令

docker attach是docker自带的命令,使用简单docker attach 后面跟ID或容器名就可以,不过attach命令有时候并不方便,当多个窗口同时attach到同一个容器的时候,所有的窗口都会同步显示,当某个窗口因命令阻塞时,其他窗口也就没法进行别的操作了。

exec命令

这也是昨天看直播的时候讲到的命令,目测很好用,exec是docker 1.3版本提供的工具,可以直接在容器内运行命令,例如进入一个容器并启动一个bash:

docker exec -ti [ID|NAME] /bin/bash

nsenter工具

nsenter是util-linux包2.23版本后包含的工具,并不是docker的自带工具,需要安装util-linux包,使用起来稍麻烦,不打算尝试。

删除容器

使用docker rm指令便可以删除指定容器,语法格式:

docker rm [OPTIONS] CONTAINER[CONTAINER..]

支持的选项包括:

  • -f,--force=false 强行终止并删除一个运行中的容器
  • -l,--link=false 删除容器链接,但保留容器
  • -v,--columes=false删除容器挂载的数据卷

导出容器

导出容器是指导出一个已经创建好的容器到一个文件,不管这个容器是否处于运行状态都可以导出。 使用导出命令docker export命令,该命令使用格式为:

docker export CONTAINER

比如:

docker export boring_galileo > dbserver.tar

可以将这些文件传输到其他机器上,在其他机器通过导入命令实现容器的迁移。

导入容器

导出的文件又可以使用docker import命令导入,成为镜像,例如: 把刚才导出的文件再导入:

cat dbserver.tar | docker import - dbserver:lastest

这个效果和Docker镜像的创建、存出、载入中的基于本地模板导入非常一致。 实际上,既可以通过docker load导出镜像存储文件到本地镜像库,又可以使用docker import命令导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢失所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。

2015/06/04 10:22 am posted in  Docker

Docker镜像的创建、存出、载入

创建镜像的方法有三种:基于已有镜像的容器创建、基于本地模板导入、基于Dockerfile创建。昨天csphere培训用的便是最后一种,不过Dockerfile文件是已经被写好的了,所以再还不会写Dockerfile的情况下,先不写这种方法创建镜像。

基于已有镜像的容器创建

该方法是使用docker commit命令,其命令格式为:

docker commit[OPTIONS] CONTAINER[REPOSITORY[:TAG]]

主要参数选项包括:

  • -a ,--author="" 作者信息
  • -m,--message="" 提交信息
  • -p,--pause=true 提交是暂停容器运行

比如,先创建一个运行bash的ubuntu容器:

docker run -it ubuntu /bin/bash
root@d8990fec2141:/# touch test
root@d8990fec2141:/# exit

然后根据创建的这个容器来提交一个新的镜像,提交时需要用到容器ID。

docker commit -m "test" -a "HypoChen" d8990fec2141 testimage

如果成功的话,就会返回新镜像的长ID号,然后可以查看看在本地已有的镜像:

docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
testimage           latest              baea98d5a437        About a minute ago   188.3 MB
ubuntu              14.04               fa81ed084842        3 days ago           188.3 MB
ubuntu              latest              fa81ed084842        3 days ago           188.3 MB

第三行就是刚刚创建的镜像。

基于本地模板导入

也可以从操作系统模板文件导入一个镜像,比如使用OpenVZ提供的模板创建,OPENVZ下载模板在:http://openvz.org/Download/template/precreated。 我尝试使用了Ubuntu14.04的模板,在vps里直接下载了:

wget http://download.openvz.org/template/precreated/ubuntu-14.04-x86_64-minimal.tar.gz

不过不得不说腾讯云下载东西好慢啊,75M的东西让我等了好久,差评。 下载完之后就可以导入了:

sudo cat ubuntu-14.04-x86_64-minimal.tar.gz | docker import - ubuntu:14.04

其实只是两个命令,不过很显而易见,就不加解释了。成功的话,就会返回根据模板建立的镜像的长ID 然后就可以查看本地的镜像:

sudo cat ubuntu-14.04-x86_64-minimal.tar.gz | docker import - ubuntu:14.04
ab80404d13d580965b9919b640169ccb585ea7884e6aa9de1ec043075c65fe35
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               ab80404d13d5        56 seconds ago      215.4 MB
testimage           latest              baea98d5a437        29 minutes ago      188.3 MB
ubuntu              latest              fa81ed084842        3 days ago          188.3 MB

其实可以看出,虽然模板才75M,但创建的镜像并不小。

镜像的存出和载入

可以利用docker save和docker命令来存出和载入镜像。

存出镜像

如果想要把镜像存出到本地文件,可以使用docker save命令,例如,存出本地的刚才创建的testimage:lastest为镜像文件testimage.tar文件:

docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
testimage           latest              baea98d5a437        25 minutes ago      188.3 MB
ubuntu              latest              fa81ed084842        3 days ago          188.3 MB
ubuntu              14.04               fa81ed084842        3 days ago          188.3 MB
docker save -o /data/testimage.tar testimage:latest

上面的第6行就是存出代码,这时在/data下就有一个testimage.tar文件,这时我们把本地镜像rmi掉,然后尝试载入。

载入镜像

删除镜像之后的状态:

ubuntu@VM-223-238-ubuntu:/data$ docker rmi baea98d5a437
Untagged: testimage:latest
Deleted: baea98d5a4371a6abf9efc8c53a54a6fc5befd167bf91ce9fd4a28a6d1b7dc5b
ubuntu@VM-223-238-ubuntu:/data$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               ab80404d13d5        5 minutes ago       215.4 MB
ubuntu              latest              fa81ed084842        3 days ago          188.3 MB

然后载入镜像:

docker load --input testimage.tar 
docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               ab80404d13d5        6 minutes ago       215.4 MB
testimage           latest              baea98d5a437        35 minutes ago      188.3 MB
ubuntu              latest              fa81ed084842        3 days ago          188.3 MB

第一行就是载入镜像,还可以简化写成:

docker load 

载入操作将会导入镜像以及相关的元数据信息(包括标签等)。

镜像的上传

最后说点镜像的上传,镜像的管理方式非常像git,可以使用docker push命令上传自己本地镜像到仓库,默认上传到DockerHub官方仓库(需要登陆),命令格式:

docker push NAME[:TAG]

在上传之前一般会先为自己的镜像添加带自己名字(作者信息)的标签:

docker tag testimage:lastest hypochen/testimage:lastest
docker push hypochen/testimage:lastest

有利于上传之后的区分。 我觉得无论是运维团队还是开发团队还是一个实验室,都有必要有一个自己的Docker仓库,可以存放符合自己需求的环境或系统镜像,可以实现快速部署。 但是镜像和代码不一样,代码我们可以用github,但镜像动辄几十M,我觉得开源理工有必要做一个本地镜像站来代替DockerHub,并且提供校内的镜像托管服务,这将十分有利用代码的快速部署。

2015/06/04 10:17 am posted in  Docker

Docker镜像的获取与删除

Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Dicker Hub公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。

获取镜像

镜像是Docker运行容器的前提。 可以使用docker pull命令从网络上下载镜像。该命令的格式为:

docker pull NAME[:TAG]

对于Docker镜像来说,如果不显示地制定TAG,则默认会选择latest标签,即下载仓库中的最新版本的镜像。 如果要获取一个ubuntu镜像,可以:

sudo docker pull ubuntu

这样,便会从Docker的Ubuntu仓库中下载一个最新的Ubuntu操作系统镜像,也可以下载制定标签的镜像,比如下载14.04标签的镜像:

sudo docker pull ubuntu:14.04

上面的命令都相当于sudo docker pull registry.hub.docker.com/ubuntu:latest命令,即从默认的注册服务器registry.hub.docker.com中的ubuntu仓库下载标记为lastest的镜像。 当然,也可以选择其他注册服务器的仓库下载,此时只需要在仓库前制定完整仓库注册服务器地址,例如从DockerPool社区的镜像源下载最新ubuntu:

sudo docker pull dl.dockerpool.com:5000/ubuntu

在下载过程中可以看到镜像文件一般是由若干层组成,行首是像e118faab2e16这样的各层ID,下载过程中会获取并输出镜像的各层信息:

latest: Pulling from ubuntu
e118faab2e16: Downloading
7e2c5c55ef2c: Download complete 
e04c66a223c4: Download complete 
fa81ed084842: Download complete

层(Layer)其实是AUFS(Advanced Union File System,一种联合文件系统)中的重要概念,是实现增量保存与更新的基础。 在本地有了这个镜像之后便可以使用,生成容器了,比如在这个ubuntu镜像上生成一个容器,在其中运行bash应用:

sudo docker run -t -i ubuntu /bin/bash
root@636151e7941b:/# 

这就是相当于用ubuntu这个镜像创建了一个容器,并且你已经在这个容器里面了,在这里,你完全可以和使用普通的ubuntu系统一样(可以认识为这个镜像生成的虚拟机,不过所有同类容器只占有自身数据的大小,而镜像部分共用),包括各种命令,甚至安装软件。

查看镜像信息

使用docker images命令可以列出本地主机上已有的镜像:

sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              fa81ed084842        3 days ago          188.3 MB

再励出的信息中分别是来自那个仓库,比如ubuntu仓库,镜像标签,镜像ID(唯一),创建时间,镜像大小。 为了管理方便,还可以使用docker tag命令为本地镜像添加新的标签,比如添加:

sudo docker tag pull dl.dockerpool.com:5000/ubuntu:lastest ubuntu:lastest

然后就会多出一个标签为ubuntu:latest的新镜像。 使用docker inspect [镜像ID]可以获取该镜像的详细信息:

sudo docker inspect fa81ed084842
[{
    "Architecture": "amd64",
    "Author": "",
    "Comment": "",
    "Config": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "/bin/bash"
        ],
        "CpuShares": 0,
        "Cpuset": "",
        "Domainname": "",
        "Entrypoint": null,
        "Env": null,
        "ExposedPorts": null,
        "Hostname": "706cb4504c90",
        "Image": "e04c66a223c45a6247237510c40117cef92acb0a4355f1ba90580ef6274b490d",
        "Labels": {},
        "MacAddress": "",
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkDisabled": false,
        "OnBuild": null,
        "OpenStdin": false,
        "PortSpecs": null,
        "StdinOnce": false,
        "Tty": false,
        "User": "",
        "Volumes": null,
        "WorkingDir": ""
    },
    "Container": "ba8570386ba189dc1af092e141415fbf522e38915b991d6ac5d682c51f42c13f",
    "ContainerConfig": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [\"/bin/bash\"]"
        ],
        "CpuShares": 0,
        "Cpuset": "",
        "Domainname": "",
        "Entrypoint": null,
        "Env": null,
        "ExposedPorts": null,
        "Hostname": "706cb4504c90",
        "Image": "e04c66a223c45a6247237510c40117cef92acb0a4355f1ba90580ef6274b490d",
        "Labels": {},
        "MacAddress": "",
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkDisabled": false,
        "OnBuild": null,
        "OpenStdin": false,
        "PortSpecs": null,
        "StdinOnce": false,
        "Tty": false,
        "User": "",
        "Volumes": null,
        "WorkingDir": ""
    },
    "Created": "2015-06-01T00:00:32.983571589Z",
    "DockerVersion": "1.6.0",
    "Id": "fa81ed084842076d1b39b56d084d99ec0011cd4a5ade1056be359486a8b213e4",
    "Os": "linux",
    "Parent": "e04c66a223c45a6247237510c40117cef92acb0a4355f1ba90580ef6274b490d",
    "Size": 0,
    "VirtualSize": 188281989
}
]

搜寻镜像

可以使用docker search命令搜寻镜像,比如搜寻带mysql关键字的镜像如下所示:

sudo docker search mysql
NAME                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                        MySQL is a widely used, open-source relati...   735       [OK]       
tutum/mysql                  MySQL Server image - listens in port 3306....   122                  [OK]
orchardup/mysql                                                              37                   [OK]
centurylink/mysql            Image containing mysql. Optimized to be li...   23                   [OK]
mysql/mysql-server           Optimized MySQL Server Docker images. Crea...   17                   [OK]
wnameless/mysql-phpmyadmin   MySQL + phpMyAdmin https://index.docker.io...   15                   [OK]
google/mysql                 MySQL server for Google Compute Engine          13                   [OK]
sameersbn/mysql                                                              11                   [OK]
ioggstream/mysql             MySQL Image with Master-Slave replication       5                    [OK]
appcontainers/mysql          CentOS 6.6 based Customizable MySQL 5.5 Co...   3                    [OK]
alreece45/phusion-mysql      Simple MySQL container with auto-creating ...   2                    [OK]
azukiapp/mysql               Docker image to run MySQL by Azuki - http:...   2                    [OK]
jdeathe/centos-ssh-mysql     CentOS-6 6.6 x86_64 / MySQL.                    2                    [OK]
frodenas/mysql               A Docker Image for MySQL                        1                    [OK]
phpmentors/mysql             MySQL server image                              1                    [OK]
lec00q/mysql                 A docker image for running a mysql server ...   0                    [OK]
jmoati/mysql                                                                 0                    [OK]
marvambass/mysql             MySQL Server based on Ubuntu 14.04              0                    [OK]
learninglayers/mysql                                                         0                    [OK]
cloyne/mysql                                                                 0                    [OK]
thomaswelton/mysql                                                           0                    [OK]
ahmet2mir/mysql              This is a Debian based image with MySQL se...   0                    [OK]
miko2u/mysql                 MySQL with groonga and ipv6                     0                    [OK]
horx/mysql                   Mysql server                                    0                    [OK]
ingoclaro/mysql                                                              0                    [OK]

返回很多包含关键字的镜像,包括镜像名、描述、星级(表示该镜像的受欢迎程度)、是否官方创建、是否自动创建等。

删除镜像

使用dockerrmi命令可以删除镜像,命令格式为:

docker rmi IMAGE[IMAGE...]

其中IMAGE可是标签或ID。 因为一个镜像可以有多个标签,如果rmi一个标签时不能找到唯一的镜像,便会删除这个标签,直到一个标签能确定唯一镜像为止。所以,如果一个标签可以确定这个镜像,再执行这个命令便危险了,因为将直接删除这个镜像。 如果一个镜像已经创建了容器,那么这个镜像文件默认是无法被删除的,例如刚才的ubuntu镜像以及创建了一个执行bash 的容器,可以用docker ps -a命令查看所有容器:

sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
636151e7941b        ubuntu:latest       "/bin/bash"         28 minutes ago      Exited (0) 22 minutes ago                       hopeful_rosalind

会发现后台存在一个处于Exited退出状态的容器,那么是无法删除ubuntu镜像的。如果想要强行删除,可以加-f参数,但这样往往遗留一些问题。比如删除之后,docker images中会存在一个名为none 的临时镜像。 正确的做法应该是先删除以来该惊险的所有容器:

sudo docker rm 636151e7941b

然后再删除镜像。

2015/06/04 10:11 am posted in  Docker

Ubuntu 下安装 Docker

Ubuntu在14.02开始就已经集成了Docker,要安装很简单:

sudo apt-get update
sudo apt-get install docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io

但是,这样安装的Docker会比较旧,如果想要安装最新版本的Docker还需要安装https支持:

sudo apt-get install apt-transport-https

然后把官方源添加进来:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
sudo sh -c "echo deb https://get.docker.io/ubuntu docker main\
> /etc/apt/sources.list.d/docker.list"
sudo apt-get update

然后就可以通过下面的命令来安装最新版本的Docker了:

sudo apt-get install lxc-docker

在安装了Docker官方软件源后,若需要更新Docker软件版本,只需要执行以下命令即可升级:

sudo apt-get update lxc-docker

如果使用的是较低版本的Ubuntu系统,则需要先进行内核更新并重启系统后再进行安装:

sudo apt-get update
sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
sudo reboot

重启后,重复和14.04一样的安装过程即可。

2015/06/03 10:11 am posted in  Docker

Docker的三大核心概念

最近开始学习Docker,不打算从介绍开始写Docker,虽然Docker从诞生(2014.6)到现在(2015.6)已经一年了,但到现在Docker在中国还处于科普阶段,但Docker 的强大随便一Google就能看到大把大把的。 现在我正在看的书是《Docker技术入门与实践》,号称中国第一本讲解Docker 的书籍,而我对Docker的学习也将围绕着这本书展开。

Docker镜像

Docker镜像(Image)类似与虚拟机的镜像,可以将他理解为一个面向Docker引擎的只读模板,包含了文件系统。 例如:一个镜像可以完全包含了Ubuntu操作系统环境,可以把它称作一个Ubuntu镜像。镜像也可以安装了Apache应用程序(或其他软件),可以把它称为一个Apache镜像。 镜像是创建Docker容器的基础,通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像。 用户可以从网上下载一个已经做好的应用镜像,并通过命令直接使用。 总之,应用运行是需要环境的,而镜像就是来提供这种环境。  

Docker容器

Docker容器(Container)类似于一个轻量级的沙箱子(因为Docker是基于Linux内核的虚拟技术,所以消耗资源十分少),Docker利用容器来运行和隔离应用。 容器是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,而这些容器都是相互隔离、互不可见的。 可以吧每个容器看作一个简易版的Linux系统环境(包括了root用户权限、进程空间、用户空间和网络空间),以及与运行在其中的应用程序打包而成的应用盒子。 镜像自身是只读的。容器从镜像启动的时候,Docker会在镜像的最上层创建一个可写层,镜像本身将保持不变。就像用ISO装系统之后,ISO并没有什么变化一样。  

Docker仓库

Docker仓库(Repository)类似与代码仓库,是Docker集中存放镜像文件的场所。 有时候会看到有资料将Docker仓库和注册服务器(Registry)混为一谈,并不严格区分。实际上,注册服务器是存放仓库的地方,其上往往存放着多个仓库。每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。例如存放Ubuntu操作系统镜像的仓库,称为Ubuntu仓库,其中可能包括14.04,12.04等不同版本的镜像。 根据存储的镜像公开分享与否,Docker仓库分为公开仓库(Public)和私有仓库(Private)两种形式。 目前,最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供稳定的国内访问。山东理工大学开源社区什么时候搞个这个啊,可以提上进程。 如果用户不希望公开分享自己的镜像文件,Docker也支持用户在本地网络内创建一个只能自己访问的私有仓库。 当用户创建了自己的镜像之后就可以使用push明亮将它上传到指定的公有或则私有仓库。这样用户下次在另一台机器上使用该镜像时,只需将其从仓库pull下来就可以了。 Docker利用仓库管理镜像的设计理念甚至命令和git非常相似,也就意味着非常好上手,尽管目前我git还不是很熟练。

2015/06/03 10:10 am posted in  Docker