【Docker】Docker Container(容器)
什么是容器。
一、什么是容器
通俗地讲,容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容器有初建、运行、停止、暂停和删除五种状态。
虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。也就是说,在容器内部无法看到主机上的进程、环境变量、网络等信息,这是容器与直接运行在主机上进程的本质区别。
容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。

二、容器的生活案例
镜像与容器就相当于同样是开发商提供的毛坯房,但是两家人装修出来的完全不一样。

再比如说,我们都学习了 C++ 或者 Java 之类的面向对象的语言,可以理解为镜像为基础类,容器是实例化出来的一个个对象,没有用户需要的不一样,里面的内容也就不一样了。

三、为什么需要容器
镜像是静态的文件,并不能提供服务,就好比如我拿了一个 Linux 或者 Windows 的光盘一样,只有安装到主机里面运行起来,才能对外提供服务,我们才能使用。
容器带来哪些收益呢?
可以参考:【Docker】Docker 的简介-CSDN博客
这里面的 “为什么要虚拟化、容器化”。
四、容器的生命周期
容器的生命周期是容器可能处于的状态。
- created:初建状态
- running:运行状态
- stopped:停止状态
- paused: 暂停状态
- deleted:删除状态
各生命周期之间的转换关系如图所示:

- docker create:创建容器后,不立即启动运行,容器进入初建状态。
- docker run:创建容器,并立即启动运行,进入运行状态。
- docker start:容器转为运行状态。
- docker stop:容器将转入停止状态。
- docker kill:容器在故障(死机)时,执行 kill(断电),容器转入停止状态,这种操作容易丢失数据,除非必要,否则不建议使用。
- docker restart:重启容器,容器转入运行状态。
- docker pause:容器进入暂停状态。
- docker unpause:取消暂停状态,容器进入运行状态。
- docker rm:删除容器,容器转入删除状态。
- killed by out-of-memory(因内存不足被终止):宿主机内存被耗尽,也被称为 OOM:非计划终止 这时需要杀死最吃内存的容器。
- container process exitde(异常终止):出现容器被终止后,将进入 Should restart?选择操作:yes 需要重启,容器执行 start 命令,转为运行状态。no 不需要重启,容器转为停止状态。
1、容器 OOM
Docker 在处理 OOM 事件时分为三种情况:
- 如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发 OOM 事件。例如:在容器当中,部署了一个 Web 服务。假设主机分配给此容器的内存上限为 1G,当脚本申请的内存大于 1G 时,此容器就会触发 OOM 事件。而在这种情况下,此容器将会被强制关闭。但需要注意,此时关闭容器的并非是 Docker Daemon,而是宿主机操作系统。因为一个容器其实就是一组运行在宿主机操作系统当中的进程,宿主机操作系统通过 cgroups 对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿主机操作系统的内核 OOM 事件,因此最终是由宿主机内核来关闭这些进程。
- 如果用户不想关闭这个容器,那么可以选择 --oom-kill-disable 来禁用 OOM-Killer。使用此参数时,仍需要注意,如果使用 -m 设置了此容器内存上限,那么当容器到达内存资源上限时,主机不会关闭容器,但也不会继续向此容器继续分配资源,此时容器将处于 hung 状态。只需要将最坏的情况封闭在一定范围之内,而不至于蔓延出去。
- 如果用户使用了--oom-kill-disable,但也没有使用 -m 来设定上限,因而此时此容器将会尽可能多地使用主机内存资源。换而言之,主机内存有多大,它就将用多大。
2、容器异常退出
每个容器内部都存在一个 Init 进程,容器中其他所有进程都是此进程的子进程。运行的容器是因为 Init 进程在运行,如果一个子进程因为某种原因造成了退出,那么其父进程也会同步退出,直至 Init 进程也退出。当 Init 进程退出时,也就代表着此容器被关闭。ocker 目前没有办法知道此时的进程退出属于正常退出还是异常退出。当出现容器关闭情况时,Docker Daemon 会尝试再次重新将此容器由 Stopped 状态转为 Running 状态。只有设置了 --restart 参数的容器,Docker Daemon 才会去尝试启动,否则容器会保持停止状态。
3、容器暂停
Docker “剥夺” 了此容器的 CPU 资源。而其他资源,如 Memory 资源、Network 资源等还保留未动。如此一来,失去了 CPU 资源的进程,是不会被主机内核系统所调度的,所以此容器就处于“冰封”状态。
五、容器命令清单


