操作 Docker 容器

                                         操作 Docker 容器


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

1、启动容器

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

2、新建并启动

所需要的命令主要为 docker run 。
例如,下面的命令输出一个 “Hello World”,之后终止容器。
$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world
这跟在本地直接执行 /bin/echo 'hello world' 几乎感觉不出任何区别。
下面的命令则启动一个 bash 终端,允许用户进行交互。
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
root@af8bae53bdd3:/#
其中, -t 选项让Docker分配一个伪终端( pseudo-tty) 并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。
在交互模式下,用户可以通过所创建的终端来输入命令,例如
root@af8bae53bdd3:/# pwd
/
root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin  srv sys tmp usr var
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  •         检查本地是否存在指定的镜像,不存在就从公有仓库下载

  •         利用镜像创建并启动一个容器

  •         分配一个文件系统,并在只读的镜像层外面挂载一层可读写层

  •         从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去

  •         从地址池配置一个 ip 地址给容器

  •         执行用户指定的应用程序

  •         执行完毕后容器被终止

3、启动已终止容器

可以利用 docker start 命令,直接将一个已经终止的容器启动运行。容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。可以在伪终端中利用 ps 或 top 来查看进程信息。
root@ba267838cc1b:/# ps
PID TTY TIME CMD
1 ? 00:00:00 bash
11 ? 00:00:00 ps
可见,容器中仅运行了指定的 bash 应用。这种特点使得 Docker 对资源的利用率极高,是货真价实的轻量级虚拟化。

扫描二维码关注公众号,回复: 2712671 查看本文章

4、后台(background)运行

更多的时候,需要让 Docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现。下面举两个例子来说明一下。如果不使用 -d 参数运行容器。
$ sudo docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
hello world
容器会把输出的结果(STDOUT)打印到宿主机上面。如果使用了 -d 参数运行容器。
$ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a
此时容器会在后台运行并不会把输出的结果(STDOUT)打印到宿主机上面(输出结果可以用docker logs 查看)。
注: 容器是否会长久运行,是和docker run指定的命令有关,和 -d 参数无关。使用 -d 参数启动后会返回一个唯一的 id,也可以通过 docker ps 命令来查看容器信息。
要获取容器的输出信息,可以通过 docker logs 命令。
$ sudo docker logs [container ID or NAMES]

5、终止容器

        可以使用 docker stop 来终止一个运行中的容器。此外,当Docker容器中指定的应用终结时,容器也自动终止。 例如对于上一章节中只启动了一个终端的容器,用户通过 exit 命令或 Ctrl+d 来退出终端时,所创建的容器立刻终止。终止状态的容器可以用 docker ps -a 命令看到。处于终止状态的容器,可以通过 docker start 命令来重新启动。此外, docker restart 命令会将一个运行态的容器终止,然后再重新启动它。

6、进入容器

        在使用 -d 参数时,容器启动后会进入后台。 某些时候需要进入容器进行操作,有很多种方法,包括使用 docker attach 命令或 nsenter 工具等。
        attach 命令
docker attach 是Docker自带的命令。下面示例如何使用该命令。
$ sudo docker run -idt ubuntu
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
$ sudo docker ps
CONTAINER ID   IMAGE            COMMAND   CREATED            STATUS  PORTS        NAMES
243c32535da7    ubuntu:latest    "/bin/bash"     18 seconds ago   Up           17 seconds  nostalgic_hypatia
$sudo docker attach nostalgic_hypatia
root@243c32535da7:/#
但是使用 attach 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。
        nsenter 命令
安装nsenter 工具在 util-linux 包2.23版本后包含。 如果系统中 util-linux 包没有该命令,可以按照下面的方法从源码安装。
$ cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
$ ./configure --without-ncurses
$ make nsenter && sudo cp nsenter /usr/local/bin

7、导出和导入容器

        导出容器
如果要导出本地某个容器,可以使用 docker export 命令。
$ sudo docker ps -a
CONTAINER ID   IMAGE            COMMAND     CREATED       STATUS   PORTS           NAMES
7691a814370e     ubuntu:14.04  "/bin/bash"       36 hours ago   Exited (0)  21 hours ago  test
$ sudo docker export 7691a814370e > ubuntu.tar
这样将导出容器快照到本地文件。
        导入容器快照
