Docker容器运行的本质是运行一个进程,该进程在其自己的隔离环境中运行,该环境由Linux内核的特性(如cgroups和namespaces)提供。Docker 容器存在的意义就是为了运行容器中的应用,对外提供服务,所以启动容器的目的就是启动运行该容器中的应用。容器中的应用运行完毕后,容器就会自动终止。所以,如果不想让容器启动后立即终止运行,则就需要使容器应用不能立即结束。通常采用的方式有两种,使应用处于与用户交互的状态或等待状态。下面以tomcat镜像为例,进行容器的相关操作。
容器的创建并启动
以交互模式运行 tomcat
docker run --name tomcat1 -it tomcat:8.5.32 /bin/bash
-
–name 指定当前容器名称为 tomcat1
-
-it 指定以交互模式运行容器,且为容器分配一个伪终端。
-
后面的/bin/bash 用于指定容器启动后需要运行的命令为/bin 下的 bash 命令,而该命令会启动一个 bash 终端。
我们在这里运行了一个tomcat的容器,并为其取名为 tomcat1。另外我们可以注意到,命令行前面提示部分内容发生了变化:原来显示的是[root@centos ~],而现在变为了
root@747113026e90:/usr/local/tomcat#,这个就是 docker 生成的伪客户端,而数字 747113026e90表示的是docker 容器的 ID。需要注意的是我们只是创建了tomcat1容器,但是tomcat1容器并没有对外(宿主机)暴露端口,所以当我们在浏览器访问tomcat时会找不到服务。
docker run --name tomcat2 -it -p 8081:8080 tomcat:8.5.32
-p 用于指定端口映射,格式为暴露给宿主机的端口:容器中应用的端口
。回车后会发现 tomcat 已启动,且 tomcat 的日志输出占居了命令行。
以分离模式运行 tomcat
docker run --name tomcat3 -dp 8082:8080 tomcat:8.5.32
-d 选项表示以分离模式(detached mode)运行容器,即命令在后台运行,命令的运行与宿主机的运行分离开来。
最后需要注意的是:当运行容器时,命令的最后要不要加/bin/bash的问题。如果你需要在程序启动后进行一些命令交互,那么就需要一个终端来输入命令,但这并不是说就需要加一个/bin/bash来生成一个终端,还要看镜像的DockerFile文件的最后一个指令是否有
CMD ["/bin/bash"]
。如果有则可加可不加(/bin/bash);如果没有就一定要加/bin/bash。就以下面的centos为例,有CMD [“/bin/bash”]就不需要我们加/bin/bash来生成终端。
容器创建命令
docker create 命令仅创建容器但不启动,其用法与 docker run 非常相似。docker create创建成功后会返回容器id。注意,其没有-d 选项
。
docker create --name tomcat4 -p 8083:8080 tomcat:8.5.32
容器退出命令
退出容器指的是退出以交互模式
运行的容器。分为两种退出方式:
-
退出并停止容器 exit
在容器命令行中再运行 exit 命令后,通过 docker ps –a 可以查看到该容器已经退出了。
-
退出并不停止容器 Ctrl + P + Q
注:先按下 Ctrl + P,然后再按下 Q。 就能够返回到了宿主机命令行。
容器状态查看命令
-
docker ps 用于查看所有
正在运行
的容器。 -
docker ps –a 用于查看所有容器,
无论是否处于运行状态
。 -
docker ps –q 用于查看所有
处于运行状态的容器的 ID
。 -
docker ps –qa 用于查看所有容器的 ID,无论是否处于运行状态。
-
docker ps –l 用于查看最后创建的容器,无论该容器是否处于运行状态。
容器再进入命令
当我们以分离模式运行了一个容器,或以交互模式运行了一个容器,但容器内部执行的命令占用了交互命令行,而此时我们又想进入到容器中对容器内部进行一些操作,此时就需要用到 exec/attach 命令了。注意,它们只能对正在运行的容器进行操作
。
exec命令
首先使用 docker run --name tomcat1 -it -p 8081:8080 tomcat:8.5.32 命令运行一个tomcat1容器。然后Ctrl + P + Q退出容器,此时容器还是运行状态。如果想要回到tomcat1容器的shell界面,就可以使用docker exec -it tomcat1 /bin/bash命令回到tomcat1容器的shell。
当执行 exit 命令退出容器后,此时查看正在运行的容器,发现 tomcat1 容器并未退出。说明 exec 命令会创建一个新的独立于容器的进程,而 exit 命令仅用于结束该新建进程。
外部操作容器 exec
前面是在进入到容器的命令行后才对容器进行操作的,我们也可以不进入容器直接对容器内部进行操作。例如仅想查看 tomcat1 容器中工作目录中所包含的文件,直接在 exec 命令后紧跟要执行的命令即可直接看到其结果。
# 外部操作容器 exec
docker exec -it "容器名" "要执行的命令"
attach 命令
1.容器附加标准输入
以centos容器为例,首先以交互方式运行一个 centos 容器,然后使用 Ctrl + P + Q 命令退出但不停止容器。然后使用 attach 命令进入容器命令行。此时,再使用 exit 命令退出容器。然后会发现容器也停止了。由于 exit 命令的作用是,结束当前进程,所以说明 attach 命令并没有另外再创建新的进程,而是使用了容器进程,exit 命令退出了当前进程,也就退出了容器。
2.容器附加标准输出
以tomcat容器为例,启动一个 tomcat 容器并指定容器名称为 tomcat1。然后通过 docker attach命令则可看到如下场景:占用了命令行,且没有任何输出,即使通过浏览器访问该 tomcat也没有任何输出。
这是因为docker attach 命令是将您的终端
连接到 Docker容器的主进程的标准输入,输出和错误输出
中。
如果容器的主进程不是一个交互式的 shell(比如 Tomcat,这是一个 Java 进程,该进程只会不断的输出日志),那么 docker attach 可能无法正常工作,因为它没有交互式 shell 来连接。在 Tomcat 容器的情况下,主进程是 Tomcat 服务器本身,而不是一个交互式 shell。因此,当你尝试使用 docker attach 连接到 Tomcat 容器时,你实际上是在尝试连接到 Tomcat 服务器进程,而不是一个 shell,所以你无法像期望的那样输入命令。
为了证明以上结论,可以在新建一个终端,命名为终端2;原来的终端叫做终端1。在终端2中使用 docker stop tomcat1 命令停止tomcat1容器。这时候可以看到原来的终端1有日志输出,这是tomcat1服务器的停止日志。但由于此时的 tomcat1已经停止,tomcat1 容器已经退出,所以该 docker attach 命令也就随之结束了。
所以结论就是:docker attach命令是将您的
终端
连接到Docker容器的主进程的标准输入,输出和错误输出
中。能不能进入容器的命令行界面要看那个容器的主进程是否是一个交互式的shell。
容器内进程查看命令
docker top 命令用于查看指定的正在运行的容器
中正在运行的进程详情。
容器日志查看命令
docker logs [容器]可以查看指定容器中应用的运行日志(显示的是容器主进程的标准输出和标准错误输出),无论该容器是运行还是停止状态
。也就是说这个日志对于不同的容器来说,其日志内容是不同的。由 docker run 命令的[command]决定(如果没有则由 Dockerfile 中的 CMD指令决定)
当查看centos日志的时候,由于/bin/bash这个shell没有标准输出或标准错误等信息的输出,所以会发现centos日志什么也没有。
但是查看tomcat1的日志就会有内容显示。由于日志非常多,所以只显示最后三行。
容器启停命令
- 启动容器:通过 docker start 命令可以启动已经停止的指定容器,这个容器可以通过容器名称指定,也可以通过容器 ID 指定。
- 重启容器:通过 docker restart 命令可以重启处于运行状态的指定容器。
- 优雅停止容器:通过 docker stop 命令可以优雅停止指定容器。所谓优雅停止是指:若当前容器正在被其它进程访问,则在访问结束后再停止。如果容器在一段时间后(默认是10秒)仍然在运行,那么 Docker 会发送一个 SIGKILL 信号来强制停止容器。
- 强制停止容器:通过 docker kill 命令可以强制停止指定容器。所谓强制停止是指:无论容器当前是否被其它进程访问都直接停止。
- 暂停容器:通过 docker pause 命令可以
暂停容器对外提供服务
。 - 解除暂停:通过 docker unpause 命令可
解除容器的暂停服务状态
。
容器删除命令
-
正常删除:docker rm 命令在默认情况下,要删除的容器
必须是已经停止
的容器。当然,这个容器可以使用容器名或容器 ID 指定。 -
强制删除:在 docker rm 命令中添加-f 可实现强制删除容器。即,无论容器是否停止都会删除。
-
删除所有容器:docker rm -f $(docker ps -aq)
容器与宿主机之间的文件传递
docker cp 命令可以完成容器与宿主机中文件/目录的相互复制,无论该容器是否处于运行状态。
容器传递文件到宿主机
- 首先进入centos容器的/home目录下。
- 创建了一个内容为hello,文件名为demo1.txt的文件。
- 退出容器环境。
- 使用docker cp 命令将容器中的文件复制到宿主机。
宿主机传递文件到容器
- 首先在宿主机中创建一个内容为world,文件名为demo2.txt的文件。
- 使用docker cp 命令将宿主机中的文件复制到容器中。
- 进入容器并查看文件。
提交容器为镜像
通过 docker commit 命令可以将一个容器文件系统的当前快照生成为一个新的镜像。
修改容器层
首先创建并启动一个容器,例如 centos:7 镜像的容器。然后发现该容器中是没有安装ifconfig 命令的。于是安装 net-tools 网络工具命令包。
此时再使用 ifconfig,已经可以使用了。
生成镜像
下面要将已经安装了 ifconfig 命令的容器生成为一个镜像,以方便后期自己或他人使用。
#docker commit 用法
docker commit -a "作者名 <邮箱名>" -m "提交的描述信息" "容器名" ["镜像名":"TAG"]
使用新镜像
下面是使用新生成的镜像创建并启动一个容器,发现其中的 ifconfig 命令是可以使用的。
生成悬虚镜像
悬虚镜像,即没有<repository>与<tag>的镜像。悬虚镜像一般都是由于某些失误操作或其它一些操作而生成的副产物,一般是要被清除掉的。如果非要使用悬虚镜像,那只能通过其 ImageID 来使用了。
下面要将已经安装了 ifconfig 命令的容器生成为一个悬虚镜像,即没有指定<repository>与<tag>。
导入 / 导出容器
导出容器 export
docker export 命令用于将一个容器的文件系统导出为 tar 文件
。例如,下面的命令是将centos:7镜像的容器 centos1 导出到当前 /root 目录的 centos.tar 文件中。
在Docker的架构中,每一个容器都是基于一个Docker镜像创建的。这个镜像是由多个只读层组成的,而当你创建一个新的容器时,Docker会在这些只读层之上添加一个可写层,这个可写层被称为“容器层”。所有对容器的改动(例如添加、删除或修改文件)都会在这个容器层中进行。因此,当你使用
docker export
命令时,实际上导出的就是这个容器层的内容。
导入容器 import
docker import 命令用于根据指定的 tar 文件构建新的镜像。下面的命令是将当前目录下的 centos.tar 导出为镜像 centos:import。
与 save/load/commit 命令的对比
1.export与save对比
-
export 作用于容器,save 作用于镜像,但它们导出的结果都为 tar 文件。
-
export 一次只能对一个容器进行导出,save 一次可以对多个镜像进行导出。
-
export 只是对当前容器的文件系统快照进行导出,其会丢弃原镜像的所有历史记录与元数据信息。save 则是保存了原镜像的完整记录
所以,如果你有一个已经配置好的容器,你想共享这个容器的文件系统,你可以使用docker export
。如果你想共享整个镜像,包括构建镜像的每一层和元数据,你应该使用docker save
。
2.import与load对比
-
import 导入的是容器包,load 加载的是镜像包,但最终都会恢复为镜像。
-
import 恢复为的镜像只包含当前镜像一层(可以通过docker history " 镜像名:TAG " 命令进行查看),load 恢复的镜像与原镜像的分层是完全相同的。
-
import 恢复的镜像就是新构建的镜像,与原镜像的 ImageID 不同;load 恢复的镜像与原镜像是同一个镜像,即 ImageID 相同。
-
import 可以为导入的镜像指定<repository>与<tag>,load 加载的镜像不能指定<repository>与<tag>,与原镜像的相同
3.export+import与commit对比
-
相同点:docker export + docker import 会将一个容器变为一个镜像,docker commit 也可以将一个容器变一个镜像。
-
不同点:docker export + docker import 恢复的镜像仅包含原容器生成的一层分层,docker commit 生成的镜像中包含容器的原镜像的所有分层信息。
docker system 命令集
docker system 是一个命令集,其有四个子命令。
- docker system df 用于查看 docker 各部分占用情况。
- docker system events 命令造价于 docker events 命令,可查看指定日间之内(–since)或之外(–until)在 docker 上所发生的所有事件。这些事件包含运行过的命令有 docker 内部执行的一些操作。
- docker system info命令等价于docker info,用于查看当前docker的详情。包括dockerClient与 docker Server 详情。其中 docker server 包含镜像、容器情况,docker 所在系统的软硬件情况等。
- docker system prune 命令用于删除 docker 中的无用数据,这些无用数据包含已经停止的容器、没有任何连接容器的网络、悬空镜像,及悬空镜像的构建缓存。