六、容器命令详解
1、docker create
(1)功能
创建一个新的容器但不启动它。
(2)语法
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
(3)别名
docker container create
(4)关键参数
- -i:以交互模式运行容器,通常与 -t 同时使用。
- -P:随机端口映射,容器内部端口随机映射到主机的端口。
- -p:指定端口映射,格式为:主机(宿主)端口:容器端口。
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
- --name="nginx-lb":为容器指定一个名称。
- -h "mars":指定容器的 hostname。
- -e username="ritchie":设置环境变量。
- --cpuset-cpus="0-2" or --cpuset-cpus="0,1,2":绑定容器到指定 CPU 运行。
- -m:设置容器使用内存最大值。
- --network="bridge":指定容器的网络连接类型。
- --link=[]:添加链接到另一个容器。
- --volume,-v:绑定一个卷。
- --rm:shell 退出的时候自动删除容器。
- --restart:自动重启。
(5)样例

2、docker run
(1)功能
创建一个新的容器并运行一个命令。
(2)语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
(3)别名
docker container run
(4)关键参数
- -d:后台运行容器,并返回容器 ID(比 create 多了这个参数)。
- -i:以交互模式运行容器,通常与 -t 同时使用。
- -P:随机端口映射,容器内部端口随机映射到主机的端口。
- -p:指定端口映射,格式为:主机(宿主)端口:容器端口。
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
- --name="nginx-lb":为容器指定一个名称。
- -h "mars":指定容器的 hostname。
- -e username="ritchie":设置环境变量。
- --cpuset-cpus="0-2" or --cpuset-cpus="0,1,2":绑定容器到指定 CPU 运行。
- -m:设置容器使用内存最大值。
- --network="bridge":指定容器的网络连接类型。
- --link=[]:添加链接到另一个容器。
- --volume,-v:绑定一个卷。
- --rm:shell 退出的时候自动删除容器。
- --restart:自动重启。
(5)样例
A. 使用 docker 镜像 nginx:1.23.4 以后台模式启动一个容器,将容器的 8051 端口映射到主机的 80 端口,并将容器命名为 mywebsite4
![]()
3、docker ps
(1)功能
列出容器。
(2)语法
docker ps [OPTIONS]
(3)别名
(4)关键参数
- -a:显示所有的容器,包括未运行的。
- -f:根据条件过滤显示的内容。
- --format:指定返回值的模板文件,如 json 或者 table。
- -l:显示 latest 的容器。
- -n:列出最近创建的 n 个容器。
- --no-trunc:不截断输出。
- -q:静默模式,只显示容器编号。
- -s:显示总的文件大小。
(5)样例

4、docker logs
(1)功能
查看容器日志。
(2)语法
docker logs [OPTIONS] CONTAINER
(3)别名
docker container logs
(4)关键参数
- -f,--follow:跟踪日志输出。
- --since:显示某个开始时间的所有日志。
- -t,--timestamps:显示时间戳。
- -n,--tail:仅列出最新 N 条容器日志。
(5)样例
A. 跟踪查看容器 mywebsite4 的日志输出

B. 查看容器 mynginx 从 2024 年 8 月 1 日后的最新 10 条日志

5、docker attach
(1)功能
连接到正在运行中的容器。
(2)语法
docker attach [OPTIONS] CONTAINER
(3)别名
(4)关键参数
- --sig-proxy:是否将所有信号代理,默认是 true,如果设置为 false,退出的话不会影响容器,否则退出会导致容器退出。
(5)样例
此处按了 Ctrl + C 后会把容器杀死。

此处按了Ctrl + C 不会把容器杀死。
显示报文为:
- CONTAINER ID:容器 ID。
- IMAGE:使用的镜像。
- COMMAND:启动容器时运行的命令。
- CREATED:容器的创建时间。
- STATUS:容器状态。
- PORTS:容器的端口信息和使用的连接类型(tcp \ udp)。
- NAMES:自动分配的容器名称。
6、docker exec
(1)功能
在容器中执行命令。
(2)语法
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
(3)别名
docker container exec
(4)关键参数
- -d:分离模式: 在后台运行。
- -i:即使没有附加也保持 STDIN 打开。
- -t:分配一个伪终端。
- -e:设置环境变量。
- -u,--user:指定用户 "<name|uid>[:<group|gid>]"。
- -w,--workdir:指定工作目录。
(5)样例
A. 在容器 mynginx 中以交互模式执行 echo
![]()
B. 在容器 mynginx 中以交互模式打开 shell