可以使用 docker import 从容器快照文件中再导入为镜像,例如
$ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0
$ sudo docker images
REPOSITORY TAG IMAGE ID         CREATED                  VIRTUAL SIZE
test/ubuntu       v1.0 9d37a6082e97 About a minute ago    171.3 MB
此外,也可以通过指定 URL 或者某个目录来导入,例如
$sudo docker import http://example.com/exampleimage.tgz example/imagerepo

8、删除容器

可以使用 docker rm 来删除一个处于终止状态的容器。 例如
$sudo docker rm trusting_newtontrusting_newton
如果要删除一个运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL信号给容器。
        清理所有处于终止状态的容器
用 docker ps -a 命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用 docker rm $(docker ps -a -q) 可以全部清理掉。
        *注意:这个命令其实会试图删除所有的包括还在运行中的容器,不过就像上面提过的 docker rm 默认并不会删除运行中的容器。

9、访问仓库

        仓库( Repository) 是集中存放镜像的地方。一个容易混淆的概念是注册服务器( Registry) 。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址dl.dockerpool.com/ubuntu 来说, dl.dockerpool.com 是注册服务器地址, ubuntu 是仓库名。
大部分时候,并不需要严格区分这两者的概念。

10、私有仓库

        有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用。docker-registry 是官方提供的工具,可以用于构建私有的镜像仓库。
        安装运行 docker-registry
容器运行在安装了 Docker 后,可以通过获取官方 registry 镜像来运行。
$ sudo docker run -d -p 5000:5000 registry
这将使用官方的 registry 镜像来启动本地的私有仓库。 用户可以通过指定参数来配置私有仓库位置,例如配置镜像存储到 Amazon S3 服务。
$ sudo docker run \
                -e SETTINGS_FLAVOR=s3 \
                -e AWS_BUCKET=acme-docker \
                -e STORAGE_PATH=/registry \
                -e AWS_KEY=AKIAHSHB43HS3J92MXZ \
                -e AWS_SECRET=xdDowwlK7TJajV1Y7EoOZrmuPEJlHYcNP2k4j49T
\
                -e SEARCH_BACKEND=sqlalchemy \
                -p 5000:5000 \
                registry
