ps: 本文仅供自己学习使用,文本来源于 docker从入门到实践一书.

1、什么是docker

   Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的cgroup,namespace,以及 AUFS ( AUFS有所有Union FS的特性,把多个目录,合并成同一个目录,并可以为每个需要合并的目录指定相应的权限) 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的libcontainer,从 1.11 开始,则进一步演进为使用 runC 和 containerd。
   Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。
  传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

docker_基础_1_第1张图片

docker_基础_1_第2张图片


2、为什么要使用 Docker?

作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。

  1. 更高效的利用系统资源
  2. 更快速的启动时间
  3. 一致的运行环境
  4. 持续交付和部署
  5. 更轻松的迁移
  6. 更轻松的维护和扩展

docker_基础_1_第3张图片

3、基本概念

三个基本概念 镜像( Image ) 容器( Container )仓库( Repository )

逻辑图
docker_基础_1_第4张图片

3.1、Docker 镜像

   Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

分层存储
   镜像充分利用union fs技术,将其设计为分层存储的架构。镜像只是一个虚拟的概念,其实际并非由一个文件组成,而是由一组文件系统组成,或者说是由多层系统联合组成,
   镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉, 文字太多看图
   分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
docker_基础_1_第5张图片

下图来自Docker的官方文档Layer,其很好的展示了Docker用UnionFS搭建的分层镜像。
docker_基础_1_第6张图片

3.2、Docker 容器

   容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样

   每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。

docker_基础_1_第7张图片

   容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

   按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
   数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。


3.3、Docker Registry

   一个 Docker Registry 中可以包含多个仓库( Repository );每个仓库可以包含多个标签( Tag );每个标签对应一个镜像。
   通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

   以centos为例,centos是仓库名字,不同版本表示为 centos:7.4 或者centos6.9来具体指定哪个版本的镜像,如果忽略那就视为 centos:latest

3.3.1、Docker Registry 公开服务

Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务
常见的有官方:docker hub 、国内镜像服务器一般被为加速器,常见的有阿里云,阿里云docker使用教程、daocloude加速器

3.3.2、Docker Registry 私有 服务

   开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。在官方的商业化版本 Docker Trusted Registry 中,提供了这些高级功能。
   除了官方的 Docker Registry 外,还有第三方软件实现了 Docker Registry API,甚至提供了用户界面以及一些高级功能。比如,VMWare Harbor 和 Sonatype Nexus。


4、安装

docker_基础_1_第8张图片

   同时 Docker 划分为 CE 和 EE。CE 即社区版(免费,支持周期三个月),EE 即企业版,强调安全,付费使用。
   Docker CE 每月发布一个 Edge 版本 (17.03, 17.04, 17.05...),每三个月发布一个 Stable 版本(17.03, 17.06, 17.09...),Docker EE 和 Stable 版本号保持一致,但每个版本提供一年维护。以下只提供在centos7.4上的安装

4.1、Cenos

系统: cetnos 7.4 Docker version 18.03.0-ce

    // 移动本地的yum源并下载阿里的yum源和阿里docker下载源
    $ mv /etc/yum.repos.d/Centos-*{,.bak}
    $ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    $ wget -O /etc/yum.repos.d/docker-re.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    // 新机器练习使用 关闭防火墙以及selinux
    $ systemctl disable firewalld
    $ systemctl stop firewalld
    $ setenforce 0 
 // 安装docker 并直接启动它
    $ yum -y install docker-ce
    $ systemctl start docker

    $ docker run hello-world   // 打印以下消息说明docker已经安装完成
       [root@docker ~]# docker run hello-world
        Unable to find image 'hello-world:latest' locally
        latest: Pulling from library/hello-world
        ca4f61b1923c: Pull complete 
        Digest: sha256:97ce6fa4b6cdc0790cda65fe7290b74cfebd9fa0c9b8c38e979330d547d22ce1
        Status: Downloaded newer image for hello-world:latest

        Hello from Docker!
        This message shows that your installation appears to be working correctly.