C. 通过 id 进去,docker ps 可以看到容器 id

7、docker start
(1)功能
启动停止的容器。
(2)语法
docker start [OPTIONS] CONTAINER [CONTAINER...]
(3)别名
docker container start
(4)样例
![]()
8、docker stop
(1)功能
停止运行的容器。
(2)语法
docker stop [OPTIONS] CONTAINER [CONTAINER...]
(3)别名
docker container stop
(4)关键参数
- -s:发送的信号。
(5)样例
![]()
9、docker restart
(1)功能
重启容器。
(2)语法
docker restart [OPTIONS] CONTAINER [CONTAINER...]
(3)别名
(4)关键参数
- -s:发送信号
(5)样例
![]()
10、docker kill
(1)功能
强制退出容器。
(2)语法
docker kill [OPTIONS] CONTAINER [CONTAINER...]
(3)别名
(4)关键参数
- -s:发送的信号
注意 :Docker stop 发送的是 SIGTERM 信号, docker kill 发送的是 SIGKILL 信号。
(5)样例
![]()
11、docker top
(1)功能
查看容器中运行的进程信息,支持 ps 命令参数。
(2)语法
docker top CONTAINER [ps OPTIONS]
(3)别名
docker container top
注意 :容器运行时不一定有 /bin/bash 终端来交互执行 top 命令,而且容器还不一定有 top 命令,可以使用 docker top 来实现查看 container 中正在运行的进程。
(4)样例
A. 查看容器进程信息
![]()
12、docker stats
(1)功能
显示容器资源的使用情况,包括: CPU 、内存、网络 I/O 等。
(2)语法
docker stats [OPTIONS] [CONTAINER...]
(3)别名
docker container stats
(4)关键参数
- --all,-a:显示所有的容器,包括未运行的。
- --format:指定返回值的模板文件。如 table、json。
- --no-stream:展示当前状态就直接退出了,不再实时更新。
- --no-trunc:不截断输出。
(5)返回报文
- CONTAINER ID 与 NAME:容器 ID 与名称。
- CPU % 与 MEM %:容器使用的 CPU 和内存的百分比。
- MEM USAGE / LIMIT:容器正在使用的总内存,以及允许使用的内存总量。
- NET I/O:容器通过其网络接口发送和接收的数据量。
- BLOCK I/O:容器从主机上的块设备读取和写入的数据量。
- PIDs:容器创建的进程或线程数。
(6)样例
A. 列出所有在运行的容器信息

B. json 格式显示

C. 定制化的表格显示

13、docker container inspect
(1)功能
查看容器详细信息。
(2)语法
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
(3)关键参数
- -f:指定返回值的模板文件。如 table、json。
- -s:显示总的文件大小。
注意 :docker inspect 会自动检查是镜像还是容器然后显示相信信息。
(4)样例
14、docker port
(1)功能
用于列出指定的容器的端口映射,或者查找将 PRIVATE_PORT NAT 到面向公众的端口。
(2)语法
docker port CONTAINER [PRIVATE_PORT[/PROTO]]
(3)别名
docker container port
(4)样例
15、docker cp
(1)功能
在容器和宿主机之间拷贝文件。
(2)语法
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
(3)别名
docker container cp
(4)样例

16、docker diff
(1)功能
检查容器里文件结构的更改。
(2)语法
docker diff CONTAINER
(3)样例
17、docker commit
(1)功能
从容器创建一个新的镜像。
(2)语法
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
(3)参数
- -a:提交的镜像作者。
- -c:使用 Dockerfile 指令来创建镜像;可以修改启动指令。
- -m:提交时的说明文字。
- -p:在 commit 时,将容器暂停。
(4)样例





18、docker pause
(1)功能
暂停容器中所有的进程。
(2)语法
docker pause CONTAINER [CONTAINER...]
(3)别名
(4)样例

19、docker unpause
(1)功能
恢复容器中所有的进程。
(2)语法
docker unpause CONTAINER [CONTAINER...]
(3)别名
docker container unpause
(4)样例

