Docker容器相对于OpenStack的云主机实例,虽然他们本质上不同。我们需要基于镜像来创建容器。容器是独立运行的一个或一组应用,以及它们的运行环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统和跑在上面的应用。

启动容器

启动容器其实就是创建镜像并启动,启动镜像有两种方式,一种是将已经存在,但是是stopped状态的镜像启动,一种就是基于一个镜像新建一个新的容器并启动。

新建并启动容器

让我们先老生常谈,输出一个Hello World吧。

[root@linux-node1 ~]# docker run centos /bin/echo 'Hello world'

Hello world

很神奇,可以在精通各种语言的Hello World计数器+1了,这个和你在本地系统运行/bin/echo ‘Hello world’ 几乎没有任何区别,但是它是Docker容器输出的,而且输出后,它就完成使命,自动退出了。

注意:这里就是我们学习Docker要面临的第一个疑惑,就是容器只会在前台运行一个任务,任务结束,容器就终止了。

使用docker ps –a可以查看当前启动的容器:

[root@linux-node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
789de67bb454 centos "/bin/echo 'Hello wor" 30 seconds ago Exited (0) 29 seconds
ago pedantic_kare

刚接触Docker到这里还会有第二个疑惑:

Docker自动帮你生成了一个名字,比如本例中是pedantic_kare。

很困惑?好吧,让我们来启动一个我们自定义名称,同时可以有终端的容器,就像启动一个虚拟机一样,不过只是像而已,它们本质上完全不同。

[root@linux-node1 ~]# docker run --name mydocker -t -i centos /bin/bash
[root@1b0cae722fa0 /]#
[root@1b0cae722fa0 /]# ls / anaconda-post.log bin dev etc home lib lib64 lost+found media mnt opt proc root
run sbin srv sys tmp usr var

上面我们使用了两个选项,-t 选项让Docker分配一个伪终端并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。

在交互模式下,用户可以通过所创建的终端来输入命令,例如我们可以查看当前运行的进程,只有/bin/bash和你运行的命令,注意看/bin/bash的PID为1,有意思。先记着这个特殊的地方,随着我们深入学习,再回过头来研究它。

[root@1b0cae722fa0 /]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.1 11776 1872 ? Ss 15:30 0:00 /bin/bash
root 18 0.0 0.0 47424 1660 ? R+ 15:31 0:00 ps aux

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

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

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

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

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

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

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

  • 执行完毕后容器被终止。

让我们输入exit来退出这个容器,退出后,容器会自动终止运行。为什么呢?请参考我们第一个疑惑,Docker容器在前台运行一个单任务,任务结束,容器就终止。这就是Docker容器的特性!同时你有没有注意到一个小细节,默认docker容器的主机名就是CONTAINER ID。

让容器容器后台运行

在使用docker run运行容器更多时候,我们是需要容器在后台运行的,也就是以守护态形式运行。可以通过-d参数来实现。

[root@linux-node1 ~]# docker run -d --name mydocker2 centos /bin/bash
38e42accfa2226bb6c7da2e28e12dc95f6b6d6717326442131887a24bb321cdd

容器启动后就会在后台运行,然后返回一个容器ID到控制台,而且上面这个容器也终止了,带着问题继续前进。

终止容器

在前面的输出Hello World的操作中我们看到了,当Docker容器中指定的应用程序运行完毕,容器也就自动终止了。同时我们可以使用exit命令退出运行/bin/bash的终端,同时我们也可以使用Ctrl+d来实现同样的效果。

使用docker stop来停止一个容器,默认是先给容器发送SIGTERM信号,然后10秒后发生SIGKILL信号终止容器,可以使用-t或者—time来设置等待的时间,单位是秒

docker stop 容器名称、容器ID

对于终止的容器,可以使用docker start来启动,或者使用docker restart来重启。

[root@bc419cd0b8fa /]# exit
Exit

可以使用docker ps –a来查看容器的状态,发现已经是停止模式。

[root@linux-node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38e42accfa22 centos "/bin/bash" 17 seconds ago Exited (0) 16 seconds ago
mydocker2
a5ef57e8783f centos "/bin/bash" 3 minutes ago Exited (0) About a minute ago
mydocker
d132d6e645ad centos "/bin/echo 'Hello wo…" 3 minutes ago Exited (0) 3 minutes
ago serene_dijkstra

启动已终止容器

可以使用docker start来开启已经终止的容器,可以通过输入容器的CONTAINER ID,或者NAMES来进行启动。

[root@linux-node1 ~]# docker start mydocker
mydocker

好的,我们又一次启动了运行/bin/bash的容器,那么问题来了,我们怎么进去呢。

进入容器

Docker attach

Docker提供了docker attach的命令,用来让我们进入已经启动的容器(如果容器已经终止,你需要使用docker start将它启动。

[root@linux-node1 ~]# docker attach mydocker
[root@a5ef57e8783f /]#

你可以继续执行一些命令,没错,很多命令都没有。

注意,在我们使用 attach 进入容器的时候,如果同时有多个窗口 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。这可怎么办,如果我们是团队作战,可能多个同事需要同时进入容器操作呢?还有一个最关键的问题。你输入exit以后呢?之前运行的容器退出了。

nsenter进入容器

nsenter命令被包含在util-linux软件包里面,使用nsenter可以访问另一个进程的名字空间,大多数Linux发行版默认包含了该软件,CentOS默认是有的。如果你的系统里面没有可以使用以下命令进行安装:

Yum安装:

[root@docker ~]# yum install -y util-linux

为了连接到容器,你还需要找到容器的第一个进程的 PID,可以通过下面的命令获取。

# docker inspect --format "{{ .State.Pid }}" <container ID or NAMES>

通过这个 PID,就可以连接到这个容器:

# nsenter --target $PID --mount --uts --ipc --net –pid

如果你刚才停止了容器,请启动。

连接方式如下:

[root@linux-node1 ~]# PID=$(docker inspect --format "{{ .State.Pid }}"
mydocker)
[root@linux-node1 ~]# echo $PID
8029

注意如果你的PID变量为0,说明mydocker容器没有启动。

[root@linux-node1 ~]# nsenter --target $PID --mount --uts --ipc --net --pid
[root@a5ef57e8783f /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 21:11 pts/0 00:00:00 /bin/bash root 14 0 0 21:12 pts/0 00:00:00 -bash root 27 14 0 21:12 pts/0 00:00:00 ps -ef

编写一个脚本用户进入容器

[root@linux-node1 ~]# vim docker_in.sh
#!/bin/bash
# Use nsenter to access docker
docker_in(){
NAME_ID=$1
PID=$(docker inspect --format "{{ .State.Pid }}" $NAME_ID)
nsenter --target $PID --mount --uts --ipc --net --pid
}
docker_in $1
[root@linux-node1 ~]# chmod +x docker_in.sh

这么后面的内容,我们就直接使用docker_in.sh这个脚本来进入Docker容器,只要传给它名称或者容器ID即可,就像下面这样:

[root@linux-node1 ~]# ./docker_in.sh mydocker

不进入容器执行命令

或许你的本意不是想进去容器,而是想让容器执行一个命令,docker提供了exec,使用exec可以在容器内运行命令。

[root@linux-node1 ~]# docker exec mydocker whoami
root

使用exec进入容器

[root@linux-node1 ~]# docker exec -it mydocker /bin/bash

注意,现在你进入容器和其它方法都是不一样的,其实是你执行了一个/bin/bash的命令,所以你现在拥有了一个shell,你现在所在的shell应该是下图中PID为33的进程。

[root@1b0cae722fa0 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 15:37 ? 00:00:00 /bin/bash
root 33 0 0 15:41 ? 00:00:00 /bin/bash
root 46 33 0 15:41 ? 00:00:00 ps -ef

或许你也发现使用docker exec、nsenter进入容器后,执行exit退出容器,容器并不会关闭。但是使用docker attach进入容器,输入exit退出容器后,容器也会自动终止。你可以想想为什么。因为除了attach,nsenter和exec实际中都是开了一个新的shell在执行。而attach是使用容器本身启动的/bin/bash,这个shell环境退出了。那么容器就自动退出了。所以Docker的魔咒来了:docker容器只能而且必须在前台运行一个进程,如果进程退出,容器就关闭。当然如果你想在Docker容器中启动多进程也是有办法的,我们后面会讲到。

删除容器

可以使用 docker rm 来删除一个处于终止状态的容器。 例如

[root@docker ~]# docker rm mydocker

如果要删除一个运行中的容器,可以添加-f参数。Docker会发送 SIGKILL信号给容器。

学习中的小技巧

如果你在学习和测试的过程中,经常因为启动非常多的容易想删除也很难,下面列举了几个小技巧,可以快速的帮我们进行容器的清理。

容器停止后就自动删除:

docker run --rm centos /bin/echo "One"

杀死所有正在运行的容器:

docker kill $(docker ps -a -q)

删除所有已经停止的容器:

docker rm $(docker ps -a -q)

删除所有未打 dangling 标签的镜像

docker rmi $(docker images -q -f dangling=true)

删除所有镜像

docker rmi $(docker images -q)

如果你觉得名称很长,不容易记,还可以为这些命令创建别名。

杀死所有正在运行的容器.

alias dockerkill='docker kill $(docker ps -a -q)'

删除所有已经停止的容器.

alias dockerclean='docker rm $(docker ps -a -q)'

删除所有未打标签的镜像.

alias dockercleani='docker rmi $(docker images -q -f dangling=true)'

删除所有已经停止的容器和未打标签的镜像.

alias dockerclean='dockercleanc || true && dockercleani'

注意:生产环境一定要慎用!!!

3、docker 容器管理的更多相关文章

  1. docker 容器管理常用命令

    Docker 容器管理: docker create -it centos //这样可以创建一个容器,但该容器并没有启动: create Create a new container 创建一个容器: ...

  2. docker 容器管理上

    Docker 容器管理: docker create -it centos //这样可以创建一个容器,但该容器并没有启动: docker start container_id //启动容器后,可以使用 ...

  3. Docker-compose 多个Docker容器管理:以MYSQL和Wordpress为例

    搬砖的陈大师版权所有,转载请注明:http://www.lenggirl.com/tool/docker-compose.html Docker-compose 多个Docker容器管理:以MYSQL ...

  4. Docker系列三:Docker容器管理

    Docker容器管理 1. 单一容器管理 1) 容器的启动 $ docker run --name gitlab-redis -d --volume /srv/docker/gitlab/redis: ...

  5. docker容器管理及网络管理

    防火墙规则—— INPUT 主要用于主机防火墙,设置规则屏蔽处理进入本机的数据包示例:禁止10.180.100.141这个机器访问我本机的web服务iptables -t filter -A INPU ...

  6. docker容器管理-含静态Ip(10)

    docker run命令详解 docker run -t #表示分配一个伪终端 -i #表示让容器的标准输入打开,不跟这个参数容器启不来 -d #后台运行 -P #dockerfile中EXPOSE ...

  7. Docker学习第二天(Docker容器管理)

    简介 emmmm Docker 容器管理 推荐文章:容器技术概述 run里面的子选项 1.使用run命令创建容器 docker container run -it ubuntu /bin/bash / ...

  8. 四、docker容器管理

    一.docker容器管理 1.1 容器查看-ps命令 显示本地容器列表,但是默认不显示关闭的容器,只显示运行中的容器,除非加上命令选项 -a 用法:docker ps [-a 显示所有容器,默认只显示 ...

  9. [CoreOS 转载] CoreOS实践指南(七):Docker容器管理服务

    转载:http://www.csdn.net/article/2015-02-11/2823925 摘要:当Docker还名不见经传的时候,CoreOS创始人Alex就预见了这个项目的价值,并将其做为 ...

  10. Docker 容器管理

    单一容器管理 容器的标识符 每个容器被创建后都会分配一个CONTAINER_ID作为容器的唯一标识符,后续的启动.停止等操作都通过CONTAINER_ID来完成的. CONTAINER_ID很难记忆, ...

随机推荐

  1. HDU 6685 Rikka with Coin (枚举 思维)

    2019 杭电多校 9 1006 题目链接:HDU 6685 比赛链接:2019 Multi-University Training Contest 9 Problem Description Rik ...

  2. Spark:三种任务提交流程standalone、yarn-cluster、yarn-client

    spark的runtime参考:Spark:Yarn-cluster和Yarn-client区别与联系浪尖分享资料 standalone Spark可以通过部署与Yarn的架构类似的框架来提供自己的集 ...

  3. axios请求中的参数(params)与路径变量

    1.axios的参数(params) import axios from 'axios' export function getDiscList() { const url = '/api/getDi ...

  4. js实现禁止页面拖拽图片

    document.ondragstart = function() {        return false;};

  5. javascript 学习犯错记录

    看w3c学习js,有时按自己想法来,会出一些莫名奇妙的错误,而这些问题百度到了,但因为学习原因基础不捞,导致看到了答案,却认为这不是答案 1.一个很简单的 一个html,一个js文件 我想在js中的b ...

  6. ARM 汇编访问 CPSR / SPSR 寄存器 【 msr ,mrs 】

    状态寄存器访问过程:读 - 改 - 写 读 CPSR / SPSR 指令[ mrs ]    格式:<opcode><cond> Rn, cpsr/spsr 写 CPSR / ...

  7. nginx : OpenEvent Faied access is denied

    主要是naginx做成服务后, 服务运行的用户权限不够(他是system的),而cmd运行的是(Administrator) 所以我们去服务里,修改成以下就好了

  8. 错误 175: 具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序未在计算

    问题描述:错误 175: 具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序未在计算 原因描述:一.首先我的系统是因为是win10 的有问题,重新装了系统. 二. ...

  9. linux 套接字

    三.命名套接字 之前的socket只是创建了一个没有名字的资源,其他进程无法访问他.所以也无法从它接受消息.只有当bind给套接字绑定了端口和名字后,其他进程才能找到它. 一般服务器是一定要bind, ...

  10. 30 System类

    System类代表系统,系统级的很多属性和控制方法都放置在该类的内部.该类位于java.lang包.由于该类的构造方法是private的,所以无法创建该类的对象,也就是无法实例化该类.其内部的成员变量 ...