docker 学习笔记

Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。简单的说Docker是一个构建在LXC之上的,基于进程容器(Processcontainer)的轻量级VM解决方案。Docker的初衷是将各种应用程序和他们所依赖的运行环境打包成标准的container/image,进而发布到不同的平台上运行—应用集装箱。

目录

1. 介绍

1.1 轻量虚拟化技术的需求

1.2 Docker VS VM

1.3 轻量虚拟化技术

1.4 docker和内核交互

1.5 如何与容器进行通信

2. 术语介绍

2.1 Docker 守护进程

2.2 Docker 客户端

2.3 客户端与守护进程

2.4 Docker images

2.5 Docker Repositories

2.6 Docker containers

2.7 Namespaces

2.8 libcontainer

2.9 cgroups-资源配额

2.10 容器数据卷

3.安装

3.1 安装条件

3.2 CentOS安装Docker

4.命令集

4.1 容器

4.2  镜像

5. Dockerfile

6. 管理工具

6.1 Docker machine

6.2 Swarm

6.3 Docker compose

6.4 Shipyard

6.5 cAdvisor

Reference


1. 介绍

1.1 轻量虚拟化技术的需求

技术发展过程中,产生了这样的需求:

  • 进程隔离:不同进程,希望有自己独立的周边环境;
  • 资源限制:限制某些进程所能使用的资源;

最终, 能进一步对一组进程进行上述隔离和限制

1.2 Docker VS VM

1.3 轻量虚拟化技术

底层技术:

  • namespace/cgroups/iptables/chroot/tc/quota
  • veth
  •  union fs(AUFS)

container管理:

  • LXC/libvirt

安全相关:

  • grsec/apparmor/SELinux

高级:

  • docker/warden/Imctfy/openVZ

1.4 docker和内核交互

Docker 从 0.9 版本开始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系统的交互图如下:

1.5 如何与容器进行通信

  • 容器通过docker0网桥与外部通信
  • 外部通过iptables端口转发与容器通信

思考:跨主机容器通信方式?

  • 基于iptables端口转发
  • 基于SDNFlannelOpen vSwitchWeaveGREVxLAN

更多网络方面的知识可以参阅另一篇“docker网络篇

2. 术语介绍

2.1 Docker 守护进程

Docker 守护进程运行在一台主机上,它会处理复杂繁重的任务,例如建立、运行、发布你的 Docker 容器。用户并不直接和守护进程进行交互,而是通过 Docker 客户端间接和其通信。

2.2 Docker 客户端

Docker 客户端,实际上是 docker 的二进制程序,是用户与 Docker 交互方式。它接收用户指令并且与背后的 Docker 守护进程通信,如此来回往复。

2.3 客户端与守护进程

  • Docker 使用客户端-服务器 (C/S) 架构模式,Docker 客户端会与 Docker 守护进程进行通信
  • Docker 客户端和守护进程可以运行在同一个系统上,当然你也可以使用 Docker 客户端去连接一个远程的 Docker 守护进程
  • Docker 客户端和守护进程之间通过 socket 或者 RESTful API 进行通信

2.4 Docker images

Docker 镜像是 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。

Docker 使用 UnionFS 来将这些层联合到单独的镜像中。UnionFS 允许独立文件系统中的文件和文件夹(称之为分支)被透明覆盖,形成一个单独连贯的文件系统。正因为有了这些层的存在,Docker 是如此的轻量。当你改变了一个 Docker 镜像,比如升级到某个程序到新的版本,一个新的层会被创建。因此,不用替换整个原先的镜像或者重新建立(在使用虚拟机的时候你可能会这么做),只是一个新 的层被添加或升级了。现在你不用重新发布整个镜像,只需要升级,层使得分发 Docker 镜像变得简单和快速。

2.5 Docker Repositories

Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。同样的,Docker 仓库也有公有和私有的概念。