20、docker rm
(1)功能
删除停止的容器。
(2)语法
docker rm [OPTIONS] CONTAINER [CONTAINER...]
(3)别名
(4)关键参数
- -f:通过 SIGKILL 信号强制删除一个运行中的容器。
(5)样例
A. 删除 mywebsite6 容器

B. 删除所有停止的容器
docker rm $(docker ps -a -q)
21、docker export
(1)功能
导出容器内容为 tar 文件
(2)语法
docker export [OPTIONS] CONTAINER
(3)别名
docker container export
(4)关键参数
- -o:写入到文件。
(5)样例
A. 导出 mywebsite7 为 tar

22、docker wait
(1)功能
阻塞运行直到容器停止,然后打印出它的退出代码。
(2)语法
docker wait CONTAINER [CONTAINER...]
(3)别名
(4)样例

23、docker rename
(1)功能
重命名容器。
(2)语法
docker rename CONTAINER NEW_NAME
(3)别名
(4)样例
24、docker container prune
(1)功能
删除所有停止的容器。
(2)语法
docker container prune [OPTIONS]
(3)关键参数
- -f,--force:不提示是否进行确认。
(4)样例


25、docker update
(1)功能
更新容器配置。
(2)语法
docker update [OPTIONS] CONTAINER [CONTAINER...]
(3)别名
docker container update
(4)关键参数
- --cpus:cpu 数量。
- --cpuset-cpus:使用哪些 cpu。
- --memory:内存限制。
- --memory-swap:交换内存。
- --cpu-period:是用来指定容器对 CPU 的使用要在多长时间内做一次重新分配。
- --cpu-quota:是用来指定在这个周期内,最多可以有多少时间用来跑这个容器。
(5)样例
A. 更新内存

七、容器操作案例
1、容器基本操作
(1)通过 nginx 镜像文件创建容器
![]()
(2)查看容器的详细信息

(3)停止当前正在运行的容器并删除

2、容器状态迁移
(1)创建容器

(2)通过 docker ps们可以看到容器状态为已经创建
![]()
(3)通过 docker start 启动容器
![]()
(4)通过 docker ps 可以看到容器为已经运行
![]()
(5)通过 docker stop 可以停止容器

(6)再次启动容器,然后 kill 容器

(7)启动容器,然后暂停容器

(8)恢复容器
![]()
(9)重启容器
可以看到容器的启动时间变短:

(10)通过 docker rm 可以删除容器

3、容器批量处理技巧

- -a:表示打印所有的容器信息, 包括正在运行和已经退出的。
- -q:表示只返回容器 ID。
- -f:表示基于给的条件过滤 等价于 --filter 选项。
(1)批量删除容器
A. 查看当前容器列表
B. 删除命令后边加多个容器 ID(比较麻烦,不建议使用)
docker container rm 43 49 50 ...
C. 通过参数传递方式批量删除容器(推荐使用)
docker container rm $(docker container ls -aq)
D. 查看当前容器列表,发现已经批量删除完毕
docker container ls -a
(2)按照状态过滤删除已经退出的容器
A. 查看当前容器列表

B. 按照状态过滤删除已经退出的容器
docker container rm $(docker container ls -q --filter status=exited)
C. 确认是否删除
docker container ls -a
注意 :其他命令在做批量处理的时候同样可以类比, 比如批量停止: docker container stop $( docker container ps -aq )
4、容器交互模式
(1)attached 模式
A. 通过 nginx 镜像创建一个容器,映射 80 端口

-p 8106:80 表示端口映射,第一个端口表示映射到宿主机的端口,第二个端口表示映射到 Docker 容器的端口。
- 通过上述方式创建容器,就是 attached 模式,这样容器会在前台运行。
- 访问服务器网址的时候,每访问一次,命令窗口就会打印一次日志,Docker 容器的日志会实时的展现到窗口并且占用此端口。
- 如果是在 Linux 服务器上,按 Ctrl+C 就会停止掉 Docker 服务,很容易误操作,所以需要一个更好的,更稳定的模式,对应的是 detached 模式。
- attached 模式仅适用于容器和程序的调试阶段
下面实践一下 attached 模式的用法:
- 第一步:以 attached 模式创建运行容器,映射到宿主机的 80 端口:

- 第二步:访问服务器的 8106 端口,用浏览器访问服务器 ip 或者域名,默认访问 80 端口:

可以看到 nginx 主页已经展现在浏览器上,当我们刷新访问后发现在标准输出上会打印一些相关的 log 出来。
- 第三步:键入 Ctrl + C

执行命令查看当前容器状态,可以发现该容器已经退出:
![]()
(2)detached 模式
在 docker container run -p 80:80 nginx 命令基础上加一个-d 或者 --detach 选项表示 detached 模式,即在后台执行。
- 在后台运行,启动后只显示容器 ID,并且可以输入任何命令。
- 就算关掉窗口依然继续运行,停止和删除容器都需要使用 shell 命令,减少了很多的误操作。
- 比起 attached 模式更建议使用。
下面来实践一下 detached 模式的用法:
- 第一步:以 detached 模式创建容器,并映射 80 端口:
![]()
- 第二步:浏览器访问服务器网址,并查看后台日志。
刷新浏览器可以看到此时在后台已经打印出来相关的日志:

![]()
- 动态跟踪日志:后台日志窗口只会打印一次日志。如果想动态跟踪日志,可以加 -f 选项;如果想关闭日志跟踪模式,可以键入 Ctrl+C 结束。

- detached 模式转 attached 模式

(3)interactive 模式
当创建好一个容器之后,可能需要去容器内部获取一些信息或执行一些命令,就需要进入到交互式模式。例如创建一个 Ubuntu 容器之后,需要到系统里输入各种 Shell 命令和系统进行交互就需要进入交互式模式才可以完成。
A. 创建运行容器并进入到交互模式

进入到容器的交互 shell 中,可以在该 shell 下执行对应的命令:
![]()
- -i:保持容器运行。通常与 -t 同时使用,加入 it 这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。

此时就可以正常访问了:

B. 针对一个已经运行的容器里进入到交互模式
a. 在后台创建运行 nginx 容器
![]()
b. 进入该容器的交互模式

C. 退出交互式模式
输入 Ctrl + C 并不会产生什么影响,在交互式 shell 中输入 exit 则退出:
![]()
5、容器与宿主机内容复制
(1)启动一个 nginx 服务

(2)拷贝宿主机文件到容器中

(3)进入容器中查看

(4)在宿主机上编译一个 index.html 文件

(5)从外部页面访问

(6)将宿主机上的 index.html 拷回容器中
![]()
(7)回到容器中查看内容,发现文件已经覆盖

(8)再次访问页面

(9)清理容器,释放空间

6、容器自动删除
(1)启动一个 nginx,指定 --rm 选项
(2)停止容器
![]()
(3)再次查看容器是否存在
发现容器自动删除了:
![]()
7、容器自动重启
容器重启选项如下:
- docker run --restart=no [容器名]:默认值不自动重启。
- docker run --restart=on-failure:3 [容器名]:on-failure 若容器的退出状态非 0,则 docker 自动重启容器,还可以指定重启次数,若超过指定次数未能启动容器则放弃。
- docker run --restart=always [容器名] :always 容器退出时总是重启。
- docker run --restart=unless-stopped [容器名] unless-stopped 容器退出时总是重启,但不考虑 Docker 守护进程启动时就已经停止的容器。
如果容器启动时没有设置–restart 参数,则通过下面命令进行更新:
- docker update --restart=always [容器名]
(1)启动 nginx 服务,指定总是重启

(2)进入容器中停止 nginx 服务

(3)查看进程状态,可以看到进程还是启动状态

(4)释放空间

8、容器环境变量设置
(1)启动一个 nginx 容器
配置环境变量:
![]()
(2)进入容器查看环境变量

(3)通过配置文件完成环境变量的设置

9、容器详情查看
可以查看一个容器的详细信息,比如我们可以查看所有设置的环境变量。
(1)启动容器
![]()
(2)查看容器信息


(3)释放资源

10、容器执行单行命令
可以直接借助 docker 的容器环境执行一些命令,比如容器中有某个命令而宿主机上没有这个时候借助容器可以完成某些任务。

11、容器镜像导入导出
(1)创建目录
![]()
(2)运行一个 nginx 镜像,然后修改首页内容

(3)访问首页

(4)通过 docker export 保存镜像

