容器是Docker的另一个核心概念。简单来说,容器是镜像的一个运行实例。所不同的是,镜像是静态的只读文件,而容器带有运行时需要的可写文件层。如果认为虚拟机是模拟运行的一整套操作系统(包括内核、应用运行态环境和其他系统环境)和跑在上面的应用,那么Docker容器就是独立运行的一个(或一组)应用,以及它们必需的运行环境。
创建容器
新建容器 docker create
可以使用docker create命令新建一个容器,例如:
$ docker create -it ubuntu:latest
af8f4f922dafee22c8fe6cd2ae11d16e25087d61f1b1fa55b36e94db7ef45178
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af8f4f922daf ubuntu:latest "/bin/bash" 17 seconds ago Created silly_euler
使用docker create命令新建的容器处于停止状态,可以使用docker start命令来启动它。
Create命令和后续的run命令支持的选项都十分复杂,主要包括如下几大类:与容器运行模式相关、与容器和环境配置相关、与容器资源限制和安全保护相关。
启动容器 docker start
使用docker start命令来启动一个已经创建的容器,例如启动刚创建的ubuntu容器:
$ docker start af
af
此时,通过docker ps命令可以查看一个运行中的容器:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af8f4f922daf ubuntu:latest "/bin/bash" 2 minutes ago Up 7 seconds silly_euler
新建并启动容器 docker run
除了创建容器后通过start命令来启动,也可以直接新建并启动容器。所需要的命令主要为docker run,等价于先执行docker create命令,再执行docker start命令。
例如,下面的命令输出一个“Hello World”,之后容器自动终止:
$ docker run ubuntu /bin/echo 'Hello world'
Hello world
当利用docker run来创建并启动容器时,Docker在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载;
- 利用镜像创建一个容器,并启动该容器;
- 分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层;
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中;
- 从网桥的地址池配置一个IP地址给容器;
- 执行用户指定的应用程序;
- 执行完毕后容器被自动终止。
下面的命令启动一个bash终端,允许用户进行交互:
$ docker run -it ubuntu:14.04 /bin/bash
root@af8bae53bdd3:/#
其中,-t选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,-i则让容器的标准输入保持打开。更多的命令选项可以通过man docker -run命令来查看。
守护态运行 docker run -d
更多的时候,需要让Docker容器在后台以守护态Daemonized)形式运行。此时,可以通过添加- d参数来实现。
例如下面的命令会在后台运行容器:
$ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
ce554267d7a4c34eefc92c5517051dc37b918b588736d0823e4c846596b04d83
容器启动后会返回一个唯一的id,也可以通过 docker ps命令来查看容器信息。
此时,要获取容器的输出信息,可以如下使用docker logs命令:
$ docker logs ce5
hello world
hello world
hello world
. . .
终止容器 docker stop
可以使用docker stop来终止一个运行中的容器。该命令的格式为docker stop [-t|--time[=10]][CONTAINER...]。
该首先向容器发送SIGTERM信号,等待一段超时时间(默认为10秒)后,再发送SIGKILL信号来终止容器。
docker kill命令会直接发送SIGKILL信号来强行终止容器。
进入容器
在使用-d参数时,容器启动后会进入后台,用户无法看到容器中的信息,也无法进行操作。
这个时候如果需要进入容器进行操作,有多种方法,包括使用官方的attach或exec命令,以及第三方的nsenter工具等。下面分别介绍一下。
attach命令
$ docker run -itd ubuntu
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds
nostalgic_hypatia
$ docker attach nostalgic_hypatia
root@243c32535da7:/#
但是使用attach命令有时候并不方便。当多个窗口同时用attach命令连到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。
exec命令
Docker从1.3.0版本起提供了一个更加方便的exec命令,可以在容器内直接执行任意命令。该命令的基本格式为
比较重要的参数有:
- -i,--interactive=true|false:打开标准输入接受用户输入命令,默认为
false; - --privileged=true|false:是否给执行命令以高权限,默认为false;
- -t,--tty=true|false:分配伪终端,默认为false;
- -u,--user="":执行命令的用户名或ID。
例如进入到刚创建的容器中,并启动一个bash:
$ docker exec -it 243c32535da7 /bin/bash
root@243c32535da7:/#
nsenter工具
在util-linux软件包版本2.23+中包含nsenter工具。如果系统中的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 && cp nsenter /usr/local/bin
为了使用nsenter连接到容器,还需要找到容器进程的PID,可以通过下面的命令获取:
PID=$(docker inspect --format "{{ .State.Pid }}" <container>)
通过这个PID,就可以连接到这个容器:
$ nsenter --target $PID --mount --uts --ipc --net --pid
下面给出一个完整的例子,通过nsenter命令进入容器:
$ docker run -idt ubuntu
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds
nostalgic_hypatia
$ PID=$(docker-pid 243c32535da7)
10981
$ nsenter --target 10981 --mount --uts --ipc --net --pid
root@243c32535da7:/#
ip netns操作容器网络
ip netns exec $PID ip link set eth0 up
ip netns exec $PID ip route add default via 172.17.0.1
删除容器
可以使用docker rm命令来删除处于终止或退出状态的容器,命令格式为docker rm [-f|--force][-l|--link][-v| --volumes]CONTAINER[CONTAINER...]。
如果要直接删除一个运行中的容器,可以添加-f参数。Docker会先发送SIGKILL信号给容器,终止其中的应用,之后强行删除,如下所示:
$ docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world;
sleep 1; done"
2aed76caf8292c7da6d24c3c7f3a81a135af942ed1707a79f85955217d4dd594
$ docker rm 2ae
Error response from daemon: You cannot remove a running container. Stop the
container before attempting removal or use -f
2016/07/03 09:02:24 Error: failed to remove one or more containers
$ docker rm -f 2ae
2ae