公有的 Docker 仓库名字是 Docker Hub。Docker Hub 提供了庞大的镜像集合供使用。这些镜像可以是自己创建,或者在别人的镜像基础上创建。Docker 仓库是 Docker 的分发部分。

国内知仓库:https://www.daocloud.io/

docker-registry是官方提供的工具,它主要用作仓库登记,管理镜像文件,也可以用于构建私有的镜像仓库。

2.6 Docker containers

Docker 容器和文件夹很类似,一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分。

2.7 Namespaces

Linux 内核从版本 2.4.19 开始陆续引入了 namespace 的概念。其目的是将某个特定的全局系统资源(global system resource)通过抽象方法使得namespace 中的进程看起来拥有它们自己的隔离的全局系统资源实例(The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource. )。Linux 内核中实现了六种 namespace,按照引入的先后顺序,列表如下:

namespace内核版本被隔离的全局系统资源在容器语境下的隔离效果
Mount namespacesLinux 2.4.19文件系统挂接点每个容器能看到不同的文件系统层次结构
UTS namespacesLinux 2.6.19nodename 和 domainname每个容器可以有自己的 hostname 和 domainame
IPC namespacesLinux 2.6.19特定的进程间通信资源,包括System V IPC 和  POSIX message queues每个容器有其自己的 System V IPC 和 POSIX 消息队列文件系统,因此,只有在同一个 IPC namespace 的进程之间才能互相通信
PID namespacesLinux 2.6.24进程 ID 数字空间 (process ID number space)每个 PID namespace 中的进程可以有其独立的 PID; 每个容器可以有其 PID 为 1 的root 进程;也使得容器可以在不同的 host 之间迁移,因为 namespace 中的进程 ID 和 host 无关了。这也使得容器中的每个进程有两个PID:容器中的 PID 和 host 上的 PID。
Network namespaces始于Linux 2.6.24 完成于 Linux 2.6.29网络相关的系统资源每个容器用有其独立的网络设备,IP 地址,IP 路由表,/proc/net 目录,端口号等等。这也使得一个 host 上多个容器内的同一个应用都绑定到各自容器的 80 端口上。
User namespaces始于 Linux 2.6.23 完成于 Linux 3.8)用户和组 ID 空间 在 user namespace 中的进程的用户和组 ID 可以和在 host 上不同; 每个 container 可以有不同的 user 和 group id;一个 host 上的非特权用户可以成为 user namespace 中的特权用户;

Linux namespace 的概念说简单也简单说复杂也复杂。简单来说,我们只要知道,处于某个 namespace 中的进程,能看到独立的它自己的隔离的某些特定系统资源;复杂来说,可以去看看 Linux 内核中实现 namespace 的原理,网络上也有大量的文档供参考,这里不再赘述。

Docker充分利用了一项称为namespaces 的技术来提供隔离的工作空间,我们称之为 container(容器)。当你运行一个容器的时候,Docker为该容器创建了一个命名空间集合。当 Docker 创建一个容器时,它会创建新的以上六种 namespace 的实例,然后把容器中的所有进程放到这些 namespace 之中,使得Docker 容器中的进程只能看到隔离的系统资源。 

pid namespace

不同用户的进程就是通过 pid namespace 隔离开的,且不同 namespace 中可以有相同 PID。

  • 每个 namespace 中的 pid 是有自己的 pid=1 的进程(类似 /sbin/init 进程)
  • 每个 namespace 中的进程只能影响自己的同一个 namespace 或子 namespace 中的进程
  • 因为 /proc 包含正在运行的进程,因此在 container 中的 pseudo-filesystem 的 /proc 目录只能看到自己 namespace 中的进程
  • 因为 namespace 允许嵌套,父 namespace 可以影响子 namespace 的进程,所以子 namespace 的进程可以在父 namespace 中看到,但是具有不同的 pid 

参考文档:Introduction to Linux namespaces – Part 3: PID

mnt namespace

使用在管理挂载点 (MNT: Mount)。mnt namespace 允许不同 namespace 的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个 namespace 中的 container 在 /proc/mounts 的信息只包含所在 namespace 的 mount point。