参考文档
  官方安装centos

4.2、使用镜像加速器

对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)

[root@docker ~]# vim /etc/docker/daemon.json
{
  "registry-mirrors": [
     "https://registry.docker-cn.com"
  ]
}

注意,一定要保证该文件符合 json 规范,否则 Docker 将不能启动。
之后重新启动服务。
$  systemctl daemon-reload
$  systemctl restart docker

注意:如果您之前查看旧教程,修改了 docker.service 文件内容,
请去掉您添加的内容( --registry-mirror=https://registry.docker-cn.com ).

5、使用镜像

   Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。

本章将介绍更多关于镜像的内容,包括:

  1. 从仓库获取镜像;
  2. 管理本地主机上的镜像;
  3. 介绍镜像实现的基本原理。

5.1、获取镜像

从docker镜像仓库获取镜像的命令是 docker pull 其命令格式为:
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。

  1. Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号] 。默认地址是 Docker
    Hub。
  2. 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名> 。对于 Docker Hub,如果不给出用户名,则默认为 library ,也就是官方镜像。

比如:
[root@docker ~]# docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
22dc81ace0ea: Pull complete
1a8b3c87dba3: Pull complete
91390a1c435a: Pull complete
07844b14977e: Pull complete
b78396653dae: Pull complete
Digest: sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6
Status: Downloaded newer image for ubuntu:16.04

// 获取官方镜像 library/ubuntu 仓库标签为16.04的镜像.

从下载过程中可以看到我们之前提及的分层存储的概念,镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。下载过程中给出了每一层的 ID 的前 12 位

运行第一个容器
有了镜像就可以运行容器了,启动ubuntu并启动里面的bash就直接直接这么使用

[root@docker ~]# docker run -it --rm ubuntu:16.04 bash
root@854fe5d52fcc:/# cat /etc/os-release 
NAME="Ubuntu"
VERSION="16.04.4 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.4 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

docker run 就是运行容器的命令,以上用到的参数详解

  • -it :这是两个参数,一个是 -i :交互式操作,一个是 -t 终端。我们这里打算进入bash 执行一些命令并查看返回结果,因此我们需要交互式终端.
  • --rm :这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm 。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
  • ubuntu:16.04 :这是指用 ubuntu:16.04 镜像为基础来启动容器。
  • bash :放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash
  • 最后直接通过exit就可以退出容器了。

5.2、列出镜像

列出已经下载的镜像可以直接使用 docker images

