本文发自 http://www.binss.me/blog/learn-docker-with-me-about-commands/,转载请注明出处。

在安装篇(http://www.binss.me/blog/learn-docker-with-me-about-installation/)中,我们已经安装了Docker,接下来,我将会介绍如何使用Docker。

在Docker中,有几个重要的概念,在这里先简单介绍一下:

镜像(image)

镜像是一个只读的模板,包含的特定的环境。比如可以包含一个完整的ubuntu环境,或者只有一个nginx服务器。

容器(container)

容器是从镜像创建的运行实例(本质上是在镜像上加了一层可写层来保存变更)。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。

仓库(registry)

仓库是集中存放镜像文件的场所(可以联想git仓库)。公用(Public)仓库有Docker Hub,它由Docker公司维护,提供官方维护版本的镜像,供用户下载使用。用户也可以在本地网络或VPS内创建一个私有(Private)仓库。镜像可以通过push上传到仓库,也可以通过pull下载到本地。

镜像库(repository)

镜像库包含了某一类镜像的所有版本。只包含库名的repository为官方顶层镜像库,如ubuntu,而包含用户名和库名的repository为用户镜像库,如 binss/ubuntu。镜像库的镜像以标签(Tag)进行区分。一个仓库包含了N个镜像库,如ubuntu、nginx、mysql。

因此我们的使用流程通常是这样的:

获取镜像->使用镜像创建容器->使用容器

下面详细介绍该流程:

  1. 获取镜像

    $ docker pull [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]

    我们直接下载ubuntu的最新镜像:

    $ docker pull ubuntu

    该命令实际上相当于:

    $ docker pull registry.hub.docker.com/ubuntu:latest

    因为未指定REGISTRY_HOST,所以默认从官方仓库registry.hub.docker.com下载,而由于未指定TAG,于是默认下载了最新的镜像(TAG为latest)。用户可以自己指定仓库、TAG,但不是必须。

  2. 使用镜像创建容器

    镜像下载完成后,我们可以查看本地的镜像列表:

    $ docker images
    REPOSITORY(仓库名)             TAG(标记,一般标版本号)  IMAGE ID(镜像唯一id)    CREATED(创建时间)    VIRTUAL SIZE(大小)
    ubuntu                        latest                 91e54dfb1179           2 weeks ago         188.4 MB

    使用run命令来运行镜像,并交互式进入容器中(如果不使用: 指定TAG,默认使用latest标记的镜像):

    $ docker run -it ubuntu:latest /bin/bash

    其中,-i 表示使用交互模式,始终保持输入流开放。-t 表示分配一个伪终端。

    此时我们可以另外通过ps 看到新容器(58edfa0fb8a4)被创建且运行:

    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    58edfa0fb8a4        ubuntu:latest       "/bin/bash"         9 seconds ago       Up 8 seconds                            silly_babbage

    由于刚刚已经通过run交互式进入容器中,我们可以像在VPS上那样操作。如图,我在home目录下新建了binss文件夹,并在里面新建了test.txt文件。

    通过exit可以退出容器。此时通过ps 我们已经看不到容器,表示容器此时已经停止运行。通过加上-a选项可以看到所有的容器(包括已经停止的):

    $docker ps -a

    可以看到

    58edfa0fb8a4        ubuntu:latest      "/bin/bash"         11 minutes ago      Exited (0) 8 seconds ago                  silly_babbage

    exited(0)表示容器正常退出。

  3. 再次启动与进入容器

    由于我们run的时候没起名字,所以被取了silly_babbage(下次记得使用--name指定)。不爽,修改之~

    $ docker rename silly_babbage binss

    然后启动容器,为了方便,我们可以使用容器的名字来代替它的id使用。

    $ docker start binss

    交互式进入容器:

    $ docker exec -it binss bash

    在/home/binss 目录下,我们看到了熟悉的test.txt。

    注意:这里强烈建议不要使用attach进入容器,因为attach是同步的:当多个窗口同时attach到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作。当某个窗口退出时,容器会被停止。此外,使用exec进入的容器在exit时不会自动停止,需要手动调用停止:

    $ docker stop binss
  4. 分享容器/镜像

    现在我们想将我们修改过(加了test.txt)的容器导出到文件,并分享给其他人。Docker提供了两种方法。

    第一种是直接由容器导出镜像:

    $ docker export binss > /Users/bin/Desktop/binss_image.tar

    命令执行后,容器binss(58edfa0fb8a4)会被保存为镜像binss_image.tar。此时可以分享给他人。

    其他人可以使用import导入镜像:

    cat ~/Desktop/binss_image.tar | docker import - binss/share:test

    这条命令从~/Desktop/binss_image.tar导入镜像,并设置镜像的REPOSITORY为binss/share,TAG为test,使用ps可以查看到导入成功:

    REPOSITORY                    TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    binss/share                   test                c2e25de3adc7        6 minutes ago       188.2 MB

    然后再次使用run来启动容器,并命名为share_binss:

    $ docker run -it --name share_binss binss/share:test bash

    可以在/home/binss 目录下找到test.txt,验证了export和import的可用性。

    第二种方法是先提交修改到镜像,然后直接导出镜像:

    首先提交容器binss的修改到镜像ubuntu:v1 ,并设置Author为binss,Comment为"add test.txt"(类似git的Comment)

    $ docker commit -a binss -m "add test.txt" binss ubuntu:v1

    然后可以看到在image列表多了镜像ubuntu:v1 :

    REPOSITORY                    TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    ubuntu                        v1                  9d2edf78a252        9 seconds ago       188.4 MB

    可以使用inspect查看镜像的详细信息:

    $ docker inspect ubuntu:v1

    结果如图,我们找到了刚刚的Comment信息:

    也可以通过history查看到:

    然后保存镜像:

    $ docker save ubuntu:v1 > ~/Desktop/binss_image.tar

    使用时,通过load导入:

    cat ~/Desktop/binss_image.tar | docker load

    那么这两种方式导出的镜像到底有什么区别呢?

    save会保存镜像的历史状态(history)和层信息(Comment等),而export不保存。这意味着save产生的镜像能够通过tag命令实现层回滚,而export的不行。从大小上可以看出save导出的镜像比export导出的大一些。

    两种方式产生的镜像文件大小对比图。

  5. 删除镜像/容器

    最后还要介绍删除命令:

    删除刚刚导入的镜像binss/share:test

    $ docker rmi binss/share:test

    发现删除失败了:

    Error response from daemon: Conflict, cannot delete 534b8e742b04 because the container d34f998b482d is using it, use -f to force
    Error: failed to remove images: [binss/share:test]

    这是因为我们刚刚通过该镜像创建的容器share_binss(d34f998b482d)依赖于该镜像,所以要想删除该镜像,必须先删除依赖的容器:

    $ docker rm share_binss

    删除成功后,就可以用刚刚的命令删除镜像了。

以上是一些常用的指令,如欲了解更多的指令及相关详细用法,请参考官方文档:

https://docs.docker.com/reference/commandline/cli/