(5)通过 docker import 导入镜像
![]()

(6)停止现在的容器,重新启动容器
![]()
(7)使用导出的镜像启动一个新的容器
![]()
如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似 "docker: Error response from daemon: Container command not found or does not exist" 的错误。我们必须指定启动命令,因为 export 丢失了元数据信息。
12、容器日志查看
(1)启动一个 nginx
![]()
(2)查看全部日志

(3)实时查看日志
刷新访问几次页面:


(4)查看最新的 5 行日志

(5)停止容器释放资源
![]()
13、容器资源查看
(1)运行一个 nginx
![]()
(2)通过 docker top 查看容器中有哪些进程
添加 aux,可以看到占用的内存和 CPU 信息:

(3)通过 docker stats 可以看到资源的实时占用变化

(4)释放资源

八、综合实战一(Mysql 容器化安装)
1、进入 mysql 的镜像网站,查找 mysql 的镜像
官方网站:mysql - Official Image | Docker Hub

2、选择使用最多的 5.7 版本,拉取镜像

3、mysql 的默认端口是 3306,而且有密码
查看官网的启动用例:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d
mysql:tag 指定了 mysql 的密码信息
启动一个 mysql,并指定密码和端口开放:
![]()
4、进入容器登录
可以看到已经可以正常登录 mysql 了:

5、如果对外开放了 8201 端口且没有防火墙的话,可以通过 GUI 工具远程登录到界面上。
以 mysql workbench 为例:




九、综合实战二(Redis 容器化安装)
1、Redis 简介
(1)Redis 出现的原因
在 Web 应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候 Web 站点基本上访问和并发不高、交互也较少。后来随着访问量的提升,使用关系型数据库的 Web 站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的 I/O 上。而随着互联网技术的进一步发展,各种类型的应用层出不穷,这导致在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体现在以下几个方面:
- 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度。
- 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用 PB 级别的数据和能应对百万级的流量。
为了克服这一问题,NoSQL 应运而生,它同时具备了高性能、可扩展性强、高可用等优点,受到广泛开发人员和仓库管理人员的青睐。
(2)Redis 是什么
Redis 全称 Remote Dictionary Server,中文名为远程字典服务器。Redis 是现在最受欢迎的 NoSQL 数据库之一,Redis 是一个使用 ANSI C 编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:
- 基于内存运行,性能高效。
- 支持分布式,理论上可以无限扩展。
- key-value 存储系统。
开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。
(3)Redis 的应用场景
几乎所有的大厂都在使用 Redis。Redis 提供了多种数据类型,String 类型、哈希类型、列表类型、集合类型和顺序集合类型,借助这些类型可以方便的实现多种应用,如缓存系统(“热点” 数据:高频读、低频写)、计数器、消息队列系统、实时排行榜、社交网络。
2、Redis 生活案例
Redis 就像一个新华字典,可以根据某个字符可以很快的找到字典对应的字。
3、Redis 容器创建
(1)下载 redis 镜像
官方网站:redis - Official Image | Docker Hub


(2)启动 redis 容器
![]()
(3)进入容器,设置一个 key
![]()
(4)如果开通了防火墙,我以通过可视化工具连接上
可视化工具下载地址:AnotherRedisDesktopManager 发行版 - Gitee.com

双击下载好的 .exe 文件:

选择为所有用户安装:

修改安装目录:



(5)配置链接

(6)查看 key

