3.1 帮助启动类命令
- 启动 Docker
bash
[root@shjava101 ~]# systemctl start docker # 启动docker
[root@shjava101 ~]# systemctl status docker # 查看docker的运行状态
[root@shjava101 ~]# systemctl restart docker # 重启docker服务
[root@shjava101 ~]# systemctl stop docker # 停止docker服务
[root@shjava101 ~]# docker --help # 查看docker帮助文档

如果我们想查看指定某条 Docker 命令的帮助信息呢?
语法格式是: docker 具体命令 --help。 比如我们现在想查看 Docker 的 cp 命令详细信息。
bash
[root@shjava101 ~]# docker cp --help

3.2 Docker 的镜像命令
- Docker images 列出本地主机上的镜像
bash
[root@shjava101 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 15 months ago 13.3kB

上图中展示镜像列表的各个选项信息是什么意思?
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签版本号。在下载镜像的时候,如果默认不加版本号,就会下载默认最新版本的镜像。如果加上指定版本号的镜像,下载的就是对应版本的镜像。
- IMAGE ID:镜像 ID
- CREATED:镜像创建时间
- SIZE:镜像大小
注意:同一仓库源可以有多个 TAG 版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
如果我们想深入学习 docker images 的命令,我们可以使用 help 指令查看关于 docker images 的帮助文档。
bash
[root@shjava101 ~]# docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
- a, --all. Show all images (default hides intermediate images)
--digests. Show digests
- f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc Don't truncate output
- q, --quiet Only show image IDs
[root@shjava101 ~]# docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 15 months ago 13.3kB
[root@shjava101 ~]# docker images -q
feb5d9fea6a5
-a :列出本地所有的镜像(含历史映像层) -q :只显示镜像ID。
- docker search 某个XXX镜像名字 指定搜索某个镜像的名称。
bash
[root@shjava101 ~]# docker search redis

搜索镜像出现的选项是什么意思呢:

我们也可以携带一些参数,比如 --limit。--limit: 只列出 N 个镜像,默认 25 个
bash
[root@shjava101 ~]# docker search --limit 5 redis
- docker pull 某个 XXX 镜像名字:拉取指定的镜像到本地(下载镜像)
- 语法:docker pull 镜像名字 :TAG
bash
[root@shjava101 ~]# docker pull mysql # 没有带标签,就下载的是最新版本的 mysql 镜像
[root@shjava101 ~]# docker pull redis:6.0.8 # 下载指定标签的 redis 镜像

比如我们给大家演示下载 ubuntu 镜像:
bash
[root@shjava101 ~]# docker pull ubuntu # 默认下载最新版本的镜像
Using default tag: latest
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
[root@shjava101 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ba6acccedd29 14 months ago 72.8MB
hello-world latest feb5d9fea6a5 15 months ago 13.3kB
redis 6.0.8 16ecd2772934 2 years ago 104MB

在 Linux 里面我们如何插件硬盘的使用情况,是不是可以使用 df -h 命令。在 Docker 里面我们也想查看镜像 / 容器的占用空间,我们应该如何使用呢:
语法格式: docker system df 查看镜像 / 容器 / 数据卷所占的空间

- docker rmi 某个 XXX 镜像名字 ID 删除某个镜像,注意:不能删除正在运行容器的镜像!
bash
[root@shjava101 ~]# docker rmi hello-world # 可以根据镜像名称删除
Error response from daemon: conflict: unable to remove repository reference
"hello-world" (must force) - container eec46ce5392d is using its referenced
image feb5d9fea6a5
[root@shjava101 ~]# docker rmi feb5d9fea6a5 # 也可以根据镜像 id 删除,因为镜像 id 是唯一的。
Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be
forced) - image is being used by stopped container eec46ce5392d
但是此时删除报错,为什么?因为删除的时候,当前镜像存在正在运行的容器。我们可以使用 -f 参数来指定强制删除,但是强制删除的话,正在运行的容器也就不复存在了。
bash
[root@shjava101 ~]# docker rmi -f feb5d9fea6a5

- docker rmi -f 镜像名1: TAG 镜像名2: TAG 删除多镜像可以使用这个命令
bash
[root@shjava101 ~]# docker rmi -f ubuntu:latest redis:6.0.8
- 也可以直接删除全部镜像(慎用!!!)
bash
[root@shjava101 ~]# docker rmi -f $(docker images -qa)
这里有个面试题,大家需要留意一下:什么是虚悬镜像?
仓库名、标签都是 <none> 的镜像,俗称虚悬镜像。

这种经常一般没啥用,我们直接删除即可。
3.3 Docker 的容器命令
Docker 的容器命令我们用 Ubuntu 演示。
首先我们使用 docker pull ubuntu 下载 ubuntu 镜像。
bash
[root@shjava101 ~]# docker pull ubuntu
3.3.1 容器的基本命令
- 启动容器
启动容器命令的语法格式是: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS 参数说明 (有些是一个减号,有些是两个减号):
--name="容器新名字" 为容器指定一个名称; -d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行); -i:以交互模式运行容器,通常与 -t 同时使用; -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用; 也即启动交互式容器(前台有伪终端,等待交互); -P: 随机端口映射,大写P -p: 指定端口映射,小写p