[root@docker ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               f975c5035748        3 weeks ago         112MB
centos              latest              2d194b392dd1        3 weeks ago         195MB
hello-world         latest              f2a91732366c        4 months ago        1.85kB

   列表包含了 仓库名 、 标签 、 镜像 ID 、 创建时间 以及 所占用的空间,镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个标签

    docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多

比如 创建两个centos容器,基础镜像100M,一个容器110M,实践占用可能就是120M而不是220M的空间

可以通过docker system df 便捷的查看,镜像、容器、数据卷所占用的空间

[root@docker ~]# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              3                   1                   307.9MB             307.9MB (99%)
Containers          1                   0                   0B                  0B
Local Volumes       0                   0                   0B                  0B
Build Cache                                                 0B                  0B

虚浮镜像
   指的是即没有标签,又没有仓库名,均为none,一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以使用如下命令

 docker image prune

中间层镜像
   为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的 docker image ls 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。

 docker images -a

   这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删

列出部分镜像
   在不要任何参数的情况下,docker image ls 会列出所有的顶级镜像,但是有时候我们只希望列出部分镜像。 docker image ls 有好几个参数可以帮助做到这个事情

根据仓库名列出镜像
[root@docker ~]# docker image ls centos
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              latest              2d194b392dd1        3 weeks ago         195MB

列出特定的某个镜像
[root@docker ~]# docker image ls ubuntu:16.04
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    ubuntu              16.04               f975c5035748        3 weeks ago         112MB

过滤参数 --filter 或者简写 -f ,列出在centos之后建立的镜像
[root@docker ~]# **docker image ls -f since=centos**
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    ubuntu              16.04               f975c5035748        3 weeks ago         112MB

之前就得使用before
[root@docker ~]# docker image ls -f before=centos
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    hello-world         latest              f2a91732366c        4 months ago        1.85kB

单独列出所有镜像的ID
[root@docker ~]# docker image ls -q
    f975c5035748
    2d194b392dd1
    f2a91732366c
  配合 --filter 或 -f  然后送给另一个docker做为参数, 从而针对这组实体成批的进行某种操作的做法在 Docker 命令行使用过程中非常常见,不仅仅是镜像,将来我们会在各个命令中看到这类搭配以完成很强大的功能

# 最为精确的是使用 --digest 选项查看长ID号
[root@docker ~]# docker images --digests
    REPOSITORY          TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
    ubuntu              16.04               sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6   f975c5035748        3 weeks ago         112MB
    centos              latest              sha256:dcbc4e5e7052ea2306eed59563da1fec09196f2ecacbe042acbdcd2b44b05270   2d194b392dd1        3 weeks ago         195MB
    hello-world         latest              sha256:97ce6fa4b6cdc0790cda65fe7290b74cfebd9fa0c9b8c38e979330d547d22ce1   f2a91732366c        4 months ago        1.85kB

使用 docker inspect [container_name] 可以获取该镜像的详细信息,包括制作者,适应架构 各层的数字摘要等。

加上-f 可以查看具体的json格式的值  键前面需要加上.比如 .RootFS
    docker inspect centos -f {{".RootFS"}}
    {layers [sha256:b03095563b7956c62ae5a6d20e5959a950e3b1a96d4404c00b7da7393847494a] }

使用history可以列出各层的创建信息.
$ docker history centos
    IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
    2d194b392dd1        4 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
               4 weeks ago         /bin/sh -c #(nop)  LABEL name=CentOS Base Im…   0B                  
               4 weeks ago         /bin/sh -c #(nop) ADD file:8d83f3e2c14f39e7f…   195MB               

5.3、删除本地镜像

如果要删除本地的镜像,可以使用 docker image rm 命令,其格式为:
$ docker image rm [选项] <镜像1> [<镜像2> ...]

使用docker rmi 也可以删除镜像 语法 docker rmi IMAGE ,IMAGE可以为标签也可以为ID

删除 docker rmi nginx 删除的只是某个标签,而不会将镜像直接删除,但当镜像只剩下一个的时候就需要注意了,此时在使用docker rmi 命令会彻底删除镜像

使用镜像ID删除镜像
    docker rmi [container_id]
如果提示有容器正在运行的,那么就需要先删除容器然后再删除镜像比如:
# 先运行一个容器
   docker run -dit centos echo "hello world"

# 删除镜像,提示有一个容器正在使用
   docker rmi 2d194b392dd1
    Error response from daemon: conflict: unable to delete 2d194b392dd1 (must be forced) - image is being used by stopped container 6449e8f68b63

# 查看容器,并删除它
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                      PORTS               NAMES
6449e8f68b63        centos              "echo 'hello world'"   19 seconds ago      Exited (0) 17 seconds ago                       eloquent_bohr

# 删除容器
$ docker rm 6449e8f68b63

# 此时在删除镜像就没有问题了
  docker rmi 2d194b392dd1
    Untagged: centos:latest
    Untagged: centos@sha256:dcbc4e5e7052ea2306eed59563da1fec09196f2ecacbe042acbdcd2b44b05270
    Deleted: sha256:2d194b392dd16955847a14f969b2dd319251471ffa6356be6d8f16c5bf53db9b
    Deleted: sha256:b03095563b7956c62ae5a6d20e5959a950e3b1a96d4404c00b7da7393847494a

# 查看镜像
[root@docker ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              c5355f8853e4        4 days ago          107MB
ubuntu              16.04               f975c5035748        3 weeks ago         112MB
centos              latest              2d194b392dd1        3 weeks ago         195MB
hello-world         latest              f2a91732366c        4 months ago        1.85kB

# 使用短ID删除镜像
[root@docker ~]# docker image rm c53
    Untagged: redis:latest
    Untagged: redis@sha256:fed1e53de35ffdf2d9e95afd20df938e4790fb52bc5093987e6f6649bd413786
    Deleted: sha256:c5355f8853e4174a55144edfec23ac37f5bb2200ed838dab53c13c7cc835ab15
    Deleted: sha256:65f4f6d6a5f66e424046ccfe359ba5668f2905ec688a8ca62079dfd7946bb989
    Deleted: sha256:3f490bf3919344e7ba4acd58824bd24a9479374d6b1d67b59bab7cda118572cf
    Deleted: sha256:678c0094f27aa1100c30946b9d55981537a107639e71527b5f54ff3de54c12d7
    Deleted: sha256:05ffc1bd56d27d29a8a9c36c77dca93ba19dabc77adaf9d3a1ff44c760c3690d
    Deleted: sha256:1df131a973126fb31c35ca41b2071da4bffcbed7ab8456635b699772e9ad0d8b
    Deleted: sha256:43efe85a991cac5894f91ee8f45b328bbacd14966d89a8a00b0d06060c64b5ad

# 使用仓库名+标签来删除镜像
[root@docker ~]# docker image rm centos:latest
Untagged: centos:latest
Untagged: centos@sha256:dcbc4e5e7052ea2306eed59563da1fec09196f2ecacbe042acbdcd2b44b05270
Deleted: sha256:2d194b392dd16955847a14f969b2dd319251471ffa6356be6d8f16c5bf53db9b
Deleted: sha256:b03095563b7956c62ae5a6d20e5959a950e3b1a96d4404c00b7da7393847494a

[root@docker ~]# docker image rm ubuntu@sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6
    Untagged: ubuntu@sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6

组合命令

# 删除所有名叫Ubuntu名称的镜像
[root@docker ~]# docker image rm $(docker image ls ubuntu)

5.3、创建镜像

该方法主要使用docker commit 命令,格式: docker commit [OPTIONS ] CONTAINER 主要选择包含
    -a,--author="": 作者信息
    -c: 提交的时候执行Dockerfile指令
    -m:提交消息
    -p: 提交时暂停容器运行
演示如何创建一个新镜像
1、先创造一个容器
    $ docker run -it centos /bin/bash
    $ touch test
    $ test

2、容器ID为 dff823383c0f   使用docker ps -a 查看

3、创建镜像
 $ docker commit -m "this is a new file" -a "Docker tetst" dff823383c0f test/v1.0
 $ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    test/v1.0           latest              cae335780627        3 seconds ago       195MB

5.4、利用 dockerfile 定制镜像

   Dockerfile定制镜像: https://blog.51cto.com/xiong51/2093846

5.5、保存镜像

   docker save | load 
# 保存  两种方式都能保存
   $ docker save -o centos.tar.gz centos
     $ docker save centos > centos2.tar.gz

# 导入
  $ docker load --input centos2.tar.gz 
  $ docker load < centos2.tar.gz 

导入成功后可以使用docker images查看

5.6、上传镜像

可以使用 docker push上传镜像到仓库 默认为docker hub 命令格式为
docker push NAME[:tag] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]

例如用户上传本地的test:v1.0 可以先添加新的标签 nginx/test:v1.0 

    docker tag test:v1.0 nginx/test:v1.0
    docker push  nginx/test:v1.0

第一次上传,需要输入登录信息或注册

6、操作容器

   容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用.

 本章将具体介绍如何来管理一个容器,包括创建、启动和停止等。

6.1、启动容器

   启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态( stopped )的容器重新启动。
   因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器

# 创建容器
 docker create -it centos 
      a0cc4b8c60c68dec064d393f96f4fd90533c890e60a2ea88736c0190496835e6

# 使用docker create 创建的容器处于停止状态,可以使用docker start 启动它

# create 分为容器运行模式相关,容器和环境配置相关,与容器资源限制和安全保护相关参数
    官方文档:[docker create]:(https://docs.docker.com/engine/reference/commandline/create/)

# 启动容器,并打印hello world
[root@docker ~]# docker run centos /bin/echo "hello world"
hello world

# 启动一个Bash终端,允许用户交互
[root@docker ~]# docker run -it centos /bin/bash
[root@d8ad8afa2f16 /]# 
       -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,
       -i 则让容器的标准输入保持打开。

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

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

启动已终止的容器

# 先找一个过期的容器
[root@docker ~]# docker  ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
d8ad8afa2f16        centos              "/bin/bash"              10 minutes ago      Exited (0) 2 minutes ago                        reverent_stallman

# 利用docker container start ID,直接将一个终止的容器启动运行
[root@docker ~]# docker  container start d8ad8afa2f16
d8ad8afa2f16
[root@docker ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d8ad8afa2f16        centos              "/bin/bash"         18 minutes ago      Up 4 seconds                            reverent_stallman

--log-device   
选项   none  syslog 

none: 不输出日志
syslog string : 指定机器的日志收集地址
fluentd: 选定驱动。

--restart
参数: alwary :一直到重启成功
       on-failure:nums 指定重新多少次超过就不在尝试了

--memory-swappiness int: 0-10   0表示禁用
--storage-opt list:只支持devicemapper存储驱动,只允许使用多少磁盘

docker stats container_name 动态查看容器的利用率
docker update 对容器的硬件资源做出限制
docker events  事件查看针对当前docker所有的运行状态

6.2、后台运行

   需要让 Docker 在后台运行,而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现

# 不加 -d 参数
[root@docker ~]# docker run centos /bin/bash -c "echo 'hello world'"
hello world
容器会把输出的结果(stdout)打印在屏幕上面

# 使用-d参数
[root@docker ~]# docker run -d  centos /bin/bash -c "echo 'hello world'"
095df481f4aadf3a291eb44fa3873eba83c2ef022e558adb40482aaaececde6f
此时容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上面(输出结果可以用docker logs 查看)

[root@docker ~]# docker logs 095df481f4aadf3a291eb44fa3873eba83c2ef022e558adb40482aaaececde6f
hello world

注: 容器是否会长久运行,是和 docker run 指定的命令有关,和 -d 参数无关。

使用 -d 参数启动会返回一个唯一ID,也可以通过 docker container ls查看容器信息

要获取容器输出信息可以使用docker container logs IDname查看
[root@docker ~]# docker container logs 095df481f4aadf3a291eb44fa3873eba83c2ef022e558adb40482aaaececde6f
hello world

6.3、终止容器

可以使用docker container stop来终止一个正在运行的容器
  例如对于上一章节中只启动了一个终端的容器,用户通过 exit 命令或 Ctrl+d 来退出终端时,所创建的容器立刻终止

# 终止容器
  $ docker stop [container_id]

# 查看已终止状态的容器
[root@docker ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
095df481f4aa        centos              "/bin/bash -c 'echo …"   7 minutes ago       Exited (0) 7 minutes ago                        epic_chandrasekhar

# 查看启动状态的容器
[root@docker ~]# docker container ls 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d8ad8afa2f16        centos              "/bin/bash"         32 minutes ago      Up 13 minutes                           reverent_stallman

# 停止一个容器
[root@docker ~]# docker container stop d8ad8afa2f16
d8ad8afa2f16
# 再次查看就没了
[root@docker ~]# docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker ~]# 

终止状态的容器可以再次通过docker container start ID启动
也可以通过 docker container restart ID 重新启动容器

6.4、进入容器

使用-d参数,容器启动会自动进行后台。
某些时候需要进入容器进行操作,包括使用 docker attach 命令或 docker exec 命令,推荐使用 docker exec 命令,

attach 命令

# 启动一个容器,让它启动后直接后台运行
[root@docker ~]# docker run -itd centos
55d17f9db37a93d99311ddf6f6c4e0798f42de5c05c498139906e24d3875ec17

# 查看启动状态的容器
[root@docker ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
55d17f9db37a        centos              "/bin/bash"         5 seconds ago       Up 4 seconds                            heuristic_nightingale

# 附加到容器中
[root@docker ~]# docker attach 55d17f9db37a
[root@55d17f9db37a /]# ls
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@55d17f9db37a /]# exit
exit

# 当输入exit的时候容器会直接退出,而exec不会
[root@docker ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker ~]# 

exec命令

-d :分离模式: 在后台运行
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端

# 先启动一个容器 
[root@docker ~]# docker run -dit centos
0bd95738df1f7ee6104c1be16fc24e82735e0e0ce7d04cc698fb9b679cbf1119

# 查看容器
[root@docker ~]#  docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0bd95738df1f        centos              "/bin/bash"         5 minutes ago       Up 5 minutes                            happy_raman

# 在容器中开启一个交互模式终端 
[root@docker ~]# docker exec -it 0bd9 /bin/bash
[root@0bd95738df1f /]# exit
exit

# exec使用exit并不会像attach一样直接退出容器
[root@docker ~]# docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0bd95738df1f        centos              "/bin/bash"         6 minutes ago       Up 6 minutes                            happy_raman

# 直接从没有附加stdin打开 等于进去输入了一次ls
[root@docker ~]# docker exec -i 0bd9 ls /
anaconda-post.log
bin
dev
etc

# 查看日志
[root@docker ~]# docker exec -i 0bd9  cat /anaconda-post.log
xxx

// 也可以直接执行脚本 docker exec -i 0bd9 bash /tmp/a.sh

6.5、导出和导入容器

6.5.1、导出容器

   如果要导出本地某个容器,可以使用 docker export 命令

# 查看容器
[root@docker ~]# docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0bd95738df1f        centos              "/bin/bash"         13 minutes ago      Up 13 minutes                           happy_raman

# 导出centos容器保存到本地
[root@docker ~]# docker export 0bd95738df1f > centos.tar

# 导出容器到本地
[root@docker ~]# du -sh centos.tar 
    195M    centos.tar

6.5.2、导入容器

   可以直接使用 docker import 命令

# 本地导入容器
[root@docker ~]# cat centos.tar | docker import - test/centos:v1.0
sha256:4ba4cce8fb6e3800702cbd4e64d1549c56df43bf8cf39207845a35c25eaaa454

# 查看导入的容器名称
[root@docker ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test/centos         v1.0                4ba4cce8fb6e        3 seconds ago       195MB

# 此外,也可以通过指定 URL 或者某个目录来导入,例如
$ docker import http://example.com/exampleimage.tgz example/imagerepo

扩展

export
   export命令用于持久化容器(不是镜像)
     语法:  docker export [container_ID] > /dir_path/filename.tar

import 
    可以指定镜像名称
    语法: cat /dir_path/filename.tar | docker import  - name/name:tag

save
    Save命令用于持久化镜像(不是容器)
    语法:  docker save [container_ID] > /dir_path/filename.tar

load
    语法: docker load > /dir/filename.tar 

导出导入 export import
会丢失所有的历史,无法回滚到之前的层,节省硬盘空间

save load
不会丢失历史, 使用保存后再加载的方式持久化整个镜像,就可以做到层回滚(可以执行docker tag 来回滚之前的层

6.6、删除并清理容器

6.6.1、删除容器

可以使用 docker container rm [container_id]

# 先查看运行容器 docker container ls

# 强制删除 -f
[root@docker ~]# docker container rm -f 0bd9
0bd9

# 最后查看是否删除 docker container ls

6.6.2、清理所有处于终止状态的容器

用 docker container ls -a 命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用 docker container prune 命令可以清理掉所有处于终止状态的容器

[root@docker ~]#  docker container prune
    WARNING! This will remove all stopped containers.
    Are you sure you want to continue? [y/N] y
    Deleted Containers:
    55d17f9db37a93d99311ddf6f6c4e0798f42de5c05c498139906e24d3875ec17
    095df481f4aadf3a291eb44fa3873eba83c2ef022e558adb40482aaaececde6f
    42779ba00905a54901b58b21f4f449a94c4de900c4b322412dc9467fcc2584f3
    d8ad8afa2f16a073af275adde435a03e80f3981cfde0a3d3697159010067fee5
    10daa1261c0406927627d15e799b5abb56157a85bffe7206e9defc46cdf84a44
    1df5c3d2306053056442b14ebdd4b4af555c712cd89f0da4273c15df250f00f2

# 再次查看容器就全空了
[root@docker ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker ~]# 

7、仓库

仓库注册服务器(registry):可以多含多个仓库,一个仓库可以存放多个镜像文件,通过不同的标签来进行区分
查找镜像
    docker search name
下载镜像
    docker pull name 

7.1、实例:搭建一个本地私有仓库

# 下载官方提供的registry私有仓库镜像来简单搭建一套本地的私有仓库
  docker run -d -p 5000:5000 registry
        Unable to find image 'registry:latest' locally
        latest: Pulling from library/registry
        81033e7c1d6a: Pull complete 
        b235084c2315: Pull complete 
        c692f3a6894b: Pull complete 
        ba2177f3a70e: Pull complete 
        a8d793620947: Pull complete 
        Digest: sha256:672d519d7fd7bbc7a448d17956ebeefe225d5eb27509d8dc5ce67ecb4a0bce54
        Status: Downloaded newer image for registry:latest
        0290c46fa317641bf2dd9e8afdbb979090997d0c5f8ce257790f0e832960b617

# 自动下载并启动了一个registry容器创建了一个本地的私有仓库服务

# 也可以将镜像文件存放在本地指定的路径 通过 -v 参数
    $ docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry
            681f8fb164e69f78f9a53f24b91408f98122a780746dcb7bff3bc5678d1aa1ef
默认情况下,会将仓库创建在容器的/tmp/registry目录,上面例子将上传的镜像放到 /opt/data/registry/ 目录下,启动私有仓库,监听端口为5000

查看仓库
  Host# curl  192.168.9.222:5000/v2/_catalog
    {"repositories":[]}

[root@dockers pipework]# docker tag alpine 192.168.9.222:5000/alpine:v1
[root@dockers pipework]# docker tag alpine 192.168.9.222:5000/alpine:v2

docker push 192.168.9.222:5000/alpine:v1
The push refers to repository [192.168.9.222:5000/alpine]
Get https://192.168.9.222:5000/v2/: http: server gave HTTP response to HTTPS client

# 添加信任
vim /etc/docker/daemon.json
    { "insecure-registries":["192.168.9.222:5000"]}

# 然后重启docker  
systemct restart docker

# 打四个tag用于测试
docker push 192.168.9.222:5000/alpine:v1
docker push 192.168.9.222:5000/alpine:v2
docker tag registry 192.168.9.222:5000/registry:v1
docker tag registry 192.168.9.222:5000/registry:v2

# 注意:一个注册仓库可以有多个仓库,一个仓库可以有多个版本
Host# curl 192.168.9.222:5000/v2/_catalog
    {"repositories":["alpine","registry"]}

Host# curl 192.168.9.222:5000/v2/alpine/tags/list
    {"name":"alpine","tags":["v1","v2"]}

Host#  curl 192.168.9.222:5000/v2/registry/tags/list
{"name":"registry","tags":["v1","v2"]}

# 下载测试
Host#  docker pull 192.168.9.222:5000/alpine:v2
Host#  docker pull 192.168.9.222:5000/registry:v2

Host#  docker images
192.168.9.222:5000/registry   v2                  d1fd7d86a825        3 months ago        33.3MB
192.168.9.222:5000/alpine     v2                  3fd9065eaf02        3 months ago        4.14MB