十、综合实战三(C++ 容器制作)
1、源是什么
源就是来源。就是你安装软件时,程序从哪里获取软件包(安装程序在你的机器上,但需要安装的东西却在软件源服务器上)。
源在 Ubuntu 下,它相当于软件库,需要什么软件,只要记得正确的软件名就可以用命令抄安装:其实你可以把他称为软件仓库。安装软件时,就是从仓库里面调取数据放在你的机器上。
sudo apt-get install 软件名
例如:要安装 gcc 软件,那么就可以再终端中输入 sudo apt-get install gcc,这样就能帮我们装好 gcc 软件,如果源里没有这个软件时,此命令就没法完成。
2、什么是镜像
镜像(Mirroring)是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。
常见的镜像文件格式有 ISO、BIN、IMG、TAO、DAO、CIF、FCD。
所谓镜像文件其实和 ZIP 压缩包类似,它将特定的一系列文件按照一定的格式制作成单一的文件,以方便用户下载和使用,例如一个测试版的操作系统、游戏等。(安装过操作系统的人应该对 xxx.iso 不陌生)
镜像文件不仅具有 ZIP 压缩包的“合成”功能,它最重要的特点是可以被特定的软件识别并可直接刻录到光盘上。
3、镜像源
镜像源就是把官方的源做一个镜像,可以在这下载软件。比如:ubuntu 官方源在国外,下载软件可能会很慢,这时候就需要换成国内的镜像源。
基于 ubuntu 来制作 C++容器,运行输出 "HelloWorld"。
可以把镜像源当做一个代理商,比如买车本来要去车厂,但是设置了一个个 4S 店以后,直接去 4S 店就好了,不用跑到车厂。
5、制作 C++ 容器
(1)下载 Centos 镜像
(2)启动容器
![]()
(3)配置国内镜像源加速
CentOS Vault - USTC Mirror Help


(4)安装 gcc vim

(5)编辑代码
![]()

(6)编译代码

(7)在容器中运行
![]()
(8)退出容器
![]()
(9)这个时候可以看到我们的容器已经退出了,如果想再次进入使用 docker restart 就可以恢复容器
十一、综合实战四(SpringBoot 容器制作)
1、编写 demo
使用 Spring Boot 创建一个简单的 demo, 在浏览器输出:"hello docker!"。
(1)创建 maven 项目
选择 Spring Boot 2.x 的第一个发布版本 2.0.2.RELEASE,如下在 pom.xml 中添加 spring-boot 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springboot-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!-- 项目的 pom 定义继承自 SpringBoot 的父 pom -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<!-- Web 项目,添加spring-boot-starter-web依赖即可,版本号由父pom已经定义好了,此处省略 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 添加 spring boot 项目构建插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
(2)编写主函数构建 Spring 容器
package com.bittech.boot;
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
(3)编写控制器
package com.bittech.boot;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/hello")
public class ExampleController {
@RequestMapping(value = "")
public String index() {
return "Hello Spring Boot for Docker World!";
}
}
(4)使用 maven 打包生成 jar 包

生成的 jar 包位于项目根路径下的 target 目录:

(5)测试 jar 包是否可用
# 在 cmd 中执行命令测试 jar 包是否可用
java -jar D:\code\java_relearn\springboot-demo\target\springboot-demo-1.0-SNAPSHOT.jar
启动容器后,访问 localhost:8080/hello 查看运行结果,确认 jar 包可用:

(6)上传到 Linux 服务器备用
[root@VM-8-5-centos spring_demo]$ pwd
/home/zsc/dockerfile/spring_demo
[root@VM-8-5-centos spring_demo]$ ls
Dockerfile springboot-demo-1.0-SNAPSHOT.jar
2、制作容器
(1)下载 Ubuntu 镜像
root@139-159-150-152:/data/myworkdir/container# docker pull
ubuntu:22.04
22.04: Pulling from library/ubuntu
2ab09b027e7f: Pull complete
Digest:
sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428
a6d21
Status: Downloaded newer image for ubuntu:22.04
docker.io/library/ubuntu:22.04
(2)启动容器
root@139-159-150-152:/data/myworkdir/container# docker run -p
8080:8080 --name myjava -it ubuntu:22.04 bash
root@50d527b8343e:/#
(3)配置国内镜像源加速
root@50d527b8343e:/# sed -i
's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g'
/etc/apt/sources.list
root@50d527b8343e:/#
(4)安装 jdk
apt update
apt install -y openjdk-8-jdk
(5)打开新的 shell 窗口,将 jar 拷贝到容器里面
docker cp ./springboot-demo-1.0-SNAPSHOT.jar myjava:/app.jar
(6)查看容器中文件
root@071ceaad511a:/# ll
total 15824
drwxr-xr-x 1 root root 4096 Mar 24 10:28 ./
drwxr-xr-x 1 root root 4096 Mar 24 10:28 ../
-rwxr-xr-x 1 root root 0 Mar 24 10:24 .dockerenv*
-rw-r--r-- 1 root root 16125993 Mar 24 10:23 app.jar
lrwxrwxrwx 1 root root 7 Mar 8 02:05 bin -> usr/bin/
drwxr-xr-x 2 root root 4096 Apr 18 2022 boot/
drwxr-xr-x 5 root root 360 Mar 24 10:24 dev/
drwxr-xr-x 1 root root 4096 Mar 24 10:27 etc/
drwxr-xr-x 2 root root 4096 Apr 18 2022 home/
lrwxrwxrwx 1 root root 7 Mar 8 02:05 lib -> usr/lib/
lrwxrwxrwx 1 root root 9 Mar 8 02:05 lib32 -> usr/lib32/
lrwxrwxrwx 1 root root 9 Mar 8 02:05 lib64 -> usr/lib64/
lrwxrwxrwx 1 root root 10 Mar 8 02:05 libx32 -> usr/libx32/
drwxr-xr-x 2 root root 4096 Mar 8 02:05 media/
drwxr-xr-x 2 root root 4096 Mar 8 02:05 mnt/
drwxr-xr-x 2 root root 4096 Mar 8 02:05 opt/
dr-xr-xr-x 206 root root 0 Mar 24 10:24 proc/
drwx------ 2 root root 4096 Mar 8 02:08 root/
drwxr-xr-x 1 root root 4096 Mar 24 10:27 run/
lrwxrwxrwx 1 root root 8 Mar 8 02:05 sbin -> usr/sbin/
drwxr-xr-x 2 root root 4096 Mar 8 02:05 srv/
dr-xr-xr-x 13 root root 0 Mar 24 10:24 sys/
drwxrwxrwt 1 root root 4096 Mar 24 10:27 tmp/
drwxr-xr-x 1 root root 4096 Mar 8 02:05 usr/
drwxr-xr-x 1 root root 4096 Mar 8 02:08 var/
(7)启动 java 服务
java -jar ./app.jar
(8)通过浏览器访问页面,注意确保防火墙打开