现在我们如何启动一个 Ubuntu 容器呢?使用 docker run ubuntu 吗?我们可以试一下:
bash
[root@shjava101 ~]# docker run ubuntu
[root@shjava101 ~]#
我们发现启动之后,没有任何反应,因为我们希望启动的是一个交互式的容器,也就是用户可以在终端输入命令的容器。那如何启动一个交互式的容器呢?
根据上面的语法规则我们可以这样启动:
bash
[root@shjava101 ~]# docker run -it ubuntu /bin/bash
root@f6d5e6eb2c5c:/#
参数说明: -i: 交互式操作。 -t: 终端。 ubuntu: ubuntu镜像。 /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,用来解释执行 Linux指令。 因此用的是 /bin/bash。 要退出终端,直接输入 exit。
- docker ps 列出正在运行的容器
我们另起一个终端,运行 docker ps 命令。
bash
[root@shjava101 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
f05e76e5e32c ubuntu "/bin/bash" 11 seconds ago Up 10 seconds
optimistic_swirles
NAMES:指定启动的容器名字,如果你不指定,系统就会给你随机指的一个名字。如何在启动容器的时候也指定容器的名字呢?
我们可以使用 --name 参数指定。
bash
[root@shjava101 /]# docker run -it --name=u1 ubuntu /bin/bash
我们再次查看正在运行的容器。
bash
[root@shjava101 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
6d2d86512480 ubuntu "/bin/bash" 11 seconds ago Up 10 seconds
u1
我们发现正在运行的容器的名字就是我们自己定义的了。这个命令还可以携带一些常用的参数:
-a: 列出当前所有正在运行的容器 + 历史上运行过的 -l: 显示最近创建的容器。 -n: 显示最近n个创建的容器。 -q: 只显示正在运行的容器编号。
下面我们来具体演示:
bash
[root@shjava101 ~]# docker ps -a # 列出所有容器(正在运行的以及历史运行的)
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
6d2d86512480 ubuntu "/bin/bash" 5 minutes ago Up 5 minutes
u1
2377079e316a ubuntu "/bin/bash" 5 minutes ago Exited (0) 5
minutes ago
[root@shjava101 ~]# docker ps -l #罗列最近运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
6d2d86512480 ubuntu "/bin/bash" 6 minutes ago Up 6 minutes
u1
[root@shjava101 ~]# docker ps -n 2 # 罗列最近运行的2个容器
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
6d2d86512480 ubuntu "/bin/bash" 6 minutes ago Up 6 minutes
u1
2377079e316a ubuntu "/bin/bash" 7 minutes ago Exited (0) 7 minutes ago
hopeful_davinci
[root@shjava101 ~]# docker ps -q # 只显示最近运行的容器的id
6d2d86512480
- 退出容器的命令
上面提到,要退出容器终端,可以使用 exit 命令,但是使用 exit 命令退出会导致容器终止执行!如果退出容器终端,不影响容器正在运行可以吗,答案是可以的。这个也是退出容器的两种机制。
exit run 进去容器,exit 退出,容器停止 ctrl+p+q run 进去容器,ctrl+p+q 退出,容器不停止
- 启动已停止运行的容器
语法格式:docker start 容器 ID 或者容器名

hash
[root@shjava101 /]# docker start 2377079e316a
2377079e316a
[root@shjava101 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
6d2d86512480 ubuntu "/bin/bash" 22 minutes ago Up 22 minutes
u1
2377079e316a ubuntu "/bin/bash" 22 minutes ago Up 17 seconds
hopeful_davinci
我们发现之前已经停止的容器也运行起来了。
- 重启容器
语法格式: docker restart 容器ID或者容器名
bash
[root@shjava101 /]# docker restart 2377079e316a
- 停止容器
语法格式: docker stop 容器ID或者容器名
bash
[root@shjava101 /]# docker stop 2377079e316a
- 强制停止容器
语法格式: docker kill 容器ID或容器名
bash
[root@shjava101 /]# docker kill 2377079e316a
- 删除已停止的容器
语法格式: docker rm 容器ID
bash
[root@shjava101 /]# docker rm 2377079e316a
如果我们要删除正在运行的容器呢?
此时需要加上一个 -f 参数
bash
[root@shjava101 /]# docker rm -f 2377079e316a
我们也可以一次性删除多个容器实例,但是一般不建议大家这么使用:
bash
[root@shjava101 /]# docker rm -f $(docker ps -a -q)
或者
bash
[root@shjava101 /]# docker ps -a -q | xargs docker rm # xargs 是linux里的一个显式参数
现在我们思考几个问题,上面我们启动了前台交互式的容器,如果我们想以后台守护式的方式启动容器应该怎么做?还有,我们从一个正在运行中的容器退出来了以后,我们又如何进入这个容器呢?接下来我们就来解决这几个问题。
3.3.2 启动守护式容器与进入容器
这里我们用 Redis6.0.8 镜像演示。各位同学首先请确保你本机里面下载有 Redis 镜像。
在大部分的场景下,我们希望 Docker 的服务是在后台运行的,我们可以过 -d 指定容器的后台运行模式。为了显示区别,我们先用前台交互的方式启动容器:
bash
[root@shjava101 /]# docker run -it redis:6.0.8
此时会以前台运行redis的方式显示:

但是这种启动方式会霸占我们整个 Linux 终端,导致我们不能做其他的事情。所以我们应该以后台的形式启动守护式容器。如何启动?
我们可以使用 docker run -d 容器名 这个命令。
bash
[root@shjava101 /]# docker run -d redis:6.0.8
38b51ae774dd345fef245de93d2285987831c9119da93421c6a4304e89447ec5
我们查看容器是否启动?
bash
[root@shjava101 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
38b51ae774dd redis:6.0.8 "docker-entrypoint.s..." 4 seconds ago Up 3
seconds 6379/tcp boring_poitras
6d2d86512480 ubuntu "/bin/bash" About an hour ago Up
About an hour u1
我们如何进入到 Redis 容器的内部,我们马上说到。现在我们再看几个和容器相关的其他命令。
- 查看容器日志的命令 docker logs 容器id
bash
[root@shjava101 /]# docker logs 38b51ae774dd

我们发现容器启动的日志信息全部被封装起来了。
- 查看容器内运行的进程
docker top 容器ID
在 Linux 里面,我们可以使用 top 命令动态查看进程信息,在 docker 里面我们可以使用docker top 命令查看指定容器的进程信息。
bash
[root@shjava101 /]# docker top 38b51ae774dd

- 查看容器内部具体细节命令 docker inspect 容器ID
bash
[root@shjava101 /]# docker inspect 38b51ae774dd

接下来我们讨论如何进入正在运行的容器并以命令行交互。我们先以前面运行的 Ubuntu 容器为例:
我们可以通过 docker exec 命令进入容器内部
bash
[root@shjava101 /]# docker exec -it 6d2d86512480 /bin/bash
root@6d2d86512480:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc
root run sbin srv sys tmp usr var
此时我们使用 exit 命令退出容器。
bash
root@6d2d86512480:/# exit
exit
[root@shjava101 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
38b51ae774dd redis:6.0.8 "docker-entrypoint.s..." 17 minutes ago Up 17
minutes 6379/tcp boring_poitras
6d2d86512480 ubuntu
我们发现,当我们退出容器之后,容器依然在运行。
我们还可以使用 docker attach 容器id 的命令进入容器,但是用 exit 命令退出会导致容器停止。
bash
[root@shjava101 /]# docker attach 6d2d86512480
root@6d2d86512480:/# exit
exit
[root@shjava101 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
38b51ae774dd redis:6.0.8 "docker-entrypoint.s..." 22 minutes ago Up 22
minutes 6379/tcp boring_poitras
我们发现 ubuntu 运行的容器已经停止了。
所以推荐大家使用 docker exec 命令,因为退出容器终端,不会导致容器的停止。
我们现在如何进入到 Redis 容器的内部呢?
bash
[root@shjava101 /]# docker exec -it 38b51ae774dd /bin/bash
root@38b51ae774dd:/data# redis-cli
127.0.0.1:6379> set username eric
OK
127.0.0.1:6379> get username
"eric"
127.0.0.1:6379>
3.3.3 备份容器
(1) 从容器内拷贝文件到主机上
语法格式: docker cp 容器ID:容器内路径 目的主机路径
需求:我们先启动 Ubuntu 容器,然后在容器的 tmp 目录创建一个文件。然后把这个文件拷贝至宿主机中。
bash
[root@shjava101 /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ba6acccedd29 14 months ago 72.8MB
redis 6.0.8 16ecd2772934 2 years ago 104MB
[root@shjava101 /]# docker run -it ubuntu /bin/bash
root@608d2057e7e5:/# cd /tmp
root@608d2057e7e5:/tmp# touch a.txt
root@608d2057e7e5:/tmp# ls
a.txt
我们使用命令尝试拷贝:
bash
[root@shjava101 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
608d2057e7e5 ubuntu "/bin/bash" 13 minutes ago Up 13
minutes reverent_stonebraker
38b51ae774dd redis:6.0.8 "docker-entrypoint.s..." About an hour ago Up
About an hour 6379/tcp boring_poitras
[root@shjava101 /]# docker cp 608d2057e7e5:/tmp/a.txt /tmp/a.txt
[root@shjava101 /]# cd /tmp
[root@shjava101 tmp]# ll
total 1504
-rw-r--r--. 1 root root 0 Dec 22 21:17 a.txt
我们发现,可以成功将容器内部的文件拷贝出来。

(2) 导入和导出容器
上面是将文件中的某个内容导出来,我们也可以将整个容器导出来,以 tar.gz 的文件保存。我们可以使用 export 命令实现。
语法格式:docker export 容器ID > 文件名.tar
bash
[root@shjava101 tmp]# docker export 608d2057e7e5 > ubuntu.tar.gz
[root@shjava101 tmp]# ll
-rw-r--r--. 1 root root 75158016 Dec 22 21:47 ubuntu.tar.gz
我们发现容器成功备份。
接下来我们分别删除运行的 Ubuntu 镜像和运行的 Ubuntu 容器。

现在我们通过 ubuntu.tar.gz 来导入一个新镜像:
语法格式:cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
bash
[root@shjava101 tmp]# cat ubuntu.tar.gz | docker import - wen/ubuntu:1.0
sha256:575629a1394b19d888621928a842b706a385fe1d3d862d85f6be3f765d88656c
[root@shjava101 tmp]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wen/ubuntu 1.0 575629a1394b 16 seconds ago 72.8MB
redis 6.0.8 16ecd2772934 2 years ago 104MB
我们发现镜像成功导入。接下来我们启动容器:
bash
[root@shjava101 tmp]# docker run -it 575629a1394b /bin/bash # 启动容器
root@e53f29855791:/# cd /tmp
root@e53f29855791:/tmp# ll
total 0
drwxrwxrwt. 2 root root 19 Dec 22 13:17 ./
drwxr-xr-x. 1 root root 6 Dec 22 13:55 ../
-rw-r--r--. 1 root root 0 Dec 22 13:17 a.txt
我们发现容器成功启动,并且之前创建的文件也存在。说明我们导入成功!