net namespace

网络隔离是通过 net namespace 实现的, 每个 net namespace 有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个 container 的网络就能隔离开来。 docker 默认采用 veth 的方式将 container 中的虚拟网卡同 host 上的一个 docker bridge 连接在一起。

参考文档:Introduction to Linux namespaces – Part 5: NET

uts namespace

使用在隔离内核和版本标识。UTS ("UNIX Time-sharing System") namespace 允许每个 container 拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。

参考文档:Introduction to Linux namespaces – Part 1: UTS

ipc namespace

使用在管理进程间通信资源。container 中进程交互还是采用 Linux 常见的进程间交互方法 (interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同,container 的进程间交互实际上还是 host 上具有相同 pid namespace 中的进程间交互,因此需要在IPC资源申请时加入 namespace 信息 - 每个 IPC 资源有一个唯一的 32bit ID。

参考文档:Introduction to Linux namespaces – Part 2: IPC

user namespace

每个 container 可以有不同的 user 和 group id, 也就是说可以以 container 内部的用户在 container 内部执行程序而非 Host 上的用户。有了以上 6 种 namespace 从进程、网络、IPC、文件系统、UTS 和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。 然而不同 namespace 之间资源还是相互竞争的,仍然需要类似 ulimit 来管理每个 container 所能使用的资源 - cgroup。

2.8 libcontainer

在docker和内核交互中介绍过,更多则查看 Docker 0.9: introducing execution drivers and libcontainer

2.9 cgroups-资源配额

cgroups 实现了对资源的配额和度量。cgroups 的使用非常简单,提供类似文件的接口,在 /cgroup 目录下新建一个文件夹即可新建一个 group,在此文件夹中新建 task 文件,并将 pid 写入该文件,即可实现对该进程的资源控制。

具体的资源配置选项可以在该文件夹中新建子 subsystem ,{子系统前缀}.{资源项} 是典型的配置方法, 如 memory.usageinbytes 就定义了该 group 在 subsystem memory 中的一个内存限制选项。 另外,cgroups 中的 subsystem 可以随意组合,一个 subsystem 可以在不同的 group 中,也可以一个 group 包含多个 subsystem - 也就是说一个 subsystem。

  • memory,内存相关的限制
  • cpu,在 cgroup 中,并不能像硬件虚拟化方案一样能够定义 CPU 能力,但是能够定义 CPU 轮转的优先级,因此具有较高 CPU 优先级的进程会更可能得到 CPU 运算。
  • blkio,block IO 相关的统计和限制,byte/operation 统计和限制 (IOPS 等),读写速度限制等,但是这里主要统计的都是同步 IO
  • devices,设备权限限制

2.10 容器数据卷

卷(Volume)是容器中的一个数据挂载点,卷可以绕过联合文件系统,从而为Docker 提供持久数据,所提供的数据还可以在宿主机-容器或多个容器之间共享。通过卷,我们可以可以使修改数据直接生效,而不必重新构建镜像。

数据卷设计的初哀是提供持久化数据,而与容器的生命周期无关。因此,在删除容器时,Docker不会自动删除卷,直到没有容器再引用。

添加数据卷

可以在docker createdocker create命令创建容器时,通过-v参数为容器添加数据卷。-v参数参数可以多次使用,以添加多个数据卷。如,可以像下面这样为容器添加一个卷:$sudo docker run -t -i -v /home/test --name test itbilu/test /bin/bash

这样就会在容器内/webapp位置创建一个卷。

除了在创建容器时添加数据卷外,还可以通过Dockerfile文件中通过Volume指令添加,Volume可以多次使用以添加多个数据卷。

说明:本文中使用的示例镜像(itbilu/test)通过以下Dockerfile文件创建:

# Version: 0.0.3
FROM ubuntu:16.04
MAINTAINER 何民三 "cn.liuht@gmail.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hello World, 我是个容器' \ 
   > /var/www/html/index.html
RUN mkdir /home/itbilu/
ENV ITBILU_PATH /home/itbilu/
VOLUME [$ITBILU_PATH]
EXPOSE 80

卷位置

添加卷后,可以通过docker inspect来查看数据卷在容器中的位置:$sudo docker inspect test

docker inspect可以用来查看容器或镜像的详细配置信息。可以在容器的Mounts节点下,查看容器的卷信息:

...
"Mounts": [{
  "Type": "volume",
  "Name": "5f869c580c06e6079b0de2c5ce682c1c9467286c76b506703d87bf11d1271c24",
  "Source": "/var/lib/docker/volumes/5f869c580c06e6079b0de2c5ce682c1c9467286c76b506703d87bf11d1271c24/_data",
  "Destination": "/home/test",
  "Driver": "local",
  "Mode": "",
  "RW": true,
  "Propagation": ""
},
{
  "Type": "volume",
  "Name": "e4fd6c3a91ba2e03b14cf174c2023f366abbe9f2f73ca07e6bac223f68e47773",
  "Source": "/var/lib/docker/volumes/e4fd6c3a91ba2e03b14cf174c2023f366abbe9f2f73ca07e6bac223f68e47773/_data",
  "Destination": "[/home/itbilu/]",
  "Driver": "local",
  "Mode": "",
  "RW": true,
  "Propagation": ""
}],
...

在以上示例中,有两个挂载卷,一个是在docker run创建容器时创建的,而另一个是在创建运行容器镜像的Dockerfile文件中通过VOLUME指令创建。其中,Source表示宿主机源文件位置,Destination表示数据卷在容器中的挂载位置,而RW表示卷是否可读/写。

挂载本地数据到容器数据卷

在前面示例中,我们运行容器时并没有指定要挂载到容器中数据卷的本地目录,所在Docker使用一个默认数据目录。-v参数除了可以在容器中创建数据卷外,还可以将宿主机中的目录挂载到容器中的数据卷。

如,运行容器,并将本地的~/code/itbilu目录挂载到容器的/home/itbilu数据卷上:$ sudo docker run -t -i -v ~/code/itbilu:/home/itbilu --name test itbilu/test /bin/bas

注:挂载本地目录到容器内的挂载目录时,如果容器内的数据卷中已经存在数据,那么本地内容将与数据卷中的数据重叠,而不会删除数据。

其中,容器目录必须使用绝对路径,而本地目录可以使用绝对路径或其它形式。

挂载共享存储

除了可以载挂本地目录到容器数据卷外,一些Docker卷插件让你可以挂载共享存储到容器的数据卷,如:iSCSINFSFC。使用共享卷的好处是它们是独立于主机的,这意味着,只要有访问共享存储权限,并安装插件,就可以在任何容器上启动卷。详细参考:

挂载本地文件到容器数据卷

-v参数不仅可挂载目录,还可以挂载单个文件。如:$ sudo docker run -t -i -v ~/.bash_history:/root/.bash_history \ --name test itbilu/test /bin/bash

以上会把本地的~/.bash_history文件挂载到新容器中,这样你就可以在容器内访问宿主上的bash历史记录。

数据卷容器

如果你有一些要在容器之间共享的持久性数据,或者希望在非持久容器中使用,那么最好创建一个命名的数据卷容器,然后从其挂载数据。

接下来,我们创建一个新的命名的共享容器。这个容器不运行一个应用程序,它利用training/postgres镜像在所有的容器之间创建了一个共享层,以节省磁盘空间。$sudo docker create -v /dbdata --name dbstore training/postgres /bin/true

注:training/postgres是Docker 官方文档中提供的一个镜像,本文拿来直接使用了。

使用数据卷容器

创建数据卷容器后,我们可以通过--volumes-from选项,将一个数据容器挂载到其它容器:$sudo docker run -d --volumes-from dbstore --name db1 training/postgres

也可以在多个容器间共享。如,挂载到另一个容器:$sudo docker run -d --volumes-from dbstore --name db2 training/postgres

这时,如果training/postgres镜像内有名/dbdata的目录,则会从dbstore容器挂载卷,并会隐藏training/postgres镜像中/dbdata下的文件。最终只有dbstore容器中的文件可见。

还可以扩展挂载链,从已经存在的dbstore容器(如:db1db2)来挂载卷:$ sudo docker run -d --name db3 --volumes-from db1 training/postgres

这种情况下,如果移除己挂载卷的容器,无论是最初的dbstore容器,还是其后的db1db2容器,卷都不会被移除。要将卷从硬盘上移除,必须使用docker rm -v命令删除最后一个引用了该卷的容器。

除上述操作外,数据卷的常用操作还有数据卷备份、恢复、合并操作。以下是一些常用操作:

备份数据卷

在前面介绍数据卷容器时,我们创建了一个名为dbdata容器,并在容器中创建了一个/dbdata数据卷。接下来,可以在创建容器使用--volumes-from参数来挂载这个数据卷,并对数据进行备份:$sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

在这个操作中,我们通过ubuntu镜像创建了一个容器,创建容器时通过--volumes-from参数共享了数据卷容器中的数据,并将当前目录($(pwd))挂载到了数据卷中。容器运行后,使用tar命令对数据卷进行了备份。

命令执行结束后,容器就会停止,之后就可以在本地当前操作目录下找到所备份的数据。

备份数据卷

数据备份后,可以在创建容器恢复备份数据到容器内的数据卷中,从而实现数据的迁移。

首先,创建并运行容器并添加一个数据卷$sudo docker run -i -t -v /dbdata --name dbdata2 ubuntu /bin/bash

然后通过tar命令恢复备份数据:$ sudo docker run --rm --volumes-from dbdata2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"

这样,数据就被恢复到了容器dbdata2/dbdata目录下,我们可以容器中操作和使用这些数据。

3.安装

Docker的安装非常的简单和快捷,当前Docker已支持大多数Linux发行版,包括:Ubuntu、Red Hat、CentOS、SUSE、Fedora、Debian等,也可以在AWS、Aliyun等云平台安装。

3.1 安装条件

  • 64位CPU,当前只支持amd64、x86_64
  • 3.0+版本的Linux内核,虽然一些老版本(如:2.6.x或其后)的版本的内核也能运行,便会有各种问题,不建议使用
  • Linux内核必须支持cgroup和namespace
  • Linux内核必须支持以下存储驱动之一:
    • Device Mapper(默认)
    • Device Manager
    • AUFS
    • vfs
    • btrfs

自2017年3月起,Docker发行版分成了CE(Community Edition)和EE版(Enterprise Edition),在本文示例中,我们使用CE版本的。

3.2 CentOS安装Docker

环境检查

官方提供支持的CentOS系统当前只有64位的CentOS 7发行版。当然这不并意味你不能CentOS 6等其它CentOS中使用,理论上讲只要满足Docker安装条件,都可以安装Docker,只是你可能需要自己进行更新。

移除非官方Docker

一些yum源中包含了一个版本较旧的Docker包,其包名是docker而不是官方的docker-engine。我们需要先移除它:

sudo yum -y remove docker\
                  docker-common \
                  container-selinux \
                  docker-selinux \
                  docker-engine

yum源安装Docker

使用yum源安装Docker,首先要设置yum,设置后就可以基于源进行安装、更新、降级等操作。

#1. 安装yum-utils工具,它提供了yum-config-manager工具
sudo yum install -y yum-utils

#2. 设置yum源(添加了一个CE版本的yum源)
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
#注意:非稳定版(testing)的Docker源默认未启用,可以通过以下命令启用:
sudo yum-config-manager --enable docker-ce-edge
#关闭非稳定版(testing)的源使用以下命令:
$ sudo yum-config-manager --disable docker-ce-edge

#3. 更新yum包索引
sudo yum makecache fast

#4. 安装最新版本的Docker
sudo yum -y install docker-ce
#查看可用的安装版本
yum list docker-ce.x86_64  --showduplicates |sort -r
#指定版本安装
sudo yum -y install docker-ce-<VERSION_STRING>

#5. 验证安装
$ sudo docker run hello-world
#如果验证成功,则会看到类似如下输出:
#Unable to find image 'hello-world:latest' locally
#latest: Pulling from library/hello-world
#如果输出如下,则说明docker服务还未运行,需要启动docker服务:
#docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
#See 'docker run --help'.
#启动docker服务:
sudo service docker start

#6. 升级安装
sudo yum makecache fast

rpm包安装Docker

Docker官方提供了CentOS 6/7两个发行版的.rpm二进制安装文件及src源安装文件,可以下载

#1. 安装Docker
sudo yum -y install /path/to/package.rpm
#2. 验证安装
sudo docker run hello-world
#3. Docker升级(不支持在线升级需先下载)
sudo yum -y upgrade /path/to/package.rpm

Docker的卸载

卸载Docker时,除了要卸载Docker程序外,还要手工删除使用过程中产生的镜像容器及自定义配置文件中。

#卸载Docker程序包
sudo yum -y remove docker-ce
#删除Docker镜像等
sudo rm -rf /var/lib/docker

4.命令集

查看帮助,比如:查看run帮助,docker run --help或docker help run

4.1 容器

容器具有良好的隔离性,容器之间是相互隔离、互不可见。

检查Docker版本

$sudo docker version

检查Docker状态

$sudo docker info

其返回信息包括:所有容器数量及各运行状态的容器数量、镜像数量、存储驱动等。

创建并运行容器

格式:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

-i:以交互模式启动容器

-t:为容器分配一个tty终端

# 在容器中运行"echo"命令,输出"hello word"

$sudo docker run image_name echo "hello word"

# 交互式shell进入容器中

$sudo docker run -i -t image_name /bin/bash

docker run命令的执行过程下:

1.首先检查本地是否image_name镜像
2.如果没有,连接Docker Hub Registry查看是否有名为image_name:latest镜像的镜像,该镜像指向latest LTS
3.找到镜像,将镜像下载到本地
4.Docker在文件系统内部使用这个镜像创建一个新容器,这个容器会有自已的网络、IP地址以及一个与本地宿主机通讯的桥接网络接口
5.容器创建完成后,执行所要执行的命令

查看容器# 查看当前所有正在运行的container
$sudo docker ps
# 查看所有的container
$sudo docker ps -a
# 查看最近一次启动的container
$sudo docker ps -l

容器内日常操作

 &安装软件

#查看主机名
root@af2099536638:/# hostname
#检查/etc/hosts文件
root@af2099536638:/# cat /etc/hosts

#查看容器中运行的进程
root@af2099536638:/# ps -aux
root@af2099536638:/# top

#其他监控
root@af2099536638:/# vmstat
#安装软件
root@af2099536638:~# apt-get update & apt-get install vim
#退出并返回宿主机(退出后,/bin/bash程序结束,容器也会随之停止)
root@af2099536638:~# exit

注:af2099536638代表容器ID

创建但不运行容器

$sudo docker create ubuntu

创建成功后会返回所创建容器的UUID,该ID做为容器标识,进行后续操作

命名容器

创建容器时,如果不指定名称,docker会为容器指定一个随机名称

--name参数,创建并命名容器

$sudo docker run -i -t --name itbilu_ubuntu ubuntu /bin/bash

注:容器命名必须唯一,如果名称重复时会创建失败

创建守护式容器

除交互式容器容器外,还可以创建没有交互会话的、长期运行的守护式容器(daemonized container)。实际上,我们使用容器在后台运行程序或服务,大多时候创建的都是守护式容器。我们使用-d参数,这个参数会告诉docker在后台运行容器(这个容器创建成功后,不会进入shell会话,而是会返回容器的UUID)。

#使用了while循环,这个循环会每秒打印一次hello world

$sudo docker run --name daemon_ubuntu -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

容器的自动重启

容器可能会由于某些错误而异常退出,默认情况下容器停止后不会自动重启。在运行容器时,可以设置--restart参数,容器退出时,--restart参数会检查容器的退出代码,并依此决定是否重启容器。可选值有:

no - 默认值,即:不会自动重启

always - 无论容器的退出代码是什么总是在退出后自动重启

no-failure[:NUM] - 退出代码非0时才自动重启。该参数还接受一个可选的NUM参数,表示尝试重启的次数

#异常退出后尝试自动重启5次
$sudo docker run --restart=no-failure:5 --name daemon_ubuntu -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

容器的启动

容器停止后,可以通过docker startdocker restart重新启动容器

附着到容器

Docker attach可以attach到一个已经运行的容器,然后进行命令执行的动作。

$sudo docker attach itbilu_ubuntu

注:退出容器shell后,会导致容器停止

容器日志查看

前面讲过后台运行的守护式容器,每秒会输出一次hello worldSTDOUT。查看可以通过:

格式:docker logs [OPTIONS] CONTAINER
#查看容器daemon_ubuntu的所有日志
$sudo docker logs daemon_ubuntu
#实时看到日志输出(类似tail -f命令)
$sudo docker logs -f daemon_ubuntu
#查看最后5行日志
$sudo docker logs -f --tail 5 daemon_ubuntu

模拟进入某容器

通过docker exec命令还可以启动新进程。在容器内启动的进程分为两类:后台任务和交互式任务。后台任务运行于容器内部没有交互需要。而交互式任务则会保持在前台,如果需要在容器内打开shell,则很适用创建交互式任务,交互式任务退出后,并不会导致守护式容器的停止。

格式:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
#在容器daemon_ubuntu内创建一个空的配置文件
$sudo docker exec -d daemon_ubuntu touch /etc/a_config_file
#创建交互式任务,与运行交互式容器时一样,需要添加-t、-i参数
$sudo docker exec -t -i daemon_ubuntu /bin/bash
注:docker exec命令在Docker 1.3+版本才可用

容器内进程查看

$sudo docker top daemon_ubuntu
容器状态查看

查看容器的详细使用统计信息,该命令可以同时查看一个或多个容器的统计信息,也可以通过-a参数对所有容器进行统计。

#查看容器daemon_ubuntu和itbilu_ubuntu的使用cpu、mem、I/O统计信息

$sudo docker stats daemon_ubuntu itbilu_ubuntu

注:docker stats命令在Docker 1.5+版本才可用

容器详细信息

该命令会返回容器的详细配置信息,包括:名称、命令、运行状态、网络配置等。

格式:docker inspect [OPTIONS] NAME|ID [NAME|ID...]
参数-f或--format,这个参数支持完整的GO语言模板,可以对输出结果进行格式化、筛选等。
#查看容器daemon_ubuntu的详细信息
$sudo docker inspect daemon_ubuntu
#查看容器daemon_ubuntu的运行状态
$sudo docker inspect -f '{{.State.Running}}' daemon_ubuntu
#查看容器daemon_ubuntu的IP地址
$sudo docker inspect -f '{{.NetworkSettings.IPAddress}}' daemon_ubuntu

停止容器

停止容器时,docker stop命令会向容器进程发送SIGTERM信号,收到该信号进程完成处理后结束。如果想快速停止可以使用docker kill,该命令会向容器进程发送SIGKILL信号。

#停止容器daemon_ubuntu
$sudo docker stop daemon_ubuntu
#也可以使用容器ID
$sudo docker stop 04e31cefe605

删除容器

容器不再使用后,可以使用docker rm命令将其删除。如果容器正在运行中,会删除失败。这时,可以先使用docker stop命令停止容器后再删除。或者使用-f参数强制删除:
导入导出#导出容器
$sudo docker export 7691a814370e > ubuntu.tar
#导入容器快照
$sudo docker import - test/ubuntu:v1.0
变更记录

列出一个容器里面被改变的文件或者目录,list列表会显示出三种事件,A 增加的,D 删除的,C 被改变的

$sudo docker diff Name/ID

拷贝到本地

从容器里面拷贝文件/目录到本地一个路径

$sudo docker cp Name:/container_path to_path
$sudo docker cp ID:/container_path to_path

4.2  镜像

查看本地镜像

通过镜像创建容器后,镜像从镜像仓库下载到本地。可以通过docker images命令查看本地主机上的镜像。

拉取(下载)镜像

使用docker run命令从镜像启动容器时,如果镜像在本地不存在,那么首先会从Docker Hub中下载该镜像。

#创建后,会在宿主机上保存了一个ubuntu镜像,其版本号为latest,即,最后一个版本的镜像
$sudo docker run -i -t --name itbilu_ubuntu ubuntu /bin/bash
为了加快容器启动时间,在运行容器前,可以通过docker pull命令将镜像先下载到本地
$sudo docker pull centos:centos6
#下载完成后可以查看
$sudo docker images centos

查找镜像有两种方式:Docker Hub在线查找镜像、docker search命令查找。

可以通过Docker Hub官网在线查找镜像:https://hub.docker.com

还可以使用 docker search [OPTIONS] TERM 命令查找镜像

$sudo docker search centos

镜像删除

删除镜像使用docker rmi命令,删除镜像时,我们会看到很多的Deleted行。这是因为,Docker镜像是一种以层(Layer)为单位的分层文件系统,每一行Deleted都表示一个镜像层被删除。

#也可以同时删除多个镜像
$sudo docker rmi image1 image2
#删除镜像时,也可以指定版本号
$sudo docker rmi centos:centos6

注:docker rmi只能删除本地镜像,并不能删除镜像仓库

查看详情

可参阅容器详细信息
另存为新镜像$sudo docker commit <container_id> <some_name>
导入导出#机器a保存
$sudo docker save image_name > /home/save.tar
#使用scp将save.tar拷到机器b上,然后:
$sudo docker load < /home/save.tar
显示历史$sudo docker history image_name

5. Dockerfile

语法比较复杂,后续专门讲

6. 管理工具

6.1 Docker machine

docker-machine 是docker官方提供的docker管理工具。通过docker-machine可以轻松的做到:

  • 在Windows平台和MAC平台安装和运行docker
  • 搭建和管理多个docker 主机
  • 搭建swarm集群

6.2 Swarm

Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些。

6.3 Docker compose

Docker Compose 是 Docker 容器进行编排的工具,定义和运行多容器的应用,可以一条命令启动多个容器。使用Compose 基本上分为三步:

  • Dockerfile 定义应用的运行环境
  • docker-compose.yml 定义组成应用的各服务
  • docker-compose up 启动整个应用

 

6.4 Shipyard

Docker图形页面管理工具基本常用的有三种: DOCKER UI,Shipyard,Portainer。对比后发现,Shipyard最强大,其次是Portainer,最后是Docker ui。它是一个集成管理docker容器、镜像、Registries的系统,它可以简化对横跨多个主机的Docker容器集群进行管理. 通过Web用户界面,你可以大致浏览相关信息,比如你的容器在使用多少处理器和内存资源、在运行哪些容器,还可以检查所有集群上的事件日志。
其特性主要包括:
1)支持节点动态集群,可扩展节点的规模(swarm、etcd方案)
2)支持镜像管理、容器管理、节点管理等功能
3)可视化的容器管理和监控管理
4)在线容console终端

6.5 cAdvisor

cAdvisor 是 google 开发的容器监控工具,cAdvisor 会显示当前 host 的资源使用情况,包括 CPU、内存、网络、文件系统等。cAdvisor 的一个亮点是它可以将监控到的数据导出给第三方工具,由这些工具进一步加工处理。

Reference

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值