目录
- 1. 什么是容器?
- 2. 容器的生命周期
- 2.1 容器处理OOM事件
- 2.2 容器异常退出
- 2.3 容器暂停
- 3. 容器命令详解
- 3.1 容器命令清单
- 3.2 docker create命令
- 3.3 docker run命令
- 3.4 docker ps命令
- 3.5 docker logs命令
- 3.6 docker attach命令
- 3.7 docker exec命令
- 3.8 docker stats命令
- 3.9 docker commit命令
- 3.10 docker update命令
- 4. 容器操作案例
- 4.1 容器基本操作
- 4.2 容器状态迁移
- 4.3 容器批量处理技巧
- 4.4 容器交互模式
- 4.4.1 attached 模式
- 4.4.2 detached 模式
- 4.4.3 interactive 模式
- 4.5 容器与宿主机内容复制
- 4.6 容器的自动删除和重启
- 4.7 容器环境变量设置、详情查看、执行单行命令
- 4.8 容器镜像的导入导出
- 4.9 容器日志查看、资源查看
- 5. Mysql 容器化安装
- 6. Redis 容器化安装
- 7. C++容器制作
- 7.1 源的介绍
- 7.2 什么是镜像
- 7.3 镜像源
- 7.4 制作 c++容器
- 8. 容器资源更新
- 9. 常见问题总结
- 9.1 docker create、docker start和docker run 有什么区别?
- 9.2 docker import 和 docker load 有什么区别?
- 9.3 docker rm & docker rmi & docker prune 的差异?
1. 什么是容器?
(1)容器的概念:
-
通俗地讲,容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容器有初建、运行、停止、暂停和删除五种状态。
-
虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。也就是说,在容器内部,无法看到主机上的进程、环境变量、网络等信息,这是容器与直接运行在主机上进程的本质区别。
-
容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。
(2)容器的生活案例来理解。镜像与容器就相当于同样是开发商提供的毛坯房,但是两家人装修出来的完全不一样。
(3)或者我们都学习了 Java 或者 C++之类的面向对象的语言,可以理解为镜像为基础类,容器是实例化出来的一个个对象,用户需要的不一样,里面的内容也就不一样了。
(4)为什么需要容器?
- 镜像是静态的文件,并不能提供服务,就像我拿了个 Linux 或者 Windows 的光盘一样,只有安装到主机里面运行起来才能对外提供服务,我们才能使用。
- 容器带来哪些收益呢,可以参考为什么要虚拟化、容器化。
2. 容器的生命周期
(1)容器的生命周期是容器可能处于的状态。
- created:初建状态。
- running:运行状态。
- stopped:停止状态。
- paused: 暂停状态。
- deleted:删除状态。
(2)各生命周期之间的转换关系如图所示:
- 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 不需要重启,容器转为停止状态。
2.1 容器处理OOM事件
(1)Docker 在处理 OOM 事件时分为三种情况:
- 如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发 OOM 事件。例如,在容器当中,部署了一个 web 服务。假设主机分配给此容器的内存上限为 1G,当脚本申请的内存大于 1G 时,此容器就会触发 OOM 事件。而在这种情况下,此容器将会被强制关闭。但需要注意的是,此时关闭容器的并非是 Docker Daemon,而是宿主机操作系统。因为一个容器其实就是一组运行在宿主机操作系统当中的进程,宿主机操作系统通过cgroups 对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿主机操作系统的内核 OOM 事件,因此最终是由宿主机内核来关闭这些进程。
- 如果用户不想关闭这个容器,那么可以选择–oom-kill-disable 来禁用 OOM-Killer。使用此参数时,仍需要注意,如果使用-m 设置了此容器内存上限,那么当容器到达内存资源上限时,主机不会关闭容器,但也不会继续向此容器继续分配资源,此时容器将处于 hung 状态。只需要将最坏的情况封闭在一定范围之内,而不至于蔓延出去。
- 如果用户使用了–oom-kill-disable,但也没有使用-m 来设定上限,因而此时此容器将会尽可能多地使用主机内存资源。换言之,主机内存有多大,它就将用多大。
2.2 容器异常退出
- 每个容器内部都存在一个 Init 进程,容器中其他所有进程都是此进程的子进程。运行的容器是因为 Init 进程在运行,如果一个子进程因为某种原因造成了退出,那么其父进程也会同步退出,直至 Init 进程也退出。
- 当 Init 进程退出时,也就代表着此容器被关闭。docker 目前没有办法知道此时的进程退出属于正常退出还是异常退出。当出现容器关闭情况时, Docker Daemon 会尝试再次重新将此容器由 Stopped 状态转为 Running状态。只有设置了–restart 参数的容器, Docker Daemon 才会去尝试启动,否则容器会保持停止状态。
2.3 容器暂停
(1)Docker“剥夺”了此容器的 CPU 资源。而其他资源,如 Memory 资源、 Network 资源等还保留未动。如此一来,失去了 CPU 资源的进程,是不会被主机内核系统所调度的,所以此容器就处于“冰封”状态。
3. 容器命令详解
3.1 容器命令清单
(1)容器命令如下:
命令 | 别名 | 功能 |
---|---|---|
docker create | docker container create | 创建容器 |
docker run | docker container run | 运行容器 |
docker attach | docker container attach | 连接到正在运行中的容器。 |
docker commit | docker container commit | 将镜像提交为容器 |
docker cp | docker container cp | 在容器和宿主机之间拷贝 |
docker diff | docker container diff | 检查容器里文件结构的更改。 |
docker exec | docker container exec | 在运行的容器中执行命令 |
docker export | docker container export | 将容器导出为 tar |
docker container inspect | 查看容器详细信息 | |
docker kill | docker container kill | 杀死容器 |
docker logs | docker container logs | 查看日志 |
docker ps | docker container ls,docker container list,docker container ps | 查看正在运行的进程 |
docker pause | docker container pause | 暂停进程 |
docker port | docker container port | 查看容器的端口映射 |
docker container prune | 删除停止的容器 | |
docker rename | docker container rename | 重命名容器 |
docker restart | docker container restart | |
docker rm | docker container rm, docker container remove | 删除容器 |
docker start | docker container start | 启动容器 |
docker stats | docker container stats | 查看资源占用信息 |
docker stop | docker container stop | 停止容器 |
docker top | docker container top | 查看某个容器的资源占用 |
docker unpause | docker container unpause | 继续运行容器 |
docker update | docker container update | 更新容器配置 |
docker wait | docker container wait | 阻止一个或多个容器停止,然后打印退出代码 |
3.2 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)样例:
docker create --name mynginx nginx:latest
3.3 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)样例:
#使用 docker 镜像 nginx:latest 以后台模式启动一个容器,并将容器命名为mynginx。
docker run --name mynginx -d nginx:latest
#使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。
docker run -p 80:80 -v /data:/data -d nginx:latest
3.4 docker ps命令
(1)功能:
- 列出容器。
(2)语法:
docker ps [OPTIONS]
(3)别名:
docker container ls, docker container list, docker container ps
(4)关键参数:
- -a:显示所有的容器,包括未运行的。
- -f:根据条件过滤显示的内容。
- –format:指定返回值的模板文件。如 json 或者 table
- -l:显示 latest 的容器。
- -n:列出最近创建的 n 个容器。
- –no-trunc:不截断输出。
- -q:静默模式,只显示容器编号。
- -s:显示总的文件大小。
(5)样例:
docker ps -a
3.5 docker logs命令
(1)功能:
- 查看容器日志
(2)语法:
docker logs [OPTIONS] CONTAINER
(3)别名:
docker container logs
(4)关键参数:
- -f ,–follow:跟踪日志输出
- –since:显示某个开始时间的所有日志
- -t,–timestamps:显示时间戳
- -n, --tail:仅列出最新 N 条容器日志
(5)样例:
#跟踪查看容器 mynginx 的日志输出。
docker logs -f mynginx1
#查看容器 mynginx 从 2016 年 7 月 1 日后的最新 10 条日志。
docker logs --since="2016-07-01" --tail=10 mynginx
3.6 docker attach命令
(1)功能:
- 连接到正在运行中的容器。
(2)语法:
docker attach [OPTIONS] CONTAINER
(3)别名:
docker container attach
(4)关键参数:
- –sig-proxy:是否将所有信号代理,默认是 true,如果设置为 false,退出的话不会影响容器, 否则退出会导致容器退出。
(5)样例:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker attach mynginx
#此处按了 ctrl+c 后会把容器杀死
^C2023/03/15 06:26:24 [notice] 1#1: signal 2 (SIGINT) received,
exiting
2023/03/15 06:26:24 [notice] 28#28: exiting
2023/03/15 06:26:24 [notice] 28#28: exit
2023/03/15 06:26:24 [notice] 1#1: signal 17 (SIGCHLD) received
from 28
2023/03/15 06:26:24 [notice] 1#1: worker process 28 exited with
code 0
2023/03/15 06:26:24 [notice] 1#1: exit
root@139-159-150-152:/data/myworkdir/dockerfile/cache# docker
attach --sig-proxy=false mynginx
#此处按了 ctrl+c 不会把容器杀死
(6)显示报文为:
- CONTAINER ID:容器 ID。
- IMAGE:使用的镜像。
- COMMAND:启动容器时运行的命令。
- CREATED:容器的创建时间。
- STATUS:容器状态。
- PORTS:容器的端口信息和使用的连接类型(tcp\udp)。
- NAMES:自动分配的容器名称。
3.7 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)样例:
#在容器 mynginx 中以交互模式执行 echo:
docker exec -it mynginx echo "Hello docker"
#在容器 mynginx 中以交互模式打开 shell:
docker exec -it mynginx bash
#通过 id 进去, docker ps 可以看到容器 id
docker exec -it 5706674cc67e bash
3.8 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)样例:
#列出所有在运行的容器信息。
root@139-159-150-152:/data/myworkdir/dockerfile/cache#docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM %
NET I/O BLOCK I/O PIDS
5706674cc67e mynginx 0.00% 4.109MiB / 1.936GiB 0.21%
4.71kB / 3.3kB 11.2MB / 4.1kB 2
#json 格式显示
root@139-159-150-152:/data/myworkdir/dockerfile/cache# docker
stats --format json
{"BlockIO":"11.2MB /
4.1kB","CPUPerc":"0.00%","Container":"5706674cc67e","ID":"5706674c
c67e","MemPerc":"0.12%","MemUsage":"2.352MiB /
1.936GiB","Name":"mynginx","NetIO":"4.71kB / 3.3kB","PIDs":"2"}
#定制化的表格显示
root@139-159-150-152:/data/myworkdir/dockerfile/cache# docker
stats --format "table
{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"
CONTAINER CPU % MEM USAGE / LIMIT
5706674cc67e 0.00% 2.363MiB / 1.936GiB
3.9 docker commit命令
(1)功能:
- 从容器创建一个新的镜像。
(2)语法:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
(3)关键参数:
- -a:提交的镜像作者;
- -c:使用 Dockerfile 指令来创建镜像;可以修改启动指令
- -m:提交时的说明文字;
- -p:在 commit 时,将容器暂停。
(4)样例:
docker commit c3f279d17e0a maxhou/mynginx:v01
3.10 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)样例:
#更新内存
docker update -m 400m myweb
4. 容器操作案例
4.1 容器基本操作
(1)通过 nginx 镜像文件创建容器:
# 不加版本,默认是最新版本
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container run nginx
(2)容器的列举(包含正在运行的容器):
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container ls
(3)停止当前正在运行的容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container stop 4c24c2
(4)容器的列举(包含正在运行和退出的容器):
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container ls -a
# 看到可以列举出已经退出的状态
(5)容器的删除:
# 删除 4c23b59523f7 这个容器
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container rm 4c24c2
# 查看当前容器列表 可以发现 4c23b59523f7 该容器已经被删除
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container ls -a
4.2 容器状态迁移
(1)首先我们创建容器:
#-p 表示端口映射,大家可以理解为访问宿主机的 80 就是方位容器的 80 端口,后续网络原理我们会深入讲解
#docker 的容器网络
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker create --name mynginx1 -p 80:80 nginx:1.22.1
11fc874cea798b02255cfb4993b1ce5efc9b231f28f44e01681e075caf9e28a5
(2)通过 docker ps 我们可以看到容器状态为已经创建:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps -a | grep mynginx1
(3)通过 docker start 启动容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker start mynginx1
mynginx1
(4)通过 docker ps 可以看到容器为已经运行:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps
(5)通过 docker stop 可以停止容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker stop mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps -a | grep mynginx1
(6)再次启动容器,然后 kill 容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker start mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker kill mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps -a | grep mynginx1
(7)启动容器,然后暂停容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker start mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker pause mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps
(8)恢复容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker unpause mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps
(9)重启容器,可以看到容器的启动时间变短了:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
11fc874cea79 nginx:1.22.1 "/docker-entrypoint.…" 5 minutes
ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker restart mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
11fc874cea79 nginx:1.22.1 "/docker-entrypoint.…" 7 minutes
ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp mynginx1
(10)通过 docker rm 可以删除容器:
root@139-159-150-152:~# docker stop mynginx1
mynginx1
root@139-159-150-152:~# docker rm mynginx1
mynginx1
root@139-159-150-152:~# docker ps -a | grep mynginx1
root@139-159-150-152:~#
4.3 容器批量处理技巧
(1)容器批量处理命令:
命令 | 解释 |
---|---|
docker container ls -qf name=xxx | 根据名称过滤得到容器编号 |
docker container ls --filter status=running | 根据状态过滤容器信息 |
docker container ls -aq | 静默获取全部容器 id |
docker container ls --filter ancestor=xxx | 过滤镜像名为 xxx 的容器信息 |
docker container ls --filter ancestor=xxx | 过滤镜像 id 为 xxx 的容器信息 |
- -a:表示打印所有的容器信息, 包括正在运行和已经退出的。
- -q:表示只返回容器 ID。
- -f:表示基于给的条件过滤 等价于 --filter 选项。
4.4 容器交互模式
4.4.1 attached 模式
(1)attached模式命令如下:
# 通过 nginx 镜像创建一个容器, 映射 80 端口
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container run -p 80:80 nginx
- -p 80:80 表示端口映射,第一个端口表示映射到宿主机的端口,第二个端口表示映射到 Docker 容器的端口, 这个在网络章节会详细讲解。
- 通过上述方式创建容器,就是 attached 模式,这样容器会在前台运行。
- 访问服务器网址的时候,每访问一次,命令窗口就会打印一次日志, Docker 容器的日志会实时的展现到窗口并且占用此端口。
- 如果是在 Linux 服务器上,按 Ctrl+C 就会停止掉 Docker 服务,很容易误操作,所以我们需要一个更好的,更稳定的模式,对应的是 detached 模式。
- attached 模式仅适用于容器和程序的调试阶段。
(2)下面实践一下 attached 模式的用法:
- 第一步:以 attached 模式创建运行容器, 映射到宿主机的 80 端口
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container run -p 80:80 nginx
- 第二步:访问服务器的 80 端口,用浏览器访问服务器 ip 或者域名,默认访问 80端口。
可以看到 nginx 主页已经展现在浏览器上。当我们刷新访问后发现在标准输出上会打印一些相关的 log 出来。
- 第三步:键入 Ctrl + C。
# 键入 Ctrl + C
# 执行命令查看当前容器状态, 可以发现该容器已经退出掉了
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container ls -a
4.4.2 detached 模式
(1)在 docker container run -p 80:80 nginx 命令基础上加一个-d 或者–detach选项表示 detached 模式, 即在后台执行:
- 在后台运行,启动后只显示容器 ID,并且可以输入任何命令。
- 就算关掉窗口依然继续运行,停止和删除容器都需要使用 shell 命令,减少了很多的误操作。
- 比起 attached 模式更建议使用。
(2)下面来实践一下 detached 模式的用法:
- 第一步:以 detached 模式创建容器, 并映射 80 端口
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container run -d -p 80:80 nginx
# 执行结果 返回容器 ID
50147dca69d7d84271476def3a10e030001e3bcd4f2f5c6cb6a7f8b93b8d9a3b
- 第二步:浏览器访问服务器网址,并查看后台日志
# 查看后台日志
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container logs 501
- 刷新浏览器可以看到此时在后台已经打印出来相关的日志
- 动态跟踪日志:后台日志窗口只会打印一次日志。如果想动态跟踪日志,可以加-f选项;如果想关闭日志跟踪模式,可以键入 Ctrl+C 结束
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container logs -f 501
- detached 模式转 attached 模式
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container attach 501
4.4.3 interactive 模式
(1)当我们创建好一个容器之后, 可能需要去容器内部获取一些信息或执行一些命令,就需要进入到交互式模式。例如创建一个 Ubuntu 容器之后,需要到系统里输入各种Shell 命令和系统进行交互就需要进入交互式模式才可以完成。
- 创建运行容器并进入到交互模式
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container run -it nginx sh
# 进入到容器的交互 shell 中,可以在该 shell 下执行对应的命令
# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc
home lib lib64 media mnt opt proc root run sbin srv
sys tmp usr var
- -i:保持容器运行。通常与 -t 同时使用,加入 it 这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
- 针对一个已经运行的容器里进入到交互模式。
# 在后台创建运行 nginx 容器
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container run -d -p 80:80 nginx
50147dca69d7d84271476def3a10e030001e3bcd4f2f5c6cb6a7f8b93b8d9a3b
# 进入该容器的交互模式
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container exec -it 501 sh
# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc
home lib lib64 media mnt opt proc root run sbin srv sys
tmp usr var
- 退出交互式模式: 在交互式 shell 中输入 exit
exit
4.5 容器与宿主机内容复制
(1)我们启动一个 nginx 服务:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker run --name mynginx1 -p 80:80 -d nginx:1.22.1
(2)在宿主机上编译一个 index.html 文件:
[xiaomaker@xiaomaker-virtual-machine:docker]$ mkdir -p /data/myworkdir/container
[xiaomaker@xiaomaker-virtual-machine:docker]$ cd /data/myworkdir/container
[xiaomaker@xiaomaker-virtual-machine:container]$ echo "Hello from my container" > index.html
(3)拷贝宿主机文件到容器中:
docker cp /data/myworkdir/container/index.html mynginx1:/usr/share/nginx/html/
(4)进入容器中查看:
[xiaomaker@xiaomaker-virtual-machine:html]$ cd /usr/share/nginx/html/
(5)从外部页面访问:
(6)在容器中编辑 index.html:
[xiaomaker@xiaomaker-virtual-machine:html]$ echo " after edit" >> index.html
(7)执行 docker cp 将内容拷贝出来,查看内容,发现文件已经覆盖:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker cp mynginx1:/usr/share/nginx/html/index.html ./
(8)清理容器,释放空间:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker stop mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:container]$ docker rm mynginx1
mynginx1
4.6 容器的自动删除和重启
(1)自动删除:
- 启动一个 nginx,我们指定–rm 选项:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run --name mynginx1 -d --rm -p 80:80 nginx:1.22.1
- 停止容器:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker stop mynginx1
mynginx1
- 再次查看容器是否存在,发现容器自动删除了:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker ps -a
(2)自动重启。容器重启选项如下:
- 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 [容器名]。
(3)启动 nginx 服务,指定总是重启:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run --name mynginx1 -d -p 80:80 --restart always nginx:1.22.1
93e8aede76ac7cc09f34e3510b590abae6161eceb2d39cdbcf8d64f86154f9ca
(4)进入 nginx 服务, kill 启动进程:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker exec -it mynginx1 bash
root@93e8aede76ac:/# kill 1
root@93e8aede76ac:/#
(5)查看进程状态,可以看到进程还是启动状态:
root@93e8aede76ac:/# root@139-159-150-152:/data/myworkdir/container# docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
93e8aede76ac nginx:1.22.1 "/docker-entrypoint.…" 22 seconds
ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp mynginx1
(6)释放空间:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker stop mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:container]$ docker rm mynginx1
mynginx1
4.7 容器环境变量设置、详情查看、执行单行命令
(1)环境变量设置:
- 启动一个 nginx 容器,配置环境变量, TEST=1:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run --name mynginx1 -d -p 80:80 -e TEST=1 nginx:1.22.1
a5bc48b9560b0cc0aa0018af3572ce2024a9d7e37859c4f905c1f6ff11401b8e
- 进入容器查看环境变量:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker exec -it mynginx1 bash
root@a5bc48b9560b:/# env |grep TEST
TEST=1
root@a5bc48b9560b:/# exit
exit
- 清理空间:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker stop mynginx1
mynginx1
[xiaomaker@xiaomaker-virtual-machine:container]$ docker rm mynginx1
mynginx1
(2)详情查看:我们可以查看一个容器的详细信息,比如我们可以查看所有设置的环境变量。
- 启动容器:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker run --name mynginx1 --rm -p 80:80 -e TEST=1 -d nginx:1.22.1
ad2d90c76b774f3f0d8d72bae8c4dee25d46c74dc5bfad3f3f8bcf3b7f93734a
- 查看容器信息:
[xiaomaker@xiaomaker-virtual-machine:docker]$ docker container inspect mynginx1
- 释放资源:
docker stop mynginx1
docker rm mynginx1
(3)执行单行命令:我们可以直接借助 docker 的容器环境执行一些命令,比如容器中有某个命令而宿主机上没有这个时候借助容器可以完成某些任务。
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run --rm -p 80:80 nginx:1.22.1 echo "Hello docker"
Hello docker
4.8 容器镜像的导入导出
(1)我们创建目录,并编辑一个自定义首页:
mkdir -p /data/myworkdir/container/
cd /data/myworkdir/container/
vi index.html
(2)首页输入以下内容:
<html>
<h1>Hello</h1>
</html>
(3)我们运行一个 nginx 镜像,然后通过 docker cp 修改首页:
docker run -d --name mynginx4 -p 80:80 nginx:1.22.1
docker cp /data/myworkdir/container/index.html
mynginx4:/usr/share/nginx/html/
(4)访问首页看到的内容如下:
(5)我们通过 docker export 保存镜像:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker export -o mynginx4.tar mynginx4
(6)我们通过 docker import 导入镜像:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker import mynginx4.tar mynginx:v0.4
sha256:d95c9d02716925e084774a15b812b3305da0826b3a0b97f6f0c063643d926811
(7)停止我们现在的容器,重新启动容器:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker stop mynginx4
mynginx4
(8)使用导出的镜像启动一个新的容器:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run -d --name mynginx5 -p 80:80 mynginx:v0.4 nginx -g "daemon off;"
d1f5c5990c95bf386bd9a70d391dfbc5b5ea53bd0cc03fb55f4a70369b418726
[xiaomaker@xiaomaker-virtual-machine:container]$ docker ps
如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似"docker: Error response from daemon: Container command not found or does not exist"的错误。我们必须指定启动命令。因为 export 丢失了元数据信息。
4.9 容器日志查看、资源查看
(1)资源查看:
- 启动一个 nginx:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run --name mynginx1 -d --rm -p 80:80 nginx:1.22.1
e4a283560e71e52579c0b19641f5ce7eff4d784603104d36a765804afb7086a8
- 查看全部日志:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker logs mynginx1
- 实时查看日志:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker logs -f mynginx1
- 刷新访问几次页面:
- 查看最新的 3 行日志:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker logs -f -n 3 mynginx1
- 停止容器释放资源:
docker stop mynginx1
(2)资源查看:
- 我们运行一个 nginx:
docker run -d --name mynginx5 -p 80:80 nginx:1.22.1
- 我们可以通过 docker top 查看容器中有哪些进程,添加 aux,可以看到占用的内存和 CPU 信息:
root@139-159-150-152:~# docker top mynginx5 aux
- 通过 docker stats 可以看到资源的实时占用变化:
root@139-159-150-152:~# docker stats
- 释放资源:
docker stop mynginx5
docker rm mynginx5
5. Mysql 容器化安装
(1)进入 mysql 的镜像网站,查找 mysql 的镜像。可以看到有这么多的 tag:
(2)我们选择使用最多的 5.7 版本,拉取镜像:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker pull mysql:5.7
(3)我们知道 msyql 的默认端口是 3306,而且有密码,查看官网的启动用例 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag 指定了 mysql 的密码信息:
#启动一个 msyql,并指定密码和端口开放
docker run --name mysql -e MYSQL_ROOT_PASSWORD=maxhouroot -p 8200:3306 -d mysql:5.7
(4)我们进入容器登录,可以看到我们已经可以正常登录 msyql 了:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker exec -it mysql bash
bash-4.2# mysql -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.41 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current
input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
(5)如果我们对外开放了 8200 端口,没有防火墙的话,我们可以通过 GUI 工具远程登录到界面上。以 mysql workbench 为例。
(6)释放空间:
docker stop mysql
docker rm mysql
6. Redis 容器化安装
(1)Redis的简介可以参考博客《Redis的认识》。
(2)下载 redis 镜像:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker pull redis:7.0
(3)启动 redis 容器:
docker run --name redis -p 8300:6379 -d redis:7.0
(4)进入容器,设置一个 key:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker exec -it redis bash
root@c0b3c4ae457e:/data# redis-cli
127.0.0.1:6379> set mykey 1
OK
127.0.0.1:6379> get mykey
"1"
127.0.0.1:6379>
(5)如果开通了防火墙,我们可以通过可视化工具连接上,可视化工具下载地址:https://gitee.com/qishibo/AnotherRedisDesktopManager/releases。
(6)配置链接:
(7)查看 key:
(8)退出容器,然后释放空间:
docker stop redis
docker rm redis
7. C++容器制作
7.1 源的介绍
(1)源就是来源。就是你安装软件时,程序从哪里获取软件包(安装程序在你的机器上,但需要安装的东西却在软件源服务器上)。
(2)源在 Ubuntu 下,它相当于软件库,需要什么软件,只要记得正确的软件名就可以用命令抄安装:其实你可以把他称为软件仓库。安装软件时,就是从仓库里面调取数据放在你的机器上。
sudo apt-get install 软件名
(3)例如:你要安装 gcc 软件,那么你就可以再终端中输入 sudo apt-get install gcc,这样就能帮你装好 gcc 软件,如果源里没有这个软件时,此命令就没法完成。
7.2 什么是镜像
(1)镜像(Mirroring)是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。常见的镜像文件格式有 ISO、 BIN、 IMG、 TAO、 DAO、 CIF、 FCD。
(2)所谓镜像文件其实和 ZIP 压缩包类似,它将特定的一系列文件按照一定的格式制作成单一的文件,以方便用户下载和使用,例如一个测试版的操作系统、游戏等。(安装过操作系统的人应该对 xxx.iso 不陌生)镜像文件不仅具有 ZIP 压缩包的“合成”功能,它最重要的特点是可以被特定的软件识别并可直接刻录到光盘上。
7.3 镜像源
(1)镜像源就是把官方的源做一个镜像,你可以在这下载软件。
- 比如 ubuntu 官方源在国外,下载软件可能会很慢,这时候就需要换成国内的镜像源。我们基于 ubuntu 来制作 C++容器,运行输出 HelloWorld可以把镜像源当做一个代理商,比如买车本来要去车厂,但是设置了一个个 4s 店以后,我去 4s 店就好了,不用跑到车厂。
(2)中科大源:https://mirrors.ustc.edu.cn/help/。
7.4 制作 c++容器
(1)下载 Ubuntu 镜像:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker pull ubuntu:22.04
(2)启动容器:
[xiaomaker@xiaomaker-virtual-machine:container]$ docker run --name mygcc -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)安装 gcc vim:
apt update
apt install gcc vim -y
(5)编辑代码:
root@50d527b8343e:/# mkdir src
root@50d527b8343e:/# cd src
root@50d527b8343e:/src# vim demo.c
#输入以下内容
#include <stdio.h>
int main()
{
printf("hello docker!\n");
return 0;
}
(6)编译代码:
root@50d527b8343e:/src# gcc demo.c -o demo
(7)在容器中运行:
root@50d527b8343e:/src# ./demo
hello docker!
(8)退出容器:
root@50d527b8343e:/src# exit
exit
(9)这个时候可以看到我们的容器已经退出了,如果想再次进入使用 docker restart 就可以恢复容器。
(10)清理容器释放空间:
docker stop mygcc
docker rm mygcc
8. 容器资源更新
(1)我们运行一个 nginx:
docker run -d --name mynginx5 -p 80:80 ngxin:1.22.1
(2)我们可以通过 docker top 查看容器中有哪些进程,添加 aux,可以看到占用的内存和 CPU 信息:
root@139-159-150-152:~# docker top mynginx5 aux
(3)通过 docker stats 可以看到资源的动态变化:
root@139-159-150-152:~# docker stats
(4)我们通过 docker update 更新 docker 的最大内存:
root@139-159-150-152:~# docker update -m 300m --memory-swap 600m mynginx5
mynginx5
(5)我们通过 docker stats 再次查看可以看到内存已经被限制到 300m 了:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM %
NET I/O BLOCK I/O PIDS
d1f5c5990c95 mynginx5 0.00% 2.648MiB / 300MiB 0.88%
7.06kB / 2.57kB 2.29MB / 4.1kB 2
(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:
docker update --cpu-period=100000 --cpu-quota=10000 mynginx5
(8)可以看到 cpu 已经只能到 10%左右了:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM %
NET I/O BLOCK I/O PIDS
d1f5c5990c95 mynginx5 9.80% 2.648MiB / 300MiB 0.88%
7.06kB / 2.57kB 2.29MB / 4.1kB 2
(9)停止容器,释放资源:
docker stop mynginx5
docker rm mynginx5
9. 常见问题总结
9.1 docker create、docker start和docker run 有什么区别?
- docker create 命令从 Docker 映像创建一个全新的容器。但是,它不会立即运行它。docker start 命令将启动任何已停止的容器。如果使用 docker create 命令创建容器,则可以使用此命令启动它。
- docker run 命令是创建和启动的组合,因为它创建了一个新容器并立即启动它。实际上,如果 docker run 命令在您的系统上找不到上述映像,它可以从 Docker Hub 中提取映像。
9.2 docker import 和 docker load 有什么区别?
(1)想要了解 docker load 与 docker import 命令的区别,还必须知道 docker save与 docker export 命令:
- docker save images_name:将一个镜像导出为文件,再使用 docker load 命
令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比 docker export 命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。 - docker export container_id:将一个容器导出为文件,再使用 docker
import 命令将容器导入成为一个新的镜像,但是相比 docker save 命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
(2)既可以使用 docker load 命令来导入镜像库存储文件到本地镜像库,也可以使用docker import 命令来导入一个容器快照到本地镜像库。
(3)两者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也会更大。
9.3 docker rm & docker rmi & docker prune 的差异?
- docker rm:删除一个或多个容器。
- docker rmi:删除一个或多个镜像。
- docker prune:用来删除不再使用的 docker 对象。