`
此外,还可以指定本地路径( 如 /home/user/registry-conf ) 下的配置文件。
        在私有仓库上传、下载、搜索镜像
创建好私有仓库之后,就可以使用 docker tag 来标记一个镜像,然后推送它到仓库,别的机器上就可以下载下来了。例如私有仓库地址为192.168.7.26:5000 。先在本机查看已有的镜像。
$ sudo docker images
REPOSITORY TAG            IMAGE ID          CREATED     VIRTUAL SIZE
ubuntu           latest             ba5877dc9bec   6 weeks ago  192.7 MB
使用 docker tag 将 ba58 这个镜像标记为 192.168.7.26:5000/test ( 格式为 docker tag IMAGE[:TAG] [REGISTRYHOST/]
[USERNAME/]NAME[:TAG] ) 。
$ sudo docker tag ba58 192.168.7.26:5000/test
root ~ # docker images
REPOSITORY    TAG                                            IMAGE ID           CREATED         VIRTUAL SIZE
ubuntu 14.04     192.168.7.26:5000/test   latest     ba5877dc9bec    6 weeks ago     192.7 MB
使用 docker push 上传标记的镜像。
$ sudo docker push 192.168.7.26:5000/test
The push refers to a repository [192.168.7.26:5000/test] (len: 1) Sending image list
Pushing repository 192.168.7.26:5000/test (1 tags)
Image 511136ea3c5a already pushed, skipping
Image 9bad880da3d2 already pushed, skipping
Image 25f11f5fb0cb already pushed, skipping
Image ebc34468f71d already pushed, skipping
Image 2318d26665ef already pushed, skipping
Image ba5877dc9bec already pushed, skipping
Pushing tag for rev [ba5877dc9bec] on {http://192.168.7.26:5000/v1/repositories/test/tags/latest}
用 curl 查看仓库中的镜像。$ curl http://192.168.7.26:5000/v1/search
{"num_results": 7, "query": "", "results": [{"description": "","name": "library/miaxis_j2ee"}, {"description": "", "name": "library/tomcat"}, {"description": "", "name": "library/ubuntu"}, {"description": "", "name": "library/ubuntu_office"}, {"description": "", "name": "library/desktop_ubu"}, {"description": "", "name": "dockerfile/ubuntu"}, {"description": "", "name": "library/test"}]}
这里可以看到 {"description": "", "name": "library/test"} ,表明镜像已经被成功上传了。
现在可以到另外一台机器去下载这个镜像。
$ sudo docker pull 192.168.7.26:5000/test
Pulling repository 192.168.7.26:5000/test
ba5877dc9bec: Download complete
511136ea3c5a: Download complete
9bad880da3d2: Download complete
25f11f5fb0cb: Download complete
ebc34468f71d: Download complete
2318d26665ef: Download complete
$ sudo docker images
REPOSITORY  TAG IMAGE ID   CREATED VIRTUAL SIZE
192.168.7.26:5000/test  latest  ba5877dc9bec 6 weeks ago 192.7 MB

11、Docker 数据管理

容器中管理数据主要有两种方式:
数据卷( Data volumes)
数据卷容器( Data volume containers)
        数据卷
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用

  • 对数据卷的修改会立马生效

  • 对数据卷的更新,不会影响镜像

  • 数据卷默认会一直存在,即使容器被删除

        *注意:数据卷的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷。
        创建一个数据卷
在用 docker run 命令的时候,使用 -v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。下面创建一个名为 web 的容器,并加载一个数据卷到容器的 /webapp 目录。
$ sudo docker run -d -P --name web -v /webapp training/webapp python app.py
        *注意:也可以在 Dockerfile 中使用 VOLUME 来添加一个或者多个新的卷到由该镜像创建的任意容器。
        删除数据卷
数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。无主的数据卷可能会占据很多空间,要清理会很麻烦。Docker官方正在试图解决这个问题,相关工作的进度可以查看这个PR。
        查看数据卷的具体信息
在主机里使用以下命令可以查看指定容器的信息
$ docker inspect web

12、自定义容器命名

        连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。虽然当创建容器的时候,系统默认会分配一个名字。自定义命名容器有2个好处:自定义的命名,比较好记,比如一个web应用容器我们可以给它起名叫web当要连接其他容器时候,可以作为一个有用的参考点,比如连接web容器到db容器使用 --name 标记可以为容器自定义命名。
$ sudo docker run -d -P --name web training/webapp python app.py
        使用 docker ps 来验证设定的命名。注意:容器的名称是唯一的。如果已经命名了一个叫 web 的容器,当你要再次使用web 这个名称的时候,需要先用 docker rm 来删除之前创建的同名容器。
        在执行 docker run 的时候如果添加 --rm 标记,则容器在终止后会立刻删除。注意, --rm 和 -d 参数不能同时使用。
        容器互联
使用 --link 参数可以让容器之间安全的进行交互。
下面先创建一个新的数据库容器。
$ sudo docker run -d --name db training/postgres
删除之前创建的 web 容器
$ docker rm -f web
然后创建一个新的 web 容器,并将它连接到 db 容器
$ sudo docker run -d -P --name web --link db:db training/webapp  python app.py
此时,db 容器和 web 容器建立互联关系。--link 参数的格式为 --link name:alias ,其中 name 是要链接的容器的名称, alias 是这个连接的别名。Docker 在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动 db 容器的时候并没有使用 -p 和 -P 标记,从而避免了暴露数据库端口到外部网络上。
Docker 通过 2 种方式为容器公开连接信息:
环境变量
更新 /etc/hosts 文件
使用 env 命令来查看 web 容器的环境变量
$ sudo 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
其中 DB_ 开头的环境变量是供 web 容器连接 db 容器使用,前缀采用大写的连接别名。

猜你喜欢

转载自blog.csdn.net/showgea/article/details/81129264
今日推荐