(9)Ctrl + C 退出服务,exit 退出容器
十二、综合实战五(容器资源更新)
1、运行一个 nginx
![]()
2、可以通过 docker top 查看容器中有哪些进程,添加 aux,可以看到占用的内存和 CPU 信息

3、查看资源的动态变化

4、通过 docker update 更新 docker 的最大内存
![]()
5、再次查看资源动态
通过 docker stats,可以看到内存已经被限制到 300m 了:

6、在容器中执行一个命令,打满 cpu
for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`
do
dd if=/dev/zero of=/dev/null &
done
# cat /proc/cpuinfo |grep “physical id” | wc -l 可以获得CPU的个数,将其表示为 N
# seq 1 N 用来生成1~N之间的数字
# for i in seq 1 N; 就是从1~N循环执行命令
# dd if=/dev/zero of=/dev/null 执行dd命令,输出到/dev/null,实际上只占用CPU,没有IO操作
# 由于连续执行N个(N是CPU个数)的dd命令,且使用率为100%,这时调度器会调度每个dd命令在不同的CPU上处理,最终就实现所有CPU占用率100%

![]()
7、执行命令配置只能使用 10% 的 cpu
![]()
8、可以看到 cpu 已经只能到 10% 左右
![]()
十三、常见问题
docker create、docker start 和 docker run 有什么区别?
docker create 命令从 Docker 映像创建一个全新的容器。但是,它不会立即运行它。
docker start 命令将启动任何已停止的容器。如果使用 docker create 命令创建容器,则可以使用此命令启动它。
docker run 命令是创建和启动的组合,因为它创建了一个新容器并立即启动它。实际上,如果 docker run 命令在您的系统上找不到上述映像,它可以从 Docker Hub 中提取映像。
docker import 和 docker load 有什么区别?
要了解 docker load 与 docker import 命令的区别,还必须知道 docker save 与 docker export 命令。
- docker save images_name:将一个镜像导出为文件,再使用 docker load 命令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比 docker export 命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。
- docker export container_id:将一个容器导出为文件,再使用 docker import 命令将容器导入成为一个新的镜像,但是相比 docker save 命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
既可以使用 docker load 命令来导入镜像库存储文件到本地镜像库,也可以使用 docker import 命令来导入一个容器快照到本地镜像库。二者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也会更大。
docker rm & docker rmi & docker prune 的差异?
- docker rm:删除一个或多个容器。
- docker rmi:删除一个或多个镜像。
- docker prune:用来删除不再使用的 docker 对象。
更多推荐









